69 lines
2.7 KiB
Python
69 lines
2.7 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Annotated
|
|
|
|
from bson import ObjectId
|
|
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from motor.motor_asyncio import AsyncIOMotorDatabase
|
|
|
|
from fastcheck_api.app.api.dependencies import CurrentUser, get_current_user
|
|
from fastcheck_api.app.core.mongodb import get_db
|
|
from fastcheck_api.app.core.security import create_access_token
|
|
from fastcheck_api.app.schemas.auth import LoginRequest, LoginResponse, UserOut
|
|
from fastcheck_api.app.services.auth_service import AuthService
|
|
|
|
|
|
router = APIRouter(prefix="/auth", tags=["auth"])
|
|
|
|
|
|
@router.post(
|
|
"/login",
|
|
response_model=LoginResponse,
|
|
summary="Login",
|
|
description="Authenticate with email and password and receive a bearer JWT token compatible with the existing Node.js backend.",
|
|
)
|
|
async def login(payload: LoginRequest, db: Annotated[AsyncIOMotorDatabase, Depends(get_db)]):
|
|
try:
|
|
res = await AuthService.login(db=db, email=payload.email, password=payload.password)
|
|
return res
|
|
except PermissionError as e:
|
|
if str(e) == "ACCOUNT_NOT_ACTIVATED":
|
|
raise HTTPException(
|
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
detail={
|
|
"message": "Tu cuenta está pendiente de activación por parte del superadministrador. Contacta al administrador para completar la activación.",
|
|
"activationStatus": "pending",
|
|
},
|
|
)
|
|
raise
|
|
except ValueError:
|
|
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid credentials")
|
|
except RuntimeError as e:
|
|
raise HTTPException(status_code=status.HTTP_502_BAD_GATEWAY, detail=str(e))
|
|
|
|
|
|
@router.get(
|
|
"/me",
|
|
response_model=UserOut,
|
|
summary="Get current user",
|
|
description="Return the authenticated user's profile from the existing `users` collection.",
|
|
)
|
|
async def me(
|
|
user: Annotated[CurrentUser, Depends(get_current_user)],
|
|
db: Annotated[AsyncIOMotorDatabase, Depends(get_db)],
|
|
):
|
|
doc = await db["users"].find_one({"_id": ObjectId(user.id)}, projection={"name": 1, "email": 1, "role": 1})
|
|
if not doc:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")
|
|
return {"id": user.id, "name": doc.get("name") or "", "email": doc.get("email") or user.email, "role": doc.get("role") or user.role}
|
|
|
|
|
|
@router.post(
|
|
"/refresh",
|
|
summary="Refresh token",
|
|
description="Issue a new JWT token using the current token's identity and tenant context.",
|
|
)
|
|
async def refresh(user: Annotated[CurrentUser, Depends(get_current_user)]):
|
|
token = create_access_token(user_id=user.id, email=user.email, role=user.role, tenant_id=user.tenant)
|
|
return {"token": token}
|