Autenticación
Endpoints de autenticación para registro, inicio de sesión y gestión de perfiles de usuario.
Modelos de Datos
Section titled “Modelos de Datos”Los siguientes modelos de Prisma pertenecen al schema auth:
model User { id String @id @default(cuid()) email String @unique emailVerified DateTime? @map("email_verified")
accounts Account[] @relation("UserAccounts") Authenticator Authenticator[]
profile UserProfile? createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at")
@@map("users") @@schema("auth")}Account
Section titled “Account”model Account { id String @id @default(cuid()) userId String @map("user_id") type String provider String providerAccountId String @map("provider_account_id")
refresh_token String? @map("refresh_token") @db.Text access_token String? @map("access_token") @db.Text id_token String? @map("id_token") @db.Text session_state String? @map("session_state") scope String?
createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at")
user User @relation(fields: [userId], references: [id], onDelete: Cascade, name: "UserAccounts")
@@unique([provider, providerAccountId]) @@map("accounts") @@schema("auth")}Authenticator
Section titled “Authenticator”model Authenticator { credentialID String @unique userId String providerAccountId String credentialPublicKey String counter Int credentialDeviceType String credentialBackedUp Boolean transports String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@id([userId, credentialID]) @@schema("auth")}UserRole (Enum)
Section titled “UserRole (Enum)”enum UserRole { ADMIN STAFF TRAINER MEMBER
@@schema("auth")}Endpoints
Section titled “Endpoints”Registrar Usuario
Section titled “Registrar Usuario”Registrar un nuevo usuario en el sistema.
- URL:
/api/v1/auth/register - Método:
POST - Autenticación Requerida: No
Descripción Interna
Section titled “Descripción Interna”Este endpoint realiza las siguientes operaciones:
- Hashea la contraseña usando Bun.password.hash para almacenamiento seguro
- Crea el usuario y perfil en una transacción atómica de Prisma:
- Crea el registro
Usercon el email proporcionado - Crea automáticamente el
UserProfileasociado con nombre, tipo de documento y número de documento - El rol por defecto es
MEMBER
- Crea el registro
- Crea la cuenta de credenciales en la tabla
Accountcon:type: “credentials”provider: “credentials”access_token: contraseña hasheada
- Retorna el usuario y perfil creados (sin la contraseña)
Nota: La verificación por email está comentada actualmente pero preparada para enviar un enlace de verificación.
Cuerpo de Solicitud
Section titled “Cuerpo de Solicitud”{ "email": "user@example.com", "password": "password123", "documentType": "CC", "document": "123456789", "name": "John Doe"}Respuesta
Section titled “Respuesta”{ "message": "Usuario registrado exitosamente", "data": { "user": { "id": "cm...", "email": "user@example.com" }, "profile": { "id": "cm...", "role": "USER" } }}Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.auth.register.$post({ json: { email: 'user@example.com', password: 'password123', documentType: 'CC', document: '123456789', name: 'John Doe' }})
if (res.ok) { const data = await res.json() console.log(data.message)}Iniciar Sesión
Section titled “Iniciar Sesión”Autenticar un usuario y obtener tokens de acceso.
- URL:
/api/v1/auth/login - Método:
POST - Autenticación Requerida: No
Descripción Interna
Section titled “Descripción Interna”Este endpoint realiza las siguientes operaciones:
- Busca la cuenta de credenciales del usuario por email en la tabla
Account - Verifica la contraseña usando Bun.password.verify comparando con el hash almacenado
- Genera tokens JWT:
- Access Token: contiene
sub(userId),email,roleypid(profileId). Expira segúnTOKEN_EXPIRATION - Refresh Token: contiene solo
sub(userId). Expira segúnREFRESH_TOKEN_EXPIRATION
- Access Token: contiene
- Retorna los tokens junto con la información básica del usuario y perfil
Errores Comunes
Section titled “Errores Comunes”401 Unauthorized: Credenciales inválidas
Cuerpo de Solicitud
Section titled “Cuerpo de Solicitud”{ "email": "user@example.com", "password": "password123"}Respuesta
Section titled “Respuesta”{ "message": "Login exitoso", "data": { "accessToken": "eyJ...", "refreshToken": "eyJ...", "user": { ... } }}Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.auth.login.$post({ json: { email: 'user@example.com', password: 'password123' }})Obtener Perfil
Section titled “Obtener Perfil”Obtener el perfil del usuario actualmente autenticado.
- URL:
/api/v1/auth/profile - Método:
GET - Autenticación Requerida: Sí
Descripción Interna
Section titled “Descripción Interna”Este endpoint realiza las siguientes operaciones:
- Obtiene el userId del token JWT en el contexto de la petición
- Consulta el perfil completo del usuario incluyendo todas las relaciones:
- Membresía activa (
membership) - Perfil de entrenador si aplica (
trainer) - Rachas activas (
streaks) - Logros obtenidos con detalles (
userAchievements.achievement) - Objetivos personales (
goals) - Meta nutricional (
nutritionGoal) - Seguidores y seguidos (
followers,follows) - Consumo de agua (
waterIntake) - Likes dados (
likes) - Actividades diarias (
dailyActivities)
- Membresía activa (
- Retorna toda la información del perfil con las relaciones anidadas
Respuesta
Section titled “Respuesta”{ "data": { "id": "...", "userId": "...", "name": "John Doe", ... }}Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.auth.profile.$get()Actualizar Perfil
Section titled “Actualizar Perfil”Actualizar el perfil del usuario actualmente autenticado.
- URL:
/api/v1/auth/profile - Método:
PATCH - Autenticación Requerida: Sí
Descripción Interna
Section titled “Descripción Interna”Este endpoint realiza las siguientes operaciones:
- Obtiene el userId del token JWT en el contexto
- Actualiza el UserProfile con los campos proporcionados:
- Convierte
dateOfBirtha objeto Date si se proporciona - Campos actualizables:
name,phone,avatar_url,dateOfBirth,gender, etc.
- Convierte
- Verifica completitud del perfil:
- Si
profileCompletees false, evalúa si todos los campos requeridos están llenos - Si el perfil está completo, actualiza
profileCompletea true
- Si
- Retorna el perfil actualizado
Cuerpo de Solicitud (Parcial)
Section titled “Cuerpo de Solicitud (Parcial)”{ "name": "Jane Doe", "phone": "1234567890"}Respuesta
Section titled “Respuesta”{ "message": "Perfil actualizado exitosamente", "data": { ... }}Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.auth.profile.$patch({ json: { name: 'Jane Doe' }})Refrescar Tokens
Section titled “Refrescar Tokens”Refrescar el token de acceso usando un token de refresco válido (pasado via cookie).
- URL:
/api/v1/auth/refresh - Método:
GET - Autenticación Requerida: No (usa cookie de Refresh Token)
Descripción Interna
Section titled “Descripción Interna”Este endpoint realiza las siguientes operaciones:
- Extrae el refresh token de la cookie de la petición
- Verifica el token usando el
AUTH_SECRETy extrae elsub(userId) - Busca el usuario en la base de datos con su email, rol y profileId
- Genera nuevos tokens:
- Nuevo Access Token con la información actualizada del usuario
- Nuevo Refresh Token
- Retorna ambos tokens nuevos
Errores Comunes
Section titled “Errores Comunes”401 Unauthorized: Token de refresco inválido o expirado
Respuesta
Section titled “Respuesta”{ "message": "Tokens refrescados exitosamente", "data": { "accessToken": "...", "refreshToken": "..." }}Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.auth.refresh.$get()Cerrar Sesión
Section titled “Cerrar Sesión”Cerrar sesión del usuario y limpiar cookies de autenticación.
- URL:
/api/v1/auth/logout - Método:
POST - Autenticación Requerida: Sí
Descripción Interna
Section titled “Descripción Interna”Este endpoint realiza las siguientes operaciones:
- Invalida la sesión del usuario actual
- Limpia las cookies de autenticación (access token y refresh token)
- Retorna confirmación del cierre de sesión
Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.auth.logout.$post()Olvidé mi Contraseña
Section titled “Olvidé mi Contraseña”Solicitar un enlace para restablecer la contraseña.
- URL:
/api/v1/auth/forgot-password - Método:
POST - Autenticación Requerida: No
Descripción Interna
Section titled “Descripción Interna”Este endpoint realiza las siguientes operaciones:
- Busca el usuario por email en la base de datos
- Verifica el email - Si el email no ha sido verificado, lanza error (requiere contactar soporte)
- Genera token de reset válido por 5 minutos usando JWT
- Construye el enlace de restablecimiento:
{FRONTEND_URL}/reset-password?token={resetToken} - Envía email al usuario con el enlace de restablecimiento
Errores Comunes
Section titled “Errores Comunes”400 Bad Request: El email no ha sido verificado404 Not Found: Usuario no encontrado
Cuerpo de Solicitud
Section titled “Cuerpo de Solicitud”{ "email": "user@example.com"}Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.auth['forgot-password'].$post({ json: { email: 'user@example.com' }})Restablecer Contraseña
Section titled “Restablecer Contraseña”Restablecer contraseña usando el token proporcionado.
- URL:
/api/v1/auth/reset-password - Método:
POST - Autenticación Requerida: No
Descripción Interna
Section titled “Descripción Interna”Este endpoint realiza las siguientes operaciones:
- Verifica el token JWT y extrae el
sub(userId) - Hashea la nueva contraseña usando Bun.password.hash
- Busca la cuenta de credenciales del usuario
- Actualiza el access_token (contraseña hasheada) en la tabla Account
- Retorna confirmación del cambio
Errores Comunes
Section titled “Errores Comunes”400 Bad Request: Token inválido o expirado
Cuerpo de Solicitud
Section titled “Cuerpo de Solicitud”{ "token": "reset_token_here", "newPassword": "newpassword123"}Ejemplo de Cliente Hono
Section titled “Ejemplo de Cliente Hono”import { hcWithType } from '@vitality-gym/api/client'
const client = hcWithType('http://localhost:3000')
const res = await client.api.v1.auth['reset-password'].$post({ json: { token: 'reset_token', newPassword: 'newpassword123' }})