Files
data-entry-app/backend/app/api/client_access.py
T

85 lines
3.3 KiB
Python
Raw Normal View History

2026-04-25 22:51:36 +12:00
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy import select
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import Session
from app.api.deps import require_admin_session
from app.db.session import get_db
from app.models.client_access import ClientAccount, ClientFeatureAccess, ClientUser
from app.schemas.client_access import ClientAccessRead, ClientFeatureUpdate, ClientUserCreate, ClientUserUpdate
from app.services.client_access_service import list_client_accounts, serialize_client_account
router = APIRouter(prefix="/api/client-access", tags=["client-access"])
def _get_client_or_404(db: Session, client_id: int) -> ClientAccount:
client = db.scalar(select(ClientAccount).where(ClientAccount.id == client_id))
if client is None:
raise HTTPException(status_code=404, detail="Client account not found")
return client
def _read_client_account(db: Session, client_id: int) -> dict:
client = next((item for item in list_client_accounts(db) if item.id == client_id), None)
if client is None:
raise HTTPException(status_code=404, detail="Client account not found")
return serialize_client_account(client)
@router.get("", response_model=list[ClientAccessRead])
def get_client_access(db: Session = Depends(get_db), _: object = Depends(require_admin_session)):
return [serialize_client_account(client) for client in list_client_accounts(db)]
@router.post("/users", response_model=ClientAccessRead, status_code=status.HTTP_201_CREATED)
def create_client_user(
payload: ClientUserCreate,
db: Session = Depends(get_db),
_: object = Depends(require_admin_session),
):
client = _get_client_or_404(db, payload.client_account_id)
user = ClientUser(tenant_id=client.tenant_id, **payload.model_dump())
db.add(user)
try:
db.commit()
except IntegrityError as exc:
db.rollback()
raise HTTPException(status_code=409, detail="A user with that email already exists for this client") from exc
return _read_client_account(db, payload.client_account_id)
@router.patch("/users/{user_id}", response_model=ClientAccessRead)
def update_client_user(user_id: int, payload: ClientUserUpdate, db: Session = Depends(get_db), _: object = Depends(require_admin_session)):
user = db.scalar(select(ClientUser).where(ClientUser.id == user_id))
if user is None:
raise HTTPException(status_code=404, detail="Client user not found")
for field, value in payload.model_dump(exclude_unset=True).items():
setattr(user, field, value)
try:
db.commit()
except IntegrityError as exc:
db.rollback()
raise HTTPException(status_code=409, detail="A user with that email already exists for this client") from exc
return _read_client_account(db, user.client_account_id)
@router.patch("/features/{feature_id}", response_model=ClientAccessRead)
def update_client_feature(
feature_id: int,
payload: ClientFeatureUpdate,
db: Session = Depends(get_db),
_: object = Depends(require_admin_session),
):
feature = db.scalar(select(ClientFeatureAccess).where(ClientFeatureAccess.id == feature_id))
if feature is None:
raise HTTPException(status_code=404, detail="Client feature not found")
feature.enabled = payload.enabled
db.commit()
return _read_client_account(db, feature.client_account_id)