89 lines
2.9 KiB
Python
89 lines
2.9 KiB
Python
"""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)
|