fix(login): el login ahora respeta el empleado seleccionado
- auth_bp.py: login acepta employee_id y verifica el PIN solo de ese empleado. Fallback legacy se mantiene para clientes antiguos. - login.html: guarda el id del empleado seleccionado y lo envia en la peticion. - Se agrega cookie pos_role en el login inline del HTML. Esto corrige el problema donde seleccionar cualquier usuario accedia siempre al mismo empleado (el primero con el mismo PIN). Tests: 35 passed
This commit is contained in:
@@ -59,6 +59,7 @@ def login_pin():
|
||||
# Subdomain-resolved tenant takes priority over body param
|
||||
tenant_id = getattr(g, 'tenant_id', None) or data.get('tenant_id')
|
||||
pin = data.get('pin', '')
|
||||
employee_id = data.get('employee_id')
|
||||
device_id = data.get('device_id', request.headers.get('X-Device-Id', 'unknown'))
|
||||
# Optional: branch_id from the device for PIN search optimization
|
||||
device_branch_id = data.get('branch_id')
|
||||
@@ -89,39 +90,53 @@ def login_pin():
|
||||
|
||||
matched_employee = None
|
||||
|
||||
if device_branch_id:
|
||||
# Try branch employees first (fast path for known devices)
|
||||
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.is_active = true AND e.pin IS NOT NULL AND e.branch_id = %s
|
||||
""", (device_branch_id,))
|
||||
for emp in cur.fetchall():
|
||||
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
|
||||
}
|
||||
break
|
||||
|
||||
if not matched_employee:
|
||||
# Fallback: check ALL active employees (covers owners, admins, roaming staff)
|
||||
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
|
||||
""")
|
||||
employees = cur.fetchall()
|
||||
# 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
|
||||
|
||||
for emp in employees:
|
||||
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
|
||||
|
||||
if not matched_employee:
|
||||
_record_attempt(device_id, False)
|
||||
|
||||
Reference in New Issue
Block a user