from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from app.core.database import get_db from app.crud import role as role_crud from app.deps import require_permission from app.models.user import User from app.schemas.rbac import PermissionRead, RoleCreate, RoleRead, RoleUpdate router = APIRouter() @router.get("", response_model=list[RoleRead]) async def list_roles( db: AsyncSession = Depends(get_db), _: User = Depends(require_permission("roles:read")), ): return await role_crud.list_roles(db) @router.post("", response_model=RoleRead, status_code=status.HTTP_201_CREATED) async def create_role( payload: RoleCreate, db: AsyncSession = Depends(get_db), _: User = Depends(require_permission("roles:write")), ): if await role_crud.get_by_name(db, payload.name): raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail="Role already exists" ) return await role_crud.create( db, name=payload.name, description=payload.description, permission_ids=payload.permission_ids, ) @router.get("/permissions", response_model=list[PermissionRead]) async def list_permissions( db: AsyncSession = Depends(get_db), _: User = Depends(require_permission("roles:read")), ): return await role_crud.list_permissions(db) @router.get("/{role_id}", response_model=RoleRead) async def get_role( role_id: int, db: AsyncSession = Depends(get_db), _: User = Depends(require_permission("roles:read")), ): role = await role_crud.get(db, role_id) if role is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Role not found") return role @router.patch("/{role_id}", response_model=RoleRead) async def update_role( role_id: int, payload: RoleUpdate, db: AsyncSession = Depends(get_db), _: User = Depends(require_permission("roles:write")), ): role = await role_crud.get(db, role_id) if role is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Role not found") return await role_crud.update(db, role, payload.model_dump(exclude_unset=True)) @router.delete("/{role_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_role( role_id: int, db: AsyncSession = Depends(get_db), _: User = Depends(require_permission("roles:write")), ): role = await role_crud.get(db, role_id) if role is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Role not found") await role_crud.delete(db, role)