"""Role management endpoints (admin).""" from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.api.deps import require_permission from app.db.session import get_async_session from app.models import User, Role from app.schemas.role import RoleCreateRequest, RoleUpdateRequest, RoleResponse router = APIRouter(prefix="/roles", tags=["roles"]) @router.get("", response_model=list[RoleResponse]) async def list_roles( current_user: User = Depends(require_permission("roles:read")), session: AsyncSession = Depends(get_async_session), ): """List all roles within the current account.""" account_id = current_user.account_id result = await session.execute( select(Role).where(Role.account_id == account_id).order_by(Role.name) ) roles = result.scalars().all() return [RoleResponse.model_validate(r) for r in roles] @router.post("", response_model=RoleResponse, status_code=status.HTTP_201_CREATED) async def create_role( body: RoleCreateRequest, current_user: User = Depends(require_permission("roles:write")), session: AsyncSession = Depends(get_async_session), ): """Create a new role within the current account.""" account_id = current_user.account_id # Check name uniqueness within account existing = await session.execute( select(Role).where(Role.account_id == account_id, Role.name == body.name) ) if existing.scalars().first(): raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail="A role with this name already exists in your account", ) role = Role( account_id=account_id, name=body.name, description=body.description, permissions=body.permissions, ) session.add(role) await session.commit() await session.refresh(role) return RoleResponse.model_validate(role) @router.put("/{role_id}", response_model=RoleResponse) async def update_role( role_id: str, body: RoleUpdateRequest, current_user: User = Depends(require_permission("roles:write")), session: AsyncSession = Depends(get_async_session), ): """Update a role's permissions, name, or description.""" account_id = current_user.account_id result = await session.execute( select(Role).where(Role.id == role_id, Role.account_id == account_id) ) role = result.scalars().first() if not role: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Role not found", ) if body.name is not None: role.name = body.name if body.description is not None: role.description = body.description if body.permissions is not None: role.permissions = body.permissions await session.commit() await session.refresh(role) return RoleResponse.model_validate(role)