Files
plantillas-proyectos/backend/api/v1/modules/a76/auth/routes.py

133 lines
3.6 KiB
Python

"""
Endpoints API para autenticación
"""
from fastapi import APIRouter, Depends, HTTPException
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from sqlalchemy.orm import Session
from core.database import get_core_db
from core.security import get_current_user
from .dto import (
LoginRequestDTO,
TokenResponseDTO,
RefreshTokenRequestDTO,
UserInfoResponseDTO,
LogoutRequestDTO,
RegisterRequestDTO,
RegisterResponseDTO,
ExchangeCodeRequestDTO
)
from .service import AuthService
router = APIRouter(prefix="/auth", tags=["Authentication"])
security = HTTPBearer()
@router.post("/register", response_model=RegisterResponseDTO, status_code=201)
async def register(
register_data: RegisterRequestDTO,
db: Session = Depends(get_core_db)
):
"""
Registra un nuevo usuario en Keycloak
El usuario debe proporcionar:
- username: Nombre de usuario único
- email: Email único
- password: Contraseña (mínimo 8 caracteres)
- first_name: Nombre
- last_name: Apellido
- tenant_slug: Slug del tenant al que pertenece
El usuario se crea automáticamente en Keycloak con:
- Cuenta habilitada
- Rol 'user' asignado por defecto
- Atributos de tenant
"""
service = AuthService(db)
return service.register(register_data)
@router.post("/login", response_model=TokenResponseDTO)
async def login(
login_data: LoginRequestDTO,
db: Session = Depends(get_core_db)
):
"""
Autentica usuario con Keycloak y retorna tokens JWT
El usuario debe proporcionar:
- username: Usuario o email
- password: Contraseña
- tenant_slug: Slug del tenant al que pertenece
"""
service = AuthService(db)
return service.login(login_data)
@router.post("/refresh", response_model=TokenResponseDTO)
async def refresh_token(
refresh_data: RefreshTokenRequestDTO,
db: Session = Depends(get_core_db)
):
"""
Refresca el access token usando el refresh token
"""
service = AuthService(db)
return service.refresh_token(refresh_data)
@router.get("/me", response_model=UserInfoResponseDTO)
async def get_current_user_info(
credentials: HTTPAuthorizationCredentials = Depends(security),
db: Session = Depends(get_core_db)
):
"""
Obtiene información del usuario actual desde el token
"""
service = AuthService(db)
return service.get_user_info(credentials.credentials)
@router.post("/logout")
async def logout(
logout_data: LogoutRequestDTO,
db: Session = Depends(get_core_db),
current_user: dict = Depends(get_current_user)
):
"""
Cierra sesión invalidando el refresh token
"""
service = AuthService(db)
return service.logout(logout_data)
@router.post("/exchange-code", response_model=TokenResponseDTO)
async def exchange_code(
exchange_data: ExchangeCodeRequestDTO,
db: Session = Depends(get_core_db)
):
"""
Intercambia un authorization code de OAuth2 por tokens
Este endpoint es útil cuando el frontend usa el flujo de autorización
con proveedores externos (Microsoft, Google, etc.) a través de Keycloak.
El código se obtiene después de que el usuario se autentica con el proveedor
externo y Keycloak lo redirige al frontend con el código en los query params.
"""
service = AuthService(db)
return service.exchange_code(exchange_data)
@router.get("/health")
async def auth_health():
"""
Health check del módulo de autenticación
"""
return {
"status": "ok",
"module": "authentication",
"provider": "keycloak"
}