The PM panel (PmPanelPage -> iframe /pm/) needs the project-management platform served at /pm/ on the ERP domain. Source: org repo Aramesh/PM, branch feature/project-management-platform. Update via: git subtree pull --prefix=pm aramesh-pm feature/project-management-platform --squash
54 lines
1.4 KiB
Python
54 lines
1.4 KiB
Python
"""PM error envelope — same contract as the ERP: {"error": {code, message, field}}."""
|
|
from fastapi import FastAPI, Request
|
|
from fastapi.responses import JSONResponse
|
|
|
|
|
|
class AppError(Exception):
|
|
status_code = 400
|
|
code = "BAD_REQUEST"
|
|
|
|
def __init__(self, message: str, field: str | None = None, code: str | None = None):
|
|
super().__init__(message)
|
|
self.message = message
|
|
self.field = field
|
|
if code:
|
|
self.code = code
|
|
|
|
@property
|
|
def body(self) -> dict:
|
|
error = {"code": self.code, "message": self.message}
|
|
if self.field is not None:
|
|
error["field"] = self.field
|
|
return {"error": error}
|
|
|
|
|
|
class AuthError(AppError):
|
|
status_code, code = 401, "UNAUTHORIZED"
|
|
|
|
|
|
class ValidationError(AppError):
|
|
status_code, code = 400, "VALIDATION_ERROR"
|
|
|
|
|
|
class ForbiddenError(AppError):
|
|
status_code, code = 403, "FORBIDDEN"
|
|
|
|
|
|
class NotFoundError(AppError):
|
|
status_code, code = 404, "NOT_FOUND"
|
|
|
|
|
|
class ConflictError(AppError):
|
|
status_code, code = 409, "CONFLICT"
|
|
|
|
|
|
class UpstreamError(AppError):
|
|
"""Upstream service unreachable / errored."""
|
|
status_code, code = 503, "UPSTREAM_UNAVAILABLE"
|
|
|
|
|
|
def install_error_handlers(app: FastAPI) -> None:
|
|
@app.exception_handler(AppError)
|
|
async def _app_error(_: Request, exc: AppError) -> JSONResponse:
|
|
return JSONResponse(status_code=exc.status_code, content=exc.body)
|