From 76dfa2adfff37433a8fa7e6b6cec2c5b6a3084f0 Mon Sep 17 00:00:00 2001 From: consultoria-as Date: Tue, 30 Jun 2026 17:23:39 +0000 Subject: [PATCH] fix(login): elimina fallback legacy y exige employee_id + PIN correcto - auth_bp.py: ahora login requiere employee_id. Si el PIN no coincide con el empleado seleccionado, devuelve 401. Ya no escanea todos los empleados ni permite entrar como otro usuario con el mismo PIN. Esto evita que al elegir un usuario se entre como mecanico solo porque comparten PIN. --- pos/blueprints/auth_bp.py | 65 ++++++++++++--------------------------- 1 file changed, 19 insertions(+), 46 deletions(-) diff --git a/pos/blueprints/auth_bp.py b/pos/blueprints/auth_bp.py index 87a1ca5..8b44721 100644 --- a/pos/blueprints/auth_bp.py +++ b/pos/blueprints/auth_bp.py @@ -90,53 +90,26 @@ def login_pin(): matched_employee = None - if employee_id: - # Secure flow: user selected an employee, verify only that PIN. - cur.execute(""" - SELECT e.id, e.name, e.pin, e.role, e.branch_id, e.max_discount_pct - FROM employees e - WHERE e.id = %s AND e.is_active = true AND e.pin IS NOT NULL - """, (employee_id,)) - emp = cur.fetchone() - if emp: - emp_id, emp_name, emp_pin_hash, emp_role, emp_branch, emp_discount = emp - if emp_pin_hash and bcrypt.checkpw(pin.encode(), emp_pin_hash.encode()): - matched_employee = { - 'id': emp_id, 'name': emp_name, 'role': emp_role, - 'branch_id': emp_branch, 'max_discount_pct': float(emp_discount) if emp_discount else 0 - } + if not employee_id: + _record_attempt(device_id, False) + cur.close() + conn.close() + return jsonify({'error': 'Empleado no seleccionado'}), 400 - if not matched_employee: - # Legacy fallback: scan active employees (kept for old clients without employee_id) - if device_branch_id: - cur.execute(""" - SELECT e.id, e.name, e.pin, e.role, e.branch_id, e.max_discount_pct - FROM employees e - WHERE e.is_active = true AND e.pin IS NOT NULL AND e.branch_id = %s - """, (device_branch_id,)) - for emp in cur.fetchall(): - emp_id, emp_name, emp_pin_hash, emp_role, emp_branch, emp_discount = emp - if emp_pin_hash and bcrypt.checkpw(pin.encode(), emp_pin_hash.encode()): - matched_employee = { - 'id': emp_id, 'name': emp_name, 'role': emp_role, - 'branch_id': emp_branch, 'max_discount_pct': float(emp_discount) if emp_discount else 0 - } - break - - if not matched_employee: - cur.execute(""" - SELECT e.id, e.name, e.pin, e.role, e.branch_id, e.max_discount_pct - FROM employees e - WHERE e.is_active = true AND e.pin IS NOT NULL - """) - for emp in cur.fetchall(): - emp_id, emp_name, emp_pin_hash, emp_role, emp_branch, emp_discount = emp - if emp_pin_hash and bcrypt.checkpw(pin.encode(), emp_pin_hash.encode()): - matched_employee = { - 'id': emp_id, 'name': emp_name, 'role': emp_role, - 'branch_id': emp_branch, 'max_discount_pct': float(emp_discount) if emp_discount else 0 - } - break + # Verify the PIN only for the selected employee. + cur.execute(""" + SELECT e.id, e.name, e.pin, e.role, e.branch_id, e.max_discount_pct + FROM employees e + WHERE e.id = %s AND e.is_active = true AND e.pin IS NOT NULL + """, (employee_id,)) + emp = cur.fetchone() + if emp: + emp_id, emp_name, emp_pin_hash, emp_role, emp_branch, emp_discount = emp + if emp_pin_hash and bcrypt.checkpw(pin.encode(), emp_pin_hash.encode()): + matched_employee = { + 'id': emp_id, 'name': emp_name, 'role': emp_role, + 'branch_id': emp_branch, 'max_discount_pct': float(emp_discount) if emp_discount else 0 + } if not matched_employee: _record_attempt(device_id, False)