from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from app.core.database import get_db from app.crud import audit as audit_crud from app.crud import scope_model as scope_model_crud from app.deps import require_permission from app.models.user import User from app.schemas.scope_model import ScopeModelCreate, ScopeModelRead, ScopeModelUpdate router = APIRouter() @router.get("", response_model=list[ScopeModelRead]) async def list_scope_models( skip: int = 0, limit: int = 100, db: AsyncSession = Depends(get_db), _: User = Depends(require_permission("scope_models:read")), ): return await scope_model_crud.list_all(db, skip=skip, limit=limit) @router.post("", response_model=ScopeModelRead, status_code=status.HTTP_201_CREATED) async def create_scope_model( payload: ScopeModelCreate, db: AsyncSession = Depends(get_db), actor: User = Depends(require_permission("scope_models:write")), ): sm = await scope_model_crud.create( db, name=payload.name, manufacturer_id=payload.manufacturer_id, url=str(payload.url) if payload.url else None, ) await audit_crud.log( db, actor=actor, action="create", resource_type="ScopeModel", resource_id=sm.id, description=audit_crud.describe_create("ScopeModel", sm.id, sm.name), ) return sm @router.get("/{scope_model_id}", response_model=ScopeModelRead) async def get_scope_model( scope_model_id: int, db: AsyncSession = Depends(get_db), _: User = Depends(require_permission("scope_models:read")), ): sm = await scope_model_crud.get(db, scope_model_id) if sm is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Scope model not found") return sm @router.patch("/{scope_model_id}", response_model=ScopeModelRead) async def update_scope_model( scope_model_id: int, payload: ScopeModelUpdate, db: AsyncSession = Depends(get_db), actor: User = Depends(require_permission("scope_models:write")), ): sm = await scope_model_crud.get(db, scope_model_id) if sm is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Scope model not found") data = payload.model_dump(exclude_unset=True) if "url" in data and data["url"] is not None: data["url"] = str(data["url"]) sm = await scope_model_crud.update(db, sm, data) await audit_crud.log( db, actor=actor, action="update", resource_type="ScopeModel", resource_id=sm.id, description=audit_crud.describe_update("ScopeModel", sm.id, data), ) return sm @router.delete("/{scope_model_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_scope_model( scope_model_id: int, db: AsyncSession = Depends(get_db), actor: User = Depends(require_permission("scope_models:delete")), ): sm = await scope_model_crud.get(db, scope_model_id) if sm is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Scope model not found") name = sm.name await scope_model_crud.delete(db, sm) await audit_crud.log( db, actor=actor, action="delete", resource_type="ScopeModel", resource_id=scope_model_id, description=audit_crud.describe_delete("ScopeModel", scope_model_id, name), )