From 1f2198225c5e18d75f58df4c655685b7043b3a86 Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Wed, 8 Jul 2026 08:53:42 -0500 Subject: [PATCH] fix(turnero): IP real con X-Forwarded-For; chat back solo para recepcionista MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - App.php: clientIp() público resuelve X-Forwarded-For/X-Real-IP - module.php: usa el mismo IP resolution en sidebar de recepcionista - chat.php: botón Menú regresa al desk solo si rol=recepcionista con IP registrada; bacteriólogo no aplica lógica de IP en este flujo Co-Authored-By: Claude Sonnet 4.6 --- core/App.php | 11 +++++++++-- modules/turnero/module.php | 5 +++-- modules/turnero/views/chat.php | 31 +++++++++++++++++-------------- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/core/App.php b/core/App.php index 31ccf29..edb12e2 100644 --- a/core/App.php +++ b/core/App.php @@ -125,6 +125,13 @@ class App // ─── Helpers de rol ───────────────────────────────────────────────────── + /** IP real del cliente, soporta proxy con X-Forwarded-For. */ + public static function clientIp(): string + { + $raw = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR'] ?? ''; + return trim(explode(',', $raw)[0]); + } + /** * Devuelve el lugar_id de recepción asignado a la IP del cliente, o null si no está registrada. */ @@ -137,7 +144,7 @@ class App JOIN turnero_lugares l ON l.id = d.lugar_id WHERE d.ip = ? AND d.activo = 1 AND l.tipo = 'recepcion' LIMIT 1" ); - $st->execute([$_SERVER['REMOTE_ADDR'] ?? '']); + $st->execute([self::clientIp()]); $id = $st->fetchColumn(); return $id ? (int)$id : null; } catch (\Throwable $_) { @@ -155,7 +162,7 @@ class App $base = '/erp.php?m=turnero&v=lugar&lugar_id='; try { $pdo = Database::getInstance()->getConnection(); - $ip = $_SERVER['REMOTE_ADDR'] ?? ''; + $ip = self::clientIp(); // ¿IP registrada? $dev = $pdo->prepare( "SELECT lugar_id FROM turnero_dispositivos WHERE ip = ? AND activo = 1 LIMIT 1" diff --git a/modules/turnero/module.php b/modules/turnero/module.php index 06e2e28..44bbe45 100644 --- a/modules/turnero/module.php +++ b/modules/turnero/module.php @@ -9,6 +9,7 @@ $_trAdminRoles = ['superadmin', 'admin', 'supervisor']; $_trIsAdmin = in_array($_trRole, $_trAdminRoles, true); $_trIsRecep = $_trRole === 'recepcionista'; $_trIsBacte = $_trRole === 'bacteriologo'; +$_trClientIp = trim(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR'] ?? '')[0]); try { $_trPdo = Database::getInstance()->getConnection(); @@ -41,7 +42,7 @@ if ($_trIsRecep) { JOIN turnero_lugares l ON l.id = d.lugar_id WHERE d.ip = ? AND d.activo = 1 AND l.tipo = 'recepcion' LIMIT 1" ); - $_trRecepIpRow->execute([$_SERVER['REMOTE_ADDR'] ?? '']); + $_trRecepIpRow->execute([$_trClientIp]); $_trRecepIpDesk = $_trRecepIpRow->fetchColumn() ?: null; } catch (\Throwable $_) {} @@ -77,7 +78,7 @@ if ($_trIsRecep) { $_trIpRow = $_trPdo->prepare( "SELECT lugar_id FROM turnero_dispositivos WHERE ip = ? AND activo = 1 LIMIT 1" ); - $_trIpRow->execute([$_SERVER['REMOTE_ADDR'] ?? '']); + $_trIpRow->execute([$_trClientIp]); $_trIpLugar = $_trIpRow->fetchColumn() ?: null; } catch (\Throwable $_) {} diff --git a/modules/turnero/views/chat.php b/modules/turnero/views/chat.php index 0497839..ffb80d9 100644 --- a/modules/turnero/views/chat.php +++ b/modules/turnero/views/chat.php @@ -10,21 +10,24 @@ if (!isUserLoggedIn()) { header('Location: ' . BASE_URL . 'login.php'); exit; } $turneroPhoneId = getConfigFromDB('whatsapp_phone_number_id_turnero', ''); -// Determinar URL de regreso según IP del cliente +// URL de regreso: recepcionista con IP registrada → su desk; resto → dashboard $_chatBackUrl = BASE_URL . 'erp.php?m=turnero&v=dashboard'; -try { - $pdo = Database::getInstance()->getConnection(); - $st = $pdo->prepare( - "SELECT d.lugar_id FROM turnero_dispositivos d - JOIN turnero_lugares l ON l.id = d.lugar_id - WHERE d.ip = ? AND d.activo = 1 AND l.tipo = 'recepcion' LIMIT 1" - ); - $st->execute([$_SERVER['REMOTE_ADDR'] ?? '']); - $deskId = $st->fetchColumn(); - if ($deskId) { - $_chatBackUrl = BASE_URL . 'erp.php?m=turnero&v=recepcion&desk_id=' . (int)$deskId; - } -} catch (\Throwable $_) {} +if (($_SESSION['admin_user']['role'] ?? '') === 'recepcionista') { + try { + $pdo = Database::getInstance()->getConnection(); + $chatIp = trim(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR'] ?? '')[0]); + $st = $pdo->prepare( + "SELECT d.lugar_id FROM turnero_dispositivos d + JOIN turnero_lugares l ON l.id = d.lugar_id + WHERE d.ip = ? AND d.activo = 1 AND l.tipo = 'recepcion' LIMIT 1" + ); + $st->execute([$chatIp]); + $lugId = $st->fetchColumn(); + if ($lugId) { + $_chatBackUrl = BASE_URL . 'erp.php?m=turnero&v=recepcion&desk_id=' . (int)$lugId; + } + } catch (\Throwable $_) {} +} ?>