ABIANAPP_NODE_PRODUCCION/README.md

6.6 KiB
Raw Blame History

tablas que tenemos que actualizar en la base de datos de producción

c_cambios_estado c_cambios_estado_eliminados c_viajes_puntos c_viajes_puntos_tracking c_viajes_incidencias v_viajes_incidencias

trg_c_viajes_puntos_tracking_au trg_c_cambios_estado_bd

Node Gestión API Firebase Admin

Este proyecto incluye un script de prueba para enviar notificaciones con Firebase Admin SDK.

Configuración segura de credenciales

La opción más segura para persistir GOOGLE_APPLICATION_CREDENTIALS en Linux es usar un archivo de entorno protegido y cargarlo desde tu gestor de procesos (systemd o PM2). Ejemplo con systemd:

  1. Crea un archivo de entorno fuera del repo, con permisos restrictivos:
# /etc/node-gestion-api.env
GOOGLE_APPLICATION_CREDENTIALS=/var/www/node.gestion.abianservice.com/notabser-firebase-adminsdk-fbsvc-bf88758663.json
FIREBASE_DATABASE_URL=https://<DATABASE_NAME>.firebaseio.com
sudo chown root:root /etc/node-gestion-api.env
sudo chmod 600 /etc/node-gestion-api.env
  1. En tu servicio systemd:
EnvironmentFile=/etc/node-gestion-api.env

Si trabajas localmente, puedes usar .env (ya soportado por dotenv) y mantenerlo fuera del control de versiones.

Script de prueba (FCM)

El script está en src/scripts/sendTestNotification.js.

Variables esperadas (pueden ir en .env):

  • GOOGLE_APPLICATION_CREDENTIALS (ruta absoluta)
  • FIREBASE_DATABASE_URL (opcional)
  • FCM_TEST_TOKEN
  • FCM_TEST_TITLE (opcional)
  • FCM_TEST_BODY (opcional)

Uso rápido

Ejemplo de envío real:

node src/scripts/sendTestNotification.js --token "<FCM_DEVICE_TOKEN>" --title "Hola" --body "Prueba"

Ejemplo de validación sin enviar (dry run):

node src/scripts/sendTestNotification.js --token "<FCM_DEVICE_TOKEN>" --dry-run

Self-test de inicialización (no envía):

node src/scripts/sendTestNotification.js --self-test

También puedes usar el script de npm:

npm run notify:test -- --token "<FCM_DEVICE_TOKEN>" --dry-run

Fotos de estado de viaje (almacenamiento temporal dual)

Para POST /api/trips/:id/status, las fotos pueden guardarse en local y replicarse por SFTP en paralelo.

  • TRIP_STATUS_UPLOAD_DIR (opcional): base local. Admite una ruta o varias rutas candidatas separadas por ;; si son relativas, se resuelven desde la raiz del proyecto Node.
    Default: uploads/trips/status dentro del proyecto.
  • TRIP_STATUS_PHOTO_STORAGE_MODE (opcional): local o dual.
    Default: local.
  • TRIP_STATUS_SFTP_HOST: host SFTP remoto.
  • TRIP_STATUS_SFTP_PORT (opcional): puerto SFTP.
    Default: 22.
  • TRIP_STATUS_SFTP_USERNAME: usuario SFTP.
  • TRIP_STATUS_SFTP_PASSWORD: password SFTP.
  • TRIP_STATUS_SFTP_REMOTE_BASE_DIR: directorio base remoto.

Ejemplo de modo temporal dual:

TRIP_STATUS_PHOTO_STORAGE_MODE=dual
TRIP_STATUS_SFTP_HOST=localhost
TRIP_STATUS_SFTP_PORT=22
TRIP_STATUS_SFTP_USERNAME=ssh_fotos_estado
TRIP_STATUS_SFTP_PASSWORD=********
TRIP_STATUS_SFTP_REMOTE_BASE_DIR=/var/www/vhosts/gestion.abianservice.com/httpdocs/produccion/app/fotos_estado_react_native

API: Crear incidencia de viaje

Endpoint: POST /api/trips/:tripId/incidencias
Auth: Bearer <JWT> obligatorio.

Request JSON

{
  "incidencia": "Retraso por tráfico",
  "notificar": 0,
  "notificar_cr": 0
}

Notas:

  • incidencia es obligatoria (string, trim, no vacía).
  • notificar/notificar_cr se ignoran; backend fuerza ind_aviso_cli=1 y ind_aviso_cr=1.

Responses

  • 201:
    • { "success": true, "message": "correcto" }
    • { "success": true, "message": "correcto", "warning": "email_failed" } (si falla SMTP, sin revertir insert)
  • 400: payload inválido (tripId inválido o incidencia vacía)
  • 401: no autenticado
  • 403: usuario autenticado sin acceso al viaje
  • 404: viaje no existe
  • 500: error interno

cURL

curl -X POST "http://127.0.0.1:3001/api/trips/248230/incidencias" \
  -H "Authorization: Bearer <JWT>" \
  -H "Content-Type: application/json" \
  -d '{
    "incidencia": "Cliente no localizable en punto de recogida",
    "notificar": 0,
    "notificar_cr": 0
  }'

API: Estado automático de viaje (auditoría)

Endpoint: POST /api/trips/:id/auto-status
Auth: Bearer <JWT> obligatorio.

Request JSON

{
  "id_estado": 5,
  "id_punto": 8123,
  "observaciones": "Estado actualizado automáticamente",
  "ind_fallido": 0,
  "latitud": "40.416775",
  "longitud": "-3.703790",
  "fecha_y_hora": "2026-02-17 12:34:56"
}

Notas:

  • id_estado es obligatorio.
  • id_punto es opcional.
  • Si se envía id_punto, id_estado solo puede ser 3, 4 o 5.
  • Sin id_punto, se permite cualquier estado válido en t_viaje_estados.
  • fecha_y_hora es opcional: si no es válida se usa hora servidor.
  • No se soportan fotos (fotos_concat/multipart).
  • Este endpoint no actualiza c_viajes.id_estado.
  • Siempre inserta en c_cambios_estado con actualizado_automaticamente=1.
  • Si hay id_punto, también actualiza c_viajes_puntos con actualizado_automaticamente=1 para disparar trg_c_viajes_puntos_tracking_au.

Responses

  • 200: estado automático registrado
  • 400: payload inválido
  • 401: no autenticado
  • 403: usuario autenticado sin acceso al viaje
  • 404: viaje o punto no existe
  • 422: id_punto enviado con id_estado fuera de 3/4/5
  • 500: error interno

Driver license seguro (backend)

Este backend soporta carga y acceso seguro de carnet de conducir:

  • POST /api/update_driver_license (alias: POST /api/upload_driver_license)
  • No usar POST /update_profile_photo para carnet: esa ruta es solo para foto_perfil y ahora rechaza payloads de driver_license.
  • GET /api/secure/driver-license/side/:side?dni=...&id_proveedor=... (side: front|back)
  • GET /api/secure/driver-license/:publicId (compatibilidad)
  • DELETE /api/secure/driver-license/:publicId (borrado lógico)

Variables de entorno nuevas

  • DRIVER_LICENSE_ENCRYPTION_KEY (obligatoria): clave AES-256-GCM de 32 bytes (hex de 64 chars o base64, opcional prefijo base64:).
  • DRIVER_LICENSE_KEY_VERSION (opcional, default v1).
  • DRIVER_LICENSE_STORAGE_DIR (opcional, default ./secure_storage/driver-license).
  • DRIVER_LICENSE_RETENTION_DAYS (opcional, default 365).
  • DRIVER_LICENSE_PURGE_BATCH_SIZE (opcional, default 100).

Migración SQL

Aplicar:

mysql -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASSWORD" "$DB_NAME" < src/sql/migrations/20260216_driver_license_security.sql
mysql -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASSWORD" "$DB_NAME" < src/sql/migrations/20260216_driver_license_sides.sql

Purga física por retención

npm run purge:driver-licenses