Files
notas-api/docs/API.md
T
Marcos 776ed86742
Despliegue Automático / desplegar (push) Successful in 1m12s
Add logoutDevice functionality to manage device-specific logouts
2026-09-07 17:13:03 +02:00

6.7 KiB

Aquí tienes la documentación completa generada en formato README.md a partir de la arquitectura y el código de tu API.


Documentación de la API: Notas Encriptadas (E2EE)

Esta API proporciona el backend para una aplicación de notas con sincronización Offline-First y Cifrado de Extremo a Extremo (E2EE). Está construida sobre Node.js con Express y utiliza PostgreSQL (vía Sequelize) como base de datos.

🏗 Arquitectura y Flujo de Datos

El sistema sigue un patrón estructurado en capas para separar responsabilidades:

  1. Punto de Entrada e Inicialización: El archivo app.js inicializa Express, habilita CORS y permite payloads JSON de hasta 50MB. El archivo initDB.js se encarga de sincronizar los modelos con la base de datos PostgreSQL utilizando Sequelize.

  2. Enrutamiento Principal (index.js): Todo el tráfico entra por /api. De ahí, el router principal distribuye las peticiones hacia /auth (autenticación), /user (datos del usuario) y / (sincronización).

  3. Controladores (*Controller.js): Son la capa de seguridad y transporte. Validan que las peticiones vengan con un JWT válido en las cabeceras (Access Token), extraen el userId y envían los parámetros limpios a los servicios.

  4. Servicios (*Service.js): Contienen toda la lógica de negocio profunda. Manejan la creación de tokens, el hasheo de contraseñas, las transacciones SQL y la lógica de resolución de conflictos durante la sincronización.

  5. Modelos (.js): Definen las tablas y relaciones estructurales en la base de datos.


🗄 Modelos de Base de Datos y Relaciones

El esquema de la base de datos se distribuye en cuatro entidades principales interconectadas:

  • User (User.js): Almacena el email y password (hasheado con bcrypt) del usuario. También guarda la encrypted_master_key, que es la llave maestra para desencriptar las notas, pero cifrada con la contraseña del usuario para asegurar el E2EE. Un usuario tiene muchas Notas, Categorías y RefreshTokens.

  • Note (Note.js): Guarda los datos cifrados de cada nota (title, body), su orden (position), versión en el servidor (serverVersion) y estados de borrado (delete, permanentDelete).

  • Category (Category.js): Guarda información visual (colorValue, iconCodePoint) y el nombre cifrado (encrypted_name) de las categorías.

  • Relación Nota-Categoría: Las Notas y las Categorías tienen una relación de Muchos a Muchos (M:N) a través de una tabla intermedia llamada NoteCategories.

  • RefreshToken (RefreshToken.js): Gestiona las sesiones multidispositivo. Guarda un token largo, seguro y único asociado al deviceName del usuario. Si el usuario se elimina, sus tokens se borran en cascada.


🚀 Endpoints de la API

1. Autenticación (/api/auth)

Estos endpoints gestionan el registro, inicio de sesión y ciclo de vida de los tokens. El sistema usa un Access Token de corta duración (15 min) y un Refresh Token persistente en base de datos.

  • Registro de Usuario

  • Ruta: POST /api/auth/register

  • Body: { "email": "...", "password": "...", "encrypted_master_key": "...", "deviceName": "..." }

  • Descripción: Comprueba que el usuario no exista, hashea su contraseña, crea la cuenta y automáticamente inicia sesión, devolviendo ambos tokens (Access y Refresh) y la llave maestra.

  • Inicio de Sesión

  • Ruta: POST /api/auth/login

  • Body: { "email": "...", "password": "...", "deviceName": "..." }

  • Descripción: Verifica credenciales y crea una nueva sesión para el dispositivo (registrando un nuevo Refresh Token en DB). Retorna los tokens y la encrypted_master_key.

  • Refrescar Token

  • Ruta: POST /api/auth/refresh

  • Body: { "refresh_token": "..." }

  • Descripción: Intercambia un Refresh Token válido por un nuevo Access Token limpio de 15 minutos.

  • Cerrar Sesión Local

  • Ruta: POST /api/auth/logout

  • Body: { "refresh_token": "..." }

  • Descripción: Borra el Refresh Token proporcionado de la base de datos, revocando el acceso a ese dispositivo específico.

  • Borrado Total de Cuenta (Danger Zone)

  • Ruta: DELETE /api/auth/delete-all-data

  • Headers: Authorization: Bearer <access_token>

  • Descripción: Mediante una transacción de base de datos, borra irremediablemente todas las notas, categorías y sesiones (tokens) asociadas al usuario actual.

  • Listar Dispositivos Activos

  • Ruta: GET /api/auth/getSessionsInfo

  • Headers: Authorization: Bearer <access_token>

  • Descripción: Devuelve un listado de todos los dispositivos (deviceName), fechas de creación y los IDs de los Refresh Tokens asociados al usuario.

2. Estadísticas de Usuario (/api/user)

  • Obtener Estadísticas

  • Ruta: GET /api/user/stats

  • Headers: Authorization: Bearer <access_token>

  • Descripción: Descarga parcialmente las notas y categorías de la base de datos (solo los campos pesados como títulos y cuerpos) para calcular el peso en bytes (RAM-friendly) del almacenamiento en la nube del usuario. Devuelve totales formateados (KB/MB).

3. Sincronización Offline-First (/api/sync)

Este endpoint único procesa de forma bidireccional los cambios ocurridos tanto en la app local como en la base de datos del servidor.

  • Endpoint de Sincronización

  • Ruta: POST /api/sync

  • Headers: Authorization: Bearer <access_token>

  • Body:

{
  "lastSyncAt": "ISO String",
  "changes": {
    "categories": [ ... ],
    "notes": [ ... ]
  }
}

  • Descripción y Flujo de Resolución:
  1. Envuelve todo en una Transacción SQL para garantizar que o se guarda todo o no se guarda nada en caso de error.

  2. Recorre las categories entrantes. Si el id no existe, lo crea. Si existe, compara la serverVersion. Si la versión enviada coincide con la del servidor, actualiza los datos e incrementa la versión en el servidor. Si el servidor tiene una versión superior (conflicto), ignora el cambio del cliente y anota el ID para mandárselo de vuelta.

  3. Repite exactamente el mismo proceso de validación transaccional e inserción de datos para las notes, actualizando también la tabla intermedia de categorías mediante el array categoryIds entrante.

  4. Consulta a la base de datos cualquier nota o categoría cuyo updatedAt sea mayor al lastSyncAt proporcionado por el cliente, además de sumar los registros que hayan sufrido un conflicto de versión en los pasos anteriores.

  5. Devuelve al cliente un objeto estructurado con las notas y categorías actualizadas del servidor y el nuevo serverTimestamp (momento exacto en el que acabó la sincronización).