85 lines
3.3 KiB
Python
85 lines
3.3 KiB
Python
|
|
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)
|