You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ADN-DMR-Peer-Server/docs/es/monitor/self-service.md

6.9 KiB

Self-service

Self-service permite al dueño de un hotspot iniciar sesión en el panel, editar las opciones de su dispositivo (listas estáticas de TG, reflector por defecto, temporizador, idioma, etc.) y que esas opciones se envíen al ADN DMR Peer Server sin editar YAML a mano en el servidor.

Intervienen cuatro piezas: MySQL (tabla Clients), API del monitor (FastAPI, sesión + REST), React (página /self-service) y el proxy hotspot integrado en adn-server (RPTO periódico al master). El peer server es quien aplica al final RPTO / OPTIONS al bridge en ejecución y al comportamiento del hotspot.


Requisitos previos

  1. Bloque SELF_SERVICE en adn-monitor.yaml con credenciales MySQL válidas y parámetros PBKDF2 alineados con tu herramienta de contraseñas (misma sal/iteraciones que hotspot_proxy_self_service.py cuando se use).
  2. DASHBOARD.SELF_SERVICE: true para que la UI muestre la entrada Self-service (y monitor.py exponga /api/self-service/* cuando la BD conecta).
  3. Tabla Clients con filas: callsign, int_id (ID DMR), psswd (hex PBKDF2-SHA256), options (línea KEY=value separada por ;), logged_in, host, modified, etc. (ver esquema / migraciones en el repo adn-monitor).
  4. El tráfico del hotspot debe pasar por el proxy si dependes de modified y del envío RPTO (ver flujo abajo).

Autenticación

Endpoint Uso
POST /api/auth/login Cuerpo: callsign, password. Verifica hash PBKDF2 contra Clients.psswd en filas con logged_in = 1. Éxito: cookie de sesión con user_id, int_ids (todos los DMR ID de ese indicativo).
GET /api/auth/login-by-ip Opcional: una coincidencia de usuario por Clients.host = IP del cliente (misma forma de sesión).
POST /api/auth/logout Cierra sesión.
GET /api/auth/me Devuelve { callsign, int_ids, selected_int_id } para React.

La sesión se prolonga con actividad (SelfServiceController usa un timeout largo de inactividad).


API de dispositivo (tras login)

Método Ruta Uso
GET /api/self-service/device?int_id= Carga fila Clients para ese int_id (debe estar en int_ids de sesión). JSON: int_id, callsign, mode, options parseadas en listas TS1/TS2, DIAL, VOICE, LANG, SINGLE, TIMER.
POST /api/self-service/device/options Cuerpo: int_id, cadena options (línea Homebrew OPTIONS). Debe terminar en ;. Longitud máx. 4096. Actualiza BD: Clients.options, modified = 1.
GET /api/self-service/device/modified?int_id= Devuelve **`{ modified: 0
POST /api/self-service/device/select Cuerpo: int_id — fija selected_int_id en sesión si el usuario tiene varios dispositivos.

Flujo extremo a extremo (cómo llegan las opciones al hotspot)

sequenceDiagram
  participant UI as React /self-service
  participant API as monitor FastAPI
  participant DB as MySQL Clients
  participant SRV as adn-server PROXY
  participant HS as Hotspot

  UI->>API: POST /api/self-service/device/options
  API->>DB: UPDATE options, modified = 1
  Note over SRV: bucle send_opts ~cada 10 s
  SRV->>DB: lee filas con modified = 1
  SRV->>SRV: RPTO en pata MASTER
  SRV->>HS: OPTIONS vía HBP
  SRV->>DB: limpia modified
  1. El usuario guarda opciones en la web → la API del monitor escribe Clients.options y modified = 1.
  2. El proxy hotspot ejecuta send_opts en bucle (~cada 10 s). Para filas con modified = 1, lee opciones de la BD, envía RPTO al peer server en (MASTER, puerto_destino_asignado), luego limpia modified en la BD.
  3. El ADN DMR Peer Server recibe RPTO en la pata MASTER y actualiza su estado OPTIONS / bridge (mismo camino que un refresco normal de registro del hotspot).
  4. El servidor envía la señalización adecuada al hotspot para que TG estáticos / reflector / temporizador surtan efecto sin reinicio completo del hotspot (el comportamiento coincide con el flujo HBP OPTIONS del servidor).

Importante: el proxy envía RPTO solo al master, no al hotspot directamente. Si el proxy no está en el camino, necesitas otro mecanismo que aplique OPTIONS o ejecutas el servidor sin este camino proxy.

Prerrequisito: el hotspot debe enviar PASS= en su línea OPTIONS para login por contraseña y sincronización bidireccional con la BD. Si el hotspot envía contenido explícito (TGs, SINGLE, etc.) sin PASS=, el servidor toma las opciones directamente de esa línea y la fila de la BD se ignora. Si el hotspot no envía RPTO (el timer expira) o envía OPTIONS vacío, el servidor hace fallback a la base de datos. Ver Proxy hotspot — comportamiento de la línea OPTIONS.


Reconciliación de logged_in

El flag logged_in controla tanto el login por contraseña como por IP: sólo las filas con logged_in = 1 pueden autenticarse en el dashboard. El peer server mantiene este flag preciso reconciliándolo contra los peers realmente conectados cada 120 s (el bucle lst_seen):

  • Los peers actualmente conectados al MASTER inject-only quedan logged_in = 1.
  • Las demás filas quedan logged_in = 0.
  • El bucle arranca con now=True, de modo que el primer tick al arrancar limpia todos los flags obsoletos inmediatamente — tras un reinicio del servidor, los hotspots que no se reconectaron no pueden autenticarse vía login-by-IP.

Esto reemplazó el clean_tbl horario del legado (barrido de 24 h de inactividad), que dejaba logged_in = 1 en peers ya desconectados tras un reinicio.


Hash de contraseñas

AuthenticateUser usa:

hash_pbkdf2('sha256', password, PBKDF2_SALT, PBKDF2_ITERATIONS)

almacenado en hex en Clients.psswd. Los mismos parámetros deben usarse donde se registran contraseñas (p. ej. hotspot_proxy_self_service.py en el repo de tooling / adn-dmr-server).


Interfaz

  • Ruta /self-service en React (SelfService.tsx): carga /api/auth/me, luego detalle del dispositivo para selected_int_id, edita la cadena de opciones, guarda.
  • Un enlace externo SelfCare (p. ej. selfcare.adn.systems) puede aparecer en el nav como producto aparte — no es el mismo que este self-service local.

Ver también

Powered by TurnKey Linux.