from beanie import PydanticObjectId from fastapi import APIRouter, HTTPException, Depends from fastapi_filter import FilterDepends from fastapi_pagination import Page, add_pagination from fastapi_pagination.ext.motor import paginate from firm.core.depends import get_authed_tenant_registry from firm.core.models import CrudDocument from firm.core.schemas import Writer, Reader def get_crud_router(model: CrudDocument, model_create: Writer, model_read: Reader, model_update: Writer, model_filter): model_name = model.__name__ router = APIRouter() @router.get("/", response_model=Page[model_read], response_description=f"{model_name} records retrieved") async def read_list(filters: model_filter=FilterDepends(model_filter), db=Depends(get_logged_tenant_db_cursor)) -> Page[model_read]: return await paginate(**model.find(db, filters)) async def read_list(filters: model_filter=FilterDepends(model_filter), reg=Depends(get_authed_tenant_registry)) -> Page[model_read]: @router.post("/", response_description=f"{model_name} added to the database") async def create(schema: model_create, reg=Depends(get_authed_tenant_registry)) -> model_read: await schema.validate_foreign_key(reg.db) record = await model.create(reg.db, schema) return model_read.validate_model(record) @router.get("/{record_id}", response_description=f"{model_name} record retrieved") async def read_one(record_id: PydanticObjectId, reg=Depends(get_authed_tenant_registry)) -> model_read: record = await model.get(reg.db, record_id) if not record: raise HTTPException( status_code=404, detail=f"{model_name} record not found!" ) return model_read.from_model(record) @router.put("/{record_id}", response_description=f"{model_name} record updated") async def update(record_id: PydanticObjectId, schema: model_update, reg=Depends(get_authed_tenant_registry)) -> model_read: record = await model.get(reg.db, record_id) if not record: raise HTTPException( status_code=404, detail=f"{model_name} record not found!" ) record = await model.update(reg.db, record, schema) return model_read.from_model(record) @router.delete("/{record_id}", response_description=f"{model_name} record deleted from the database") async def delete(record_id: PydanticObjectId, reg=Depends(get_authed_tenant_registry)) -> dict: record = await model.get(reg.db, record_id) if not record: raise HTTPException( status_code=404, detail=f"{model_name} record not found!" ) await model.delete(reg.db, record) return { "message": f"{model_name} deleted successfully" } add_pagination(router) return router