evo-ai/src/api/auth_routes.py

229 lines
6.8 KiB
Python

from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from src.config.database import get_db
from src.models.models import User
from src.schemas.user import (
UserCreate,
UserResponse,
UserLogin,
TokenResponse,
ForgotPassword,
PasswordReset,
MessageResponse
)
from src.services.user_service import (
create_user,
verify_email,
resend_verification,
forgot_password,
reset_password
)
from src.services.auth_service import (
authenticate_user,
create_access_token,
get_current_admin_user
)
import logging
logger = logging.getLogger(__name__)
router = APIRouter(
prefix="/auth",
tags=["autenticação"],
responses={404: {"description": "Não encontrado"}},
)
@router.post("/register", response_model=UserResponse, status_code=status.HTTP_201_CREATED)
async def register_user(user_data: UserCreate, db: Session = Depends(get_db)):
"""
Registra um novo usuário (cliente) no sistema
Args:
user_data: Dados do usuário a ser registrado
db: Sessão do banco de dados
Returns:
UserResponse: Dados do usuário criado
Raises:
HTTPException: Se houver erro no registro
"""
user, message = create_user(db, user_data, is_admin=False)
if not user:
logger.error(f"Erro ao registrar usuário: {message}")
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=message
)
logger.info(f"Usuário registrado com sucesso: {user.email}")
return user
@router.post("/register-admin", response_model=UserResponse, status_code=status.HTTP_201_CREATED)
async def register_admin(
user_data: UserCreate,
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_user)
):
"""
Registra um novo administrador no sistema.
Apenas administradores existentes podem criar novos administradores.
Args:
user_data: Dados do administrador a ser registrado
db: Sessão do banco de dados
current_admin: Administrador atual (autenticado)
Returns:
UserResponse: Dados do administrador criado
Raises:
HTTPException: Se houver erro no registro
"""
user, message = create_user(db, user_data, is_admin=True)
if not user:
logger.error(f"Erro ao registrar administrador: {message}")
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=message
)
logger.info(f"Administrador registrado com sucesso: {user.email} (criado por {current_admin.email})")
return user
@router.get("/verify-email/{token}", response_model=MessageResponse)
async def verify_user_email(token: str, db: Session = Depends(get_db)):
"""
Verifica o email de um usuário usando o token fornecido
Args:
token: Token de verificação
db: Sessão do banco de dados
Returns:
MessageResponse: Mensagem de sucesso
Raises:
HTTPException: Se o token for inválido ou expirado
"""
success, message = verify_email(db, token)
if not success:
logger.warning(f"Falha na verificação de email: {message}")
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=message
)
logger.info(f"Email verificado com sucesso usando token: {token}")
return {"message": message}
@router.post("/resend-verification", response_model=MessageResponse)
async def resend_verification_email(
email_data: ForgotPassword,
db: Session = Depends(get_db)
):
"""
Reenvia o email de verificação para o usuário
Args:
email_data: Email do usuário
db: Sessão do banco de dados
Returns:
MessageResponse: Mensagem de sucesso
Raises:
HTTPException: Se houver erro no reenvio
"""
success, message = resend_verification(db, email_data.email)
if not success:
logger.warning(f"Falha no reenvio de verificação: {message}")
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=message
)
logger.info(f"Email de verificação reenviado com sucesso para: {email_data.email}")
return {"message": message}
@router.post("/login", response_model=TokenResponse)
async def login_for_access_token(
form_data: UserLogin,
db: Session = Depends(get_db)
):
"""
Realiza login e retorna um token de acesso JWT
Args:
form_data: Dados de login (email e senha)
db: Sessão do banco de dados
Returns:
TokenResponse: Token de acesso e tipo
Raises:
HTTPException: Se as credenciais forem inválidas
"""
user = authenticate_user(db, form_data.email, form_data.password)
if not user:
logger.warning(f"Tentativa de login com credenciais inválidas: {form_data.email}")
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Email ou senha incorretos",
headers={"WWW-Authenticate": "Bearer"},
)
access_token = create_access_token(user)
logger.info(f"Login realizado com sucesso para usuário: {user.email}")
return {"access_token": access_token, "token_type": "bearer"}
@router.post("/forgot-password", response_model=MessageResponse)
async def forgot_user_password(
email_data: ForgotPassword,
db: Session = Depends(get_db)
):
"""
Inicia o processo de recuperação de senha
Args:
email_data: Email do usuário
db: Sessão do banco de dados
Returns:
MessageResponse: Mensagem de sucesso
Raises:
HTTPException: Se houver erro no processo
"""
success, message = forgot_password(db, email_data.email)
# Sempre retornamos a mesma mensagem por segurança
return {"message": "Se o email estiver cadastrado, você receberá instruções para redefinir sua senha."}
@router.post("/reset-password", response_model=MessageResponse)
async def reset_user_password(
reset_data: PasswordReset,
db: Session = Depends(get_db)
):
"""
Redefine a senha do usuário usando o token fornecido
Args:
reset_data: Token e nova senha
db: Sessão do banco de dados
Returns:
MessageResponse: Mensagem de sucesso
Raises:
HTTPException: Se o token for inválido ou expirado
"""
success, message = reset_password(db, reset_data.token, reset_data.new_password)
if not success:
logger.warning(f"Falha na redefinição de senha: {message}")
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=message
)
logger.info("Senha redefinida com sucesso")
return {"message": message}