fix: bound organization aggregate responses
This commit is contained in:
@@ -55,6 +55,8 @@ from .schemas import (
|
|||||||
|
|
||||||
|
|
||||||
router = APIRouter(prefix="/organizations", tags=["organizations"])
|
router = APIRouter(prefix="/organizations", tags=["organizations"])
|
||||||
|
ORGANIZATION_MODEL_COLLECTION_LIMIT = 5_000
|
||||||
|
ORGANIZATION_MODEL_TOTAL_LIMIT = 20_000
|
||||||
|
|
||||||
ORG_READ_SCOPES = (
|
ORG_READ_SCOPES = (
|
||||||
"organizations:model:read",
|
"organizations:model:read",
|
||||||
@@ -335,15 +337,90 @@ def get_organization_model(
|
|||||||
principal: ApiPrincipal = Depends(require_any_scope(*ORG_READ_SCOPES)),
|
principal: ApiPrincipal = Depends(require_any_scope(*ORG_READ_SCOPES)),
|
||||||
) -> OrganizationModelResponse:
|
) -> OrganizationModelResponse:
|
||||||
tenant_id = _tenant_id(principal)
|
tenant_id = _tenant_id(principal)
|
||||||
return OrganizationModelResponse(
|
unit_types = _bounded_organization_rows(
|
||||||
unit_types=[_item_unit_type(item) for item in session.query(OrganizationUnitType).filter(OrganizationUnitType.tenant_id == tenant_id).order_by(OrganizationUnitType.name.asc()).all()],
|
session.query(OrganizationUnitType)
|
||||||
structures=[_item_structure(item) for item in session.query(OrganizationStructure).filter(OrganizationStructure.tenant_id == tenant_id).order_by(OrganizationStructure.name.asc()).all()],
|
.filter(OrganizationUnitType.tenant_id == tenant_id)
|
||||||
relation_types=[_item_relation_type(item) for item in session.query(OrganizationRelationType).filter(OrganizationRelationType.tenant_id == tenant_id).order_by(OrganizationRelationType.name.asc()).all()],
|
.order_by(OrganizationUnitType.name.asc()),
|
||||||
units=[_item_unit(item) for item in session.query(OrganizationUnit).filter(OrganizationUnit.tenant_id == tenant_id).order_by(OrganizationUnit.name.asc()).all()],
|
"unit types",
|
||||||
relations=[_item_relation(item) for item in session.query(OrganizationRelation).filter(OrganizationRelation.tenant_id == tenant_id).order_by(OrganizationRelation.created_at.asc()).all()],
|
|
||||||
function_types=[_item_function_type(item) for item in session.query(OrganizationFunctionType).filter(OrganizationFunctionType.tenant_id == tenant_id).order_by(OrganizationFunctionType.name.asc()).all()],
|
|
||||||
functions=[_item_function(item) for item in session.query(OrganizationFunction).filter(OrganizationFunction.tenant_id == tenant_id).order_by(OrganizationFunction.name.asc()).all()],
|
|
||||||
)
|
)
|
||||||
|
structures = _bounded_organization_rows(
|
||||||
|
session.query(OrganizationStructure)
|
||||||
|
.filter(OrganizationStructure.tenant_id == tenant_id)
|
||||||
|
.order_by(OrganizationStructure.name.asc()),
|
||||||
|
"structures",
|
||||||
|
)
|
||||||
|
relation_types = _bounded_organization_rows(
|
||||||
|
session.query(OrganizationRelationType)
|
||||||
|
.filter(OrganizationRelationType.tenant_id == tenant_id)
|
||||||
|
.order_by(OrganizationRelationType.name.asc()),
|
||||||
|
"relation types",
|
||||||
|
)
|
||||||
|
units = _bounded_organization_rows(
|
||||||
|
session.query(OrganizationUnit)
|
||||||
|
.filter(OrganizationUnit.tenant_id == tenant_id)
|
||||||
|
.order_by(OrganizationUnit.name.asc()),
|
||||||
|
"units",
|
||||||
|
)
|
||||||
|
relations = _bounded_organization_rows(
|
||||||
|
session.query(OrganizationRelation)
|
||||||
|
.filter(OrganizationRelation.tenant_id == tenant_id)
|
||||||
|
.order_by(OrganizationRelation.created_at.asc()),
|
||||||
|
"relations",
|
||||||
|
)
|
||||||
|
function_types = _bounded_organization_rows(
|
||||||
|
session.query(OrganizationFunctionType)
|
||||||
|
.filter(OrganizationFunctionType.tenant_id == tenant_id)
|
||||||
|
.order_by(OrganizationFunctionType.name.asc()),
|
||||||
|
"function types",
|
||||||
|
)
|
||||||
|
functions = _bounded_organization_rows(
|
||||||
|
session.query(OrganizationFunction)
|
||||||
|
.filter(OrganizationFunction.tenant_id == tenant_id)
|
||||||
|
.order_by(OrganizationFunction.name.asc()),
|
||||||
|
"functions",
|
||||||
|
)
|
||||||
|
if sum(
|
||||||
|
len(items)
|
||||||
|
for items in (
|
||||||
|
unit_types,
|
||||||
|
structures,
|
||||||
|
relation_types,
|
||||||
|
units,
|
||||||
|
relations,
|
||||||
|
function_types,
|
||||||
|
functions,
|
||||||
|
)
|
||||||
|
) > ORGANIZATION_MODEL_TOTAL_LIMIT:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE,
|
||||||
|
detail=(
|
||||||
|
"The organization model is too large for the aggregate "
|
||||||
|
"endpoint and cannot be returned as one response."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return OrganizationModelResponse(
|
||||||
|
unit_types=[_item_unit_type(item) for item in unit_types],
|
||||||
|
structures=[_item_structure(item) for item in structures],
|
||||||
|
relation_types=[_item_relation_type(item) for item in relation_types],
|
||||||
|
units=[_item_unit(item) for item in units],
|
||||||
|
relations=[_item_relation(item) for item in relations],
|
||||||
|
function_types=[_item_function_type(item) for item in function_types],
|
||||||
|
functions=[_item_function(item) for item in functions],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _bounded_organization_rows(query: Any, label: str) -> list[Any]:
|
||||||
|
rows = query.limit(ORGANIZATION_MODEL_COLLECTION_LIMIT + 1).all()
|
||||||
|
if len(rows) > ORGANIZATION_MODEL_COLLECTION_LIMIT:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE,
|
||||||
|
detail=(
|
||||||
|
f"The organization model has more than "
|
||||||
|
f"{ORGANIZATION_MODEL_COLLECTION_LIMIT} {label} and cannot "
|
||||||
|
"be returned as one response."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return rows
|
||||||
|
|
||||||
|
|
||||||
@router.post("/unit-types", response_model=OrganizationUnitTypeItem, status_code=status.HTTP_201_CREATED)
|
@router.post("/unit-types", response_model=OrganizationUnitTypeItem, status_code=status.HTTP_201_CREATED)
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-router-dom": "^7.1.1",
|
"react-router-dom": ">=7.18.2 <8",
|
||||||
"typescript": "^5.7.2",
|
"typescript": "^5.7.2",
|
||||||
"vite": "^6.0.6"
|
"vite": "^6.0.6"
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user