Files
ABIANAPP_NODE_PRODUCCION/README_sin_ruta_mod_imagenes_api.md
T

6.5 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.
    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