From 3b92f47b54829e34fcee57acc068939698249aae Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Wed, 25 Mar 2026 16:14:26 -0500 Subject: [PATCH] =?UTF-8?q?feat:=20enlaces=20de=20formulario=20sin=20venci?= =?UTF-8?q?miento=20+=20PDF=20descargable=20sin=20sesi=C3=B3n=20v=C3=ADa?= =?UTF-8?q?=20token=20p=C3=BAblico?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/lab/send_formulario.php | 2 +- classes/lab/Formulario.php | 2 +- form_cliente.php | 8 ++-- ver_formulario_enviado.php | 78 +++++++++++++++++++++++++------------ 4 files changed, 60 insertions(+), 30 deletions(-) diff --git a/api/lab/send_formulario.php b/api/lab/send_formulario.php index 059d47c..4823c91 100644 --- a/api/lab/send_formulario.php +++ b/api/lab/send_formulario.php @@ -67,7 +67,7 @@ try { $nomForm = $plantilla['nombre']; $mensajeWa = "Hola $nomPac, le enviamos el formulario *\"$nomForm\"* para que lo complete y firme digitalmente.\n\n" . "👉 Accede aquí:\n$url\n\n" - . "El enlace expira en 7 días. Si tiene dudas contáctenos."; + . "Si tiene dudas contáctenos."; $telPac = $prefilled['__paciente']['telefono'] ?? ''; $waUrl = 'https://wa.me/' . preg_replace('/\D/', '', $telPac) diff --git a/classes/lab/Formulario.php b/classes/lab/Formulario.php index 8c15bb1..852fc2f 100644 --- a/classes/lab/Formulario.php +++ b/classes/lab/Formulario.php @@ -94,7 +94,7 @@ class Formulario { */ public function crearEnvio(array $datos, int $enviadoPor): int { $token = bin2hex(random_bytes(32)); - $expira = date('Y-m-d H:i:s', strtotime('+7 days')); + $expira = null; // El enlace no expira $id = $this->db->insert('lab_form_envios', [ 'formulario_id' => (int)$datos['formulario_id'], diff --git a/form_cliente.php b/form_cliente.php index 02f89a1..fd8270a 100644 --- a/form_cliente.php +++ b/form_cliente.php @@ -853,8 +853,8 @@ const formCliente = { show('yf-firma-thumb'); } - // Link al PDF (requiere sesión admin, se muestra de todas formas) - $('yf-pdf-btn').href = 'ver_formulario_enviado.php?id=' + env.id; + // Link al PDF (acceso público vía token, no requiere sesión) + $('yf-pdf-btn').href = 'ver_formulario_enviado.php?t=' + encodeURIComponent(TOKEN); if (env.hash_verificacion) { $('yf-hash').textContent = env.hash_verificacion; @@ -1080,10 +1080,10 @@ const formCliente = { $('success-hash').textContent = d.hash; show('success-hash-box'); } - // Link al PDF + // Link al PDF (acceso público vía token, no requiere sesión) if (d.envio_id) { const pdfBtn = $('success-pdf-btn'); - pdfBtn.href = 'ver_formulario_enviado.php?id=' + d.envio_id; + pdfBtn.href = 'ver_formulario_enviado.php?t=' + encodeURIComponent(TOKEN); show('success-pdf-row'); } show('success-screen'); diff --git a/ver_formulario_enviado.php b/ver_formulario_enviado.php index 4c8171c..1b55a16 100644 --- a/ver_formulario_enviado.php +++ b/ver_formulario_enviado.php @@ -1,39 +1,69 @@ fetch( - "SELECT e.*, f.nombre AS form_nombre, f.categoria, f.descripcion AS form_descripcion, - f.esquema, f.permite_firma, f.requiere_firma, - f.doc_encabezado, f.doc_subtitulo, f.doc_logo_base64, f.doc_color, f.doc_pie_pagina, - p.nombre_completo AS paciente_nombre, p.numero_documento, p.tipo_documento, - p.fecha_nacimiento, p.telefono AS paciente_telefono, p.eps, - u.full_name AS enviado_por_nombre, u.email AS enviado_por_email - FROM lab_form_envios e - JOIN lab_formularios f ON f.id = e.formulario_id - LEFT JOIN lab_pacientes p ON p.id = e.paciente_id - LEFT JOIN admin_users u ON u.id = e.enviado_por - WHERE e.id = ?", - [$id] -); +if ($modoPublico) { + // Acceso por token: solo si el formulario ya fue firmado/completado + if (!preg_match('/^[a-f0-9]{64}$/i', $tokenPublico)) { + http_response_code(400); die('Token inválido'); + } + $envio = $db->fetch( + "SELECT e.*, f.nombre AS form_nombre, f.categoria, f.descripcion AS form_descripcion, + f.esquema, f.permite_firma, f.requiere_firma, + f.doc_encabezado, f.doc_subtitulo, f.doc_logo_base64, f.doc_color, f.doc_pie_pagina, + p.nombre_completo AS paciente_nombre, p.numero_documento, p.tipo_documento, + p.fecha_nacimiento, p.telefono AS paciente_telefono, p.eps, + u.full_name AS enviado_por_nombre, u.email AS enviado_por_email + FROM lab_form_envios e + JOIN lab_formularios f ON f.id = e.formulario_id + LEFT JOIN lab_pacientes p ON p.id = e.paciente_id + LEFT JOIN admin_users u ON u.id = e.enviado_por + WHERE e.token = ?", + [$tokenPublico] + ); + if (!$envio) { http_response_code(404); die('Formulario no encontrado'); } + if (!in_array($envio['estado'], ['firmado', 'completado'])) { + http_response_code(403); die('El formulario aún no ha sido completado.'); + } +} else { + $id = (int)($_GET['id'] ?? 0); + if (!$id) { http_response_code(400); die('ID requerido'); } -if (!$envio) { http_response_code(404); die('Formulario no encontrado'); } + $envio = $db->fetch( + "SELECT e.*, f.nombre AS form_nombre, f.categoria, f.descripcion AS form_descripcion, + f.esquema, f.permite_firma, f.requiere_firma, + f.doc_encabezado, f.doc_subtitulo, f.doc_logo_base64, f.doc_color, f.doc_pie_pagina, + p.nombre_completo AS paciente_nombre, p.numero_documento, p.tipo_documento, + p.fecha_nacimiento, p.telefono AS paciente_telefono, p.eps, + u.full_name AS enviado_por_nombre, u.email AS enviado_por_email + FROM lab_form_envios e + JOIN lab_formularios f ON f.id = e.formulario_id + LEFT JOIN lab_pacientes p ON p.id = e.paciente_id + LEFT JOIN admin_users u ON u.id = e.enviado_por + WHERE e.id = ?", + [$id] + ); + if (!$envio) { http_response_code(404); die('Formulario no encontrado'); } -// Enfermero solo puede ver sus propios envíos -if (isEnfermero()) { - $uid = (int)($_SESSION['admin_user']['id'] ?? 0); - if ($envio['enviado_por'] != $uid) { http_response_code(403); die('Sin acceso'); } + // Enfermero solo puede ver sus propios envíos + if (isEnfermero()) { + $uid = (int)($_SESSION['admin_user']['id'] ?? 0); + if ($envio['enviado_por'] != $uid) { http_response_code(403); die('Sin acceso'); } + } } // ── Config global del lab ─────────────────────────────────────────────