230 lines
7.4 KiB
Python
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))
|