Files
linkedsign/backend/README.md
T

4.4 KiB

LinkedSign Backend

Backend REST de LinkedSign construido con Node.js + Express. Esta API atiende tanto a la aplicación web como a la app Android.

Stack

  • Node.js + Express
  • MariaDB
  • JWT access + refresh
  • helmet, cors, morgan
  • multer para archivos
  • bcrypt para contraseñas

Ejecutar

cd /home/mgonzalez/desarrollo/react/linkedsign/backend
npm install
npm run dev

Producción:

npm start

Variables principales

Usa .env.example como base.

Variables importantes:

PORT=4000
CORS_ORIGIN=http://192.168.222.40:5173
FRONTEND_URL=http://192.168.222.40:5173
MAIL_HOST=
MAIL_PORT=587
MAIL_SECURE=false
MAIL_USER=
MAIL_PASS=
MAIL_FROM=
MAIL_TLS_REJECT_UNAUTHORIZED=false
JWT_ACCESS_SECRET=
JWT_REFRESH_SECRET=
DB_HOST=
DB_PORT=3306
DB_USER=
DB_PASSWORD=
DB_NAME=

Flujo actual

  • registro por correo y contraseña segura
  • validación del correo por enlace
  • reenvío automático del enlace si el usuario intenta entrar sin validar
  • cambio de contraseña con confirmación por correo
  • gestión de documentos PDF originales
  • gestión de certificados P12/PFX
  • firmado visible y criptográfico
  • verificación pública por QR
  • auditoría de eventos
  • preferencias visuales de firma por usuario

Endpoints principales

Auth

POST /auth/register

Registra usuario y envía correo de validación.

curl -X POST http://192.168.222.40:4000/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "email": "usuario@correo.com",
    "password": "ClaveSegura#2026"
  }'

POST /auth/login

Inicia sesión. Si el correo no está validado, reenvía el enlace.

curl -X POST http://192.168.222.40:4000/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "usuario@correo.com",
    "password": "ClaveSegura#2026"
  }'

GET /auth/verify/:token

Confirma el correo de la cuenta.

PATCH /auth/change-password

Solicita cambio de contraseña para usuario autenticado. Envía correo con enlace de confirmación.

GET /auth/confirm-password-change/:token

Aplica el cambio de contraseña desde el enlace enviado por correo.

GET /auth/me

Devuelve usuario autenticado y preferencias visuales de firma.

Documents

POST /documents

Sube un PDF original.

curl -X POST http://192.168.222.40:4000/documents \
  -H "Authorization: Bearer TU_ACCESS_TOKEN" \
  -F "file=@/ruta/documento.pdf"

GET /documents

Lista documentos originales del usuario.

GET /documents/:id/download

Descarga un documento original.

Certificates

POST /certificates

Sube un certificado .p12 o .pfx.

curl -X POST http://192.168.222.40:4000/certificates \
  -H "Authorization: Bearer TU_ACCESS_TOKEN" \
  -F "file=@/ruta/certificado.p12" \
  -F "alias=MPGH 2026" \
  -F "password=TuClaveP12"

GET /certificates

Lista certificados del usuario, incluyendo datos de cadena embebida.

Signatures

POST /signatures/sign

Firma un documento con un certificado del usuario.

curl -X POST http://192.168.222.40:4000/signatures/sign \
  -H "Authorization: Bearer TU_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "documentId": 1,
    "certificateId": 2,
    "certPassword": "TuClaveP12",
    "reason": "Firmado digitalmente",
    "location": "Guayaquil",
    "page": 0,
    "rect": null,
    "signatureStyle": "qr",
    "qrPosition": "right",
    "qrBackground": "transparent",
    "qrBorder": "none"
  }'

GET /signatures/mine

Lista PDFs firmados generados.

GET /signatures/:id/download

Descarga un PDF firmado.

GET /signatures/verify/:code

Verificación pública usada por el QR.

Users

PATCH /users/me/preferences/signature-appearance

Guarda la configuración visual de firma del usuario.

Respuesta estándar

{
  "success": true,
  "data": {},
  "error": null
}

Notas operativas

  • Si SMTP no está configurado, el flujo de correo no quedará completo.
  • Si el servidor SMTP usa un certificado interno o vencido, puede ser necesario:
    • MAIL_TLS_REJECT_UNAUTHORIZED=false
  • La verificación QR de LinkedSign valida integridad y registro interno de la firma.
  • La app Android en android/README.md consume esta misma API y sincroniza su cache local solo cuando el usuario lo solicita.