HR-ATS-Portal/backend/users/app.py

230 lines
7.4 KiB
Python

from fastapi import APIRouter,Depends, Query
from fastapi.responses import JSONResponse
from fastapi import HTTPException
from db_setup import get_session
from sqlalchemy.ext.asyncio import AsyncSession
from pydantic import BaseModel, EmailStr, model_validator
from users.views import User
from users.permissions import CurrentUser, PermissionTag, require_permission
from users.serializers import serialize_token
from users.plugins import create_access_token,create_refresh_token
from dotenv import load_dotenv
load_dotenv()
router = APIRouter()
class UserCreate(BaseModel):
name: str
email: EmailStr
password: str
role_id: int | None = None
is_active: bool = True
class UserSignup(BaseModel):
name: str
email: EmailStr
password: str
class UserUpdate(BaseModel):
name: str | None = None
email: EmailStr | None = None
password: str | None = None
is_active: bool | None = None
class RoleAssign(BaseModel):
role_id: int
class UserLogin(BaseModel):
password: str
email: EmailStr | None = None
username: str | None = None
@model_validator(mode="after")
def require_email_or_username(self):
if not self.email and not self.username:
raise ValueError("email or username is required")
return self
class TokenRefresh(BaseModel):
refresh_token: str
@router.post("/users/login")
async def login(payload: UserLogin,session: AsyncSession = Depends(get_session)):
try:
service=User(session=session)
user=await service.authenticate_user(payload.email or payload.username,payload.password)
tokens=serialize_token(create_access_token(user),create_refresh_token(user),user)
return JSONResponse(content={**tokens,"status_code":200})
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500,detail=str(e))
@router.post("/users/signup")
async def signup(payload: UserSignup,session: AsyncSession = Depends(get_session)):
try:
service=User(session=session)
user=await service.signup_user(payload.model_dump())
tokens=serialize_token(create_access_token(user),create_refresh_token(user),user)
return JSONResponse(content={**tokens,"status_code":200})
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500,detail=str(e))
@router.post("/users/refresh")
async def refresh(payload: TokenRefresh,session: AsyncSession = Depends(get_session)):
try:
service=User(session=session)
user=await service.refresh_access_token(payload.refresh_token)
tokens=serialize_token(create_access_token(user),create_refresh_token(user),user)
return JSONResponse(content={**tokens,"status_code":200})
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500,detail=str(e))
@router.get("/users/me")
async def me(current_user: CurrentUser):
try:
return JSONResponse(content={"data":current_user,"status_code":200})
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500,detail=str(e))
@router.post("/users/create")
async def create_user(
payload: UserCreate,
current_user: dict = Depends(require_permission(PermissionTag.RBAC_USERS_CREATE)),
session: AsyncSession = Depends(get_session),
):
try:
service=User(session=session)
user=await service.create_user(payload.model_dump(),current_user)
tokens=serialize_token(create_access_token(user),create_refresh_token(user),user)
return JSONResponse(content={**tokens,"status_code":200})
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500,detail=str(e))
@router.get("/users/fetch")
async def fetch_users(
current_user: dict = Depends(require_permission(PermissionTag.RBAC_USERS_VIEW)),
record_id: str | None = Query(None),
search: str | None = Query(None),
top: int | None = Query(None),
skip: int = Query(0, ge=0),
role_id: int | None = Query(None),
session: AsyncSession = Depends(get_session),
):
try:
service=User(session=session)
if record_id:
item=await service.get_user_by_id(record_id)
return JSONResponse(content={"data":item,"total":1,"status_code":200})
items=await service.get_users(top,skip,search,role_id=role_id)
total=await service.count_users(search,role_id=role_id)
return JSONResponse(content={"data":items,"total":total,"status_code":200})
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500,detail=str(e))
@router.put("/users/update")
async def update_user(
payload: UserUpdate,
current_user: dict = Depends(require_permission(PermissionTag.RBAC_USERS_EDIT)),
record_id: str = Query(...),
session: AsyncSession = Depends(get_session),
):
try:
service=User(session=session)
data=await service.update_user(record_id,payload.model_dump(exclude_unset=True))
return JSONResponse(content={"data":data,"status_code":200})
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500,detail=str(e))
@router.put("/users/assign-role")
async def assign_role(
payload: RoleAssign,
current_user: dict = Depends(require_permission(PermissionTag.RBAC_USERS_EDIT)),
record_id: str = Query(...),
session: AsyncSession = Depends(get_session),
):
try:
service=User(session=session)
data=await service.assign_role(record_id,payload.role_id,current_user)
return JSONResponse(content={"data":data,"status_code":200})
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500,detail=str(e))
@router.put("/users/remove-role")
async def remove_role(
current_user: dict = Depends(require_permission(PermissionTag.RBAC_USERS_EDIT)),
record_id: str = Query(...),
session: AsyncSession = Depends(get_session),
):
try:
service=User(session=session)
data=await service.remove_role(record_id,current_user)
return JSONResponse(content={"data":data,"status_code":200})
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500,detail=str(e))
@router.delete("/users/delete")
async def delete_user(
current_user: dict = Depends(require_permission(PermissionTag.RBAC_USERS_DELETE)),
record_id: str = Query(...),
session: AsyncSession = Depends(get_session),
):
try:
service=User(session=session)
data=await service.delete_user(record_id)
return JSONResponse(content={"data":data,"status_code":200})
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500,detail=str(e))
@router.get("/managers/fetch")
async def fetch_managers(
current_user: dict = Depends(
require_permission(PermissionTag.JOBS_VIEW, PermissionTag.CANDIDATES_VIEW, require_all=False)
),
session: AsyncSession = Depends(get_session),
):
try:
service=User(session=session)
data,total=await service.get_managers()
return JSONResponse(content={"data":data,"total":total,"status_code":200})
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500,detail=str(e))