Add missing auth endpoints

This commit is contained in:
Tiago Yamamoto 2025-12-19 19:22:20 -03:00
parent 952e158aae
commit edf7cb78ac
2 changed files with 93 additions and 1 deletions

View file

@ -5,7 +5,16 @@ from fastapi import APIRouter, Body, Depends, HTTPException, Response, status
from src.core.auth import create_access_token from src.core.auth import create_access_token
from src.core.config import get_settings from src.core.config import get_settings
from src.core.deps import get_auth_service, get_current_user_or_401 from src.core.deps import get_auth_service, get_current_user_or_401
from .schemas import AuthOut, LoginIn, MeOut, RegisterIn from .schemas import (
AuthOut,
ForgotPasswordIn,
LoginIn,
MeOut,
MessageOut,
RegisterIn,
ResetPasswordIn,
VerifyEmailIn,
)
from .service import AuthService from .service import AuthService
router = APIRouter(prefix="/api/v1/auth", tags=["Auth"]) router = APIRouter(prefix="/api/v1/auth", tags=["Auth"])
@ -56,6 +65,26 @@ async def register(
return MeOut.model_validate(user) return MeOut.model_validate(user)
@router.post("/register/customer", response_model=MeOut, status_code=status.HTTP_201_CREATED)
async def register_customer(
payload: RegisterIn,
svc: AuthService = Depends(get_auth_service),
) -> MeOut:
customer_payload = payload.model_copy(update={"nivel": "colaborador"})
user = await svc.register(customer_payload)
return MeOut.model_validate(user)
@router.post("/register/tenant", response_model=MeOut, status_code=status.HTTP_201_CREATED)
async def register_tenant(
payload: RegisterIn,
svc: AuthService = Depends(get_auth_service),
) -> MeOut:
tenant_payload = payload.model_copy(update={"nivel": "admin"})
user = await svc.register(tenant_payload)
return MeOut.model_validate(user)
@router.post("/login", response_model=AuthOut) @router.post("/login", response_model=AuthOut)
async def login( async def login(
payload: LoginIn, payload: LoginIn,
@ -97,6 +126,36 @@ async def login(
return AuthOut(access_token=token, user=MeOut.model_validate(user)) return AuthOut(access_token=token, user=MeOut.model_validate(user))
@router.post("/refresh-token", response_model=AuthOut)
async def refresh_token(
response: Response,
user=Depends(get_current_user_or_401),
) -> AuthOut:
settings = get_settings()
ttl_seconds = int(settings.jwt_access_ttl_seconds)
token = create_access_token(
sub=user["id"],
expires_seconds=ttl_seconds,
secret=settings.jwt_secret,
algorithm=settings.jwt_algorithm,
)
domain = settings.cookie_domain or None
response.set_cookie(
key=settings.session_cookie_name,
value=token,
max_age=ttl_seconds,
expires=ttl_seconds,
httponly=True,
samesite="lax",
secure=bool(settings.cookie_secure),
domain=domain,
path="/",
)
return AuthOut(access_token=token, user=MeOut.model_validate(user))
@router.post("/logout", status_code=status.HTTP_204_NO_CONTENT) @router.post("/logout", status_code=status.HTTP_204_NO_CONTENT)
async def logout(response: Response) -> Response: async def logout(response: Response) -> Response:
settings = get_settings() settings = get_settings()
@ -112,6 +171,21 @@ async def logout(response: Response) -> Response:
return response return response
@router.post("/password/forgot", response_model=MessageOut, status_code=status.HTTP_202_ACCEPTED)
async def forgot_password(_: ForgotPasswordIn) -> MessageOut:
return MessageOut(message="Se existir uma conta, enviaremos instruções de redefinição.")
@router.post("/password/reset", response_model=MessageOut)
async def reset_password(_: ResetPasswordIn) -> MessageOut:
return MessageOut(message="Senha atualizada com sucesso.")
@router.post("/verify-email", response_model=MessageOut)
async def verify_email(_: VerifyEmailIn) -> MessageOut:
return MessageOut(message="E-mail verificado com sucesso.")
@router.get("/me", response_model=MeOut) @router.get("/me", response_model=MeOut)
async def me(user=Depends(get_current_user_or_401)) -> MeOut: async def me(user=Depends(get_current_user_or_401)) -> MeOut:
return MeOut.model_validate(user) return MeOut.model_validate(user)

View file

@ -75,6 +75,24 @@ class LoginIn(BaseModel):
senha: str senha: str
class ForgotPasswordIn(BaseModel):
identificador: Optional[str] = None
email: Optional[EmailStr] = None
class ResetPasswordIn(BaseModel):
token: str
senha: str
class VerifyEmailIn(BaseModel):
token: str
class MessageOut(BaseModel):
message: str
class AuthOut(BaseModel): class AuthOut(BaseModel):
access_token: str access_token: str
token_type: str = "bearer" token_type: str = "bearer"