blackmistcode's picture
Add files using upload-large-folder tool
71b8eb2 verified
|
Raw
History Blame Contribute Delete
5.45 kB

Auth — Guía de uso

Login con email + password. El backend emite un JWT (HS256, default 1h) que viaja en Authorization: Bearer <token>. No hay registro público en esta fase: los usuarios se crean vía el seeder. No hay rolesrequireAuth solo valida que el usuario esté logueado y activo, para que pueda mantener sus preferencias.

1. Variables de entorno

Copiar backend/.env.example a backend/.env y rellenar:

Variable Default Notas
NODE_ENV development development | test | production
PORT 7860 Puerto del backend (HF Spaces requiere 7860)
DATABASE_URL file:./polysignal.db Path SQLite relativo a prisma/schema.prisma
JWT_SECRET — (obligatorio) Mínimo 32 chars. Generar con openssl rand -hex 48
JWT_EXPIRES_IN 1h Formato jsonwebtoken (1h, 15m, 7d, ...)
BCRYPT_ROUNDS 10 Entre 4 y 15
CORS_ORIGIN http://localhost:5173 Origen del frontend en dev
LOG_LEVEL info trace/debug/info/warn/error/fatal

Si el .env falta una variable obligatoria o un valor es inválido, el backend imprime el error y aborta el arranque (validación con Zod en src/config.js).

2. Primer arranque

Desde backend/:

npm install                                  # instala deps
npm run db:migrate -- --name init_auth       # solo la primera vez (ya hecho)
npm run db:seed                              # crea los 2 usuarios de prueba
npm run dev                                  # arranca en http://localhost:7860

Para inspeccionar la DB en una UI:

npm run db:studio

3. Usuarios de prueba

Sembrados por prisma/seed.js (idempotente, se puede re-ejecutar):

Email Password
admin@polysignal.test Admin123!
user@polysignal.test User123!

4. Endpoints

GET /api/v1/health

Sanity check. Respuesta:

{ "ok": true, "data": { "status": "up" } }

POST /api/v1/auth/login

Body:

{ "email": "admin@polysignal.test", "password": "Admin123!" }

Respuesta 200:

{
  "ok": true,
  "data": {
    "token": "eyJhbGciOiJIUzI1NiJ9...",
    "user": { "id": 1, "email": "admin@polysignal.test" }
  }
}

Errores:

HTTP code cuándo
400 VALIDATION_ERROR Email inválido o password < 8 chars
401 INVALID_CREDENTIALS Email no existe, usuario desactivado, o password incorrecta
429 TOO_MANY_REQUESTS Más de 5 intentos en 15 min desde la misma IP

GET /api/v1/auth/me

Requiere header Authorization: Bearer <token>. Respuesta 200:

{
  "ok": true,
  "data": {
    "user": {
      "id": 1,
      "email": "admin@polysignal.test",
      "isActive": true,
      "createdAt": "2026-05-16T07:11:43.000Z"
    }
  }
}

Errores:

HTTP code cuándo
401 UNAUTHORIZED Sin header, token mal formado, expirado, manipulado, o usuario desactivado

5. Ejemplos con curl

# 1) Login y guardar token en variable
TOKEN=$(curl -s -X POST http://localhost:7860/api/v1/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"email":"admin@polysignal.test","password":"Admin123!"}' \
  | jq -r '.data.token')

# 2) Llamar a /me con el token
curl -s http://localhost:7860/api/v1/auth/me \
  -H "Authorization: Bearer $TOKEN" | jq

6. Login desde el frontend (referencia)

El JWT es opaco para el front: basta con guardarlo (sessionStorage o estado en memoria) y enviarlo en cada request protegido.

const res = await fetch('/api/v1/auth/login', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ email, password }),
});
const json = await res.json();
if (!json.ok) throw new Error(json.error.code);
const { token, user } = json.data;
// guardar token y user

// requests autenticados
fetch('/api/v1/auth/me', { headers: { Authorization: `Bearer ${token}` } });

En dev, Vite proxea /api/* al backend (localhost:7860); no hace falta CORS si va por el proxy, pero ya está configurado por si el front llama directo.

7. Cómo proteger nuevos endpoints

import { requireAuth } from '../middlewares/requireAuth.js';

router.get('/positions', requireAuth, controller.list);

Dentro del controller, req.user ya está disponible con { id, email, isActive, createdAt } — suficiente para filtrar datos del usuario logueado (ej. sus preferencias, posiciones, watchlist).

8. Rotar JWT_SECRET

Genera uno nuevo y reemplaza el valor de JWT_SECRET en backend/.env:

openssl rand -hex 48

Al cambiar el secreto, todos los tokens emitidos previamente quedan invalidados (los clientes deben volver a hacer login).

9. Notas técnicas

  • Hashing: bcryptjs (puro JS, sin compilación nativa — más portable a HF Spaces) con coste BCRYPT_ROUNDS (default 10).
  • JWT: algoritmo HS256, claim sub = user.id, email, iat, exp.
  • Rate limit en /auth/login: express-rate-limit, 5 intentos / 15 min / IP.
  • Validación de body: zod schema en src/auth/auth.validators.js.
  • Errores formateados: todas las respuestas siguen { ok, data } o { ok:false, error:{ code, message, details? } } vía src/utils/apiResponse.js y el middleware errorHandler.
  • Prisma: singleton en src/utils/prisma.js para no abrir conexiones de más con node --watch.