e65111a7f4
Permisos (superadmin, viewer, busqueda, tareas recurrentes), bootstrap atomico, revocacion de JWT por version de sesion (028), control optimista de edicion (029), logo sin SVG + CSP, ingesta endurecida, correos escapados, borradores, paginacion de proyectos, accesibilidad de dialogos/controles e i18n. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5.3 KiB
5.3 KiB
Sesión, retorno al contexto y borradores
Solución compartida para toda la app (frontend). Los proyectos y comentarios también verifican
la versión en el backend (migración 029_optimistic_versions.sql).
Piezas
| Archivo | Qué hace |
|---|---|
utils/jwt.js |
Lee exp y sub del JWT (sin verificar firma; eso lo hace el backend). |
context/auth-context.jsx |
Vigila el vencimiento: temporizador al instante exacto, chequeo cada 30 s y al volver a la pestaña/ventana (visibilitychange, focus, pageshow). El navegador congela temporizadores en segundo plano, por eso el chequeo al volver es el que manda. |
services/api.js |
Nunca envía una petición con token vencido: corta la sesión antes. Un 401 con token también corta. |
utils/session.js |
Al vencer guarda { userId, ruta completa } (plc_return_ctx, 24 h). Tras el login solo se usa si entra el mismo usuario; otro usuario la descarta. |
utils/drafts.js + hooks/useDraftForm.js |
Borradores por formulario (ver abajo). |
components/NavigationGuard.jsx |
Aviso al salir con cambios (useBlocker), advertencia nativa en F5/cierre, DraftMark, useGuardedClose. |
components/DraftNotice.jsx |
Aviso dentro del formulario: cambios recuperados / conflicto con el servidor. |
app/App.jsx |
Router de datos (createBrowserRouter, mismas rutas): requisito de useBlocker. |
Pestañas y vistas que viven en la URL (para volver exactamente ahí): proyecto ?tab=, actividad
abierta ?activity=&activityTab=, Organización ?tab=, Equipos ?tab=&device=&deviceTab=.
Comportamiento
- Vencimiento: se cierra la sesión al instante (aunque no haya peticiones) y aparece el login con el aviso "Tu sesión venció…". Al volver a entrar, el mismo usuario regresa a la misma ruta, pestaña y popup, con la edición reabierta y sus cambios. Salir con "Cerrar sesión" no guarda ruta de retorno.
- Borradores: clave
plc_draft:v1:<usuario>:<formulario>:<entidad>enlocalStorage, vigencia 7 días. Solo se guardan los campos permitidos de cada formulario (draftAllowedFields); el texto libre de notas, comentarios, descripciones y observaciones no se conserva. Sobreviven a cambiar de pestaña/menú, F5 y vencimiento. Se borran al guardar, descartar o cerrar sesión voluntariamente. Solo se restauran si el registro sigue en lo que el backend devuelve para ese usuario (si se borró o perdió acceso, no se abre nada). - Secretos: nunca se guardan campos cuyo nombre parezca contraseña/token/PIN, archivos ni campos fuera de la lista permitida. Al leer borradores antiguos se eliminan los campos excluidos.
- Marcas: campo modificado en rojo con el texto "· modificado"; pestaña, sección plegable, botón "Nuevo …", tarjeta (Notas) y menú lateral con punto rojo + texto para lector de pantalla.
- Salir con cambios (menú, pestaña, cerrar popup, plegar sección): diálogo Seguir editando / Dejar pendiente / Descartar cambios. Con "Dejar pendiente", al volver se reabre la edición con los valores recuperados. F5 o cerrar la pestaña: advertencia nativa del navegador.
- Integridad: los borradores no se guardan automáticamente en el backend; Guardar envía los campos del formulario con la versión leída. Si el registro cambió, se conserva el borrador y se pide recargar para revisar la versión actual. En Info de proyecto/actividad, Equipos, SMTP y Empresa además se consulta el servidor justo antes de guardar.
Formularios sin recuperación (a propósito)
| Formulario | Motivo |
|---|---|
| Contraseñas (todo el módulo, incluido PIN y grupos) | Los datos están protegidos por PIN y cifrados; guardarlos en el navegador saltaría esa protección. |
| Cambiar contraseña (menú del usuario) | Solo contiene secretos. |
| Login, registro, olvidé/restablecer clave, aceptar invitación, restablecer PIN | Pantallas públicas: no hay usuario autenticado para aislar el borrador y contienen claves/tokens. |
| Documentos (subir archivo), logo y nombre de Empresa | Archivos y texto libre no se guardan en el navegador. |
| Equipos → Agentes (token de instalación) | Token secreto; generar uno es una acción de un paso. |
| Mover actividad, agregar dependencia, compartir nota, compartir Equipos | Acciones de una sola elección, sin captura de datos: se repiten en un clic. |
| Clave y texto libre en "Nuevo usuario"; clave SMTP | Solo se recuperan rol/departamento; las claves y el texto libre se vuelven a escribir. |
| Apariencia, filtros, selector de tarjetas del Panel | Se aplican al instante; no queda nada pendiente. |
Límites conocidos
- Los borradores son de este navegador: no se sincronizan entre equipos.
- En un equipo compartido, los borradores de un usuario quedan en el navegador hasta guardarlos, descartarlos, cerrar sesión voluntariamente o que venzan (7 días). Tras vencimiento de sesión se conservan para permitir el retorno al contexto.
- Todos los formularios de edición de entidades, empresa y SMTP envían
editVersion; el backend rechaza con409una versión obsoleta. El borrador se conserva y el aviso pide revisar la versión actual. Miembros no edita una entidad mediante formulario: sus acciones aplican cambios puntuales de acceso. - Los popups son modales: con uno abierto no se puede usar el menú lateral; se sale cerrándolo (pasa por el mismo aviso) o con atrás del navegador.