From de0af28e93d610c70a873ccc7f558f77ad306e34 Mon Sep 17 00:00:00 2001 From: JWittmeyer Date: Thu, 14 Nov 2024 11:46:00 +0100 Subject: [PATCH] Removes unused config parts --- api/misc.py | 20 ------ api/transfer.py | 4 -- app.py | 6 -- base_config.json | 10 +-- config_handler.py | 22 ++---- controller/auth/manager.py | 23 ------ controller/embedding/manager.py | 9 +-- controller/information_source/manager.py | 2 - controller/misc/black_white_demo.py | 89 ------------------------ controller/misc/manager.py | 19 ----- controller/organization/manager.py | 13 ---- controller/payload/payload_scheduler.py | 5 +- exceptions/exceptions.py | 8 --- fast_api/models.py | 8 --- fast_api/routes/embedding.py | 4 +- fast_api/routes/misc.py | 46 ++---------- fast_api/routes/organization.py | 37 +--------- fast_api/routes/project.py | 5 -- middleware/database_session.py | 37 ---------- 19 files changed, 19 insertions(+), 348 deletions(-) delete mode 100644 controller/misc/black_white_demo.py diff --git a/api/misc.py b/api/misc.py index fcdd3c86..6c9602d5 100644 --- a/api/misc.py +++ b/api/misc.py @@ -1,32 +1,12 @@ from starlette.endpoints import HTTPEndpoint from starlette.responses import JSONResponse -from starlette import status from fastapi import Request from config_handler import ( - base_config_json, full_config_json, - get_config_value, ) -class IsManagedRest(HTTPEndpoint): - def get(self, request) -> JSONResponse: - is_managed = get_config_value("is_managed") - return JSONResponse(is_managed, status_code=status.HTTP_200_OK) - - -class IsDemoRest(HTTPEndpoint): - def get(self, request) -> JSONResponse: - is_managed = get_config_value("is_demo") - return JSONResponse(is_managed, status_code=status.HTTP_200_OK) - - class FullConfigRest(HTTPEndpoint): def get(self, request: Request) -> JSONResponse: return full_config_json() - - -class BaseConfigRest(HTTPEndpoint): - def get(self, request: Request) -> JSONResponse: - return base_config_json() diff --git a/api/transfer.py b/api/transfer.py index 72eae0db..15fd5f55 100644 --- a/api/transfer.py +++ b/api/transfer.py @@ -28,7 +28,6 @@ from controller.upload_task import manager as upload_task_manager from controller.auth import manager as auth_manager from controller.transfer import association_transfer_manager -from controller.auth import manager as auth from controller.project import manager as project_manager from controller.attribute import manager as attribute_manager @@ -135,7 +134,6 @@ def get(self, request) -> JSONResponse: class PrepareFileImport(HTTPEndpoint): async def post(self, request) -> JSONResponse: - auth.check_is_demo_without_info() project_id = request.path_params["project_id"] request_body = await request.json() @@ -168,7 +166,6 @@ async def post(self, request) -> JSONResponse: class JSONImport(HTTPEndpoint): async def post(self, request) -> JSONResponse: - auth.check_is_demo_without_info() project_id = request.path_params["project_id"] request_body = await request.json() user_id = request_body["user_id"] @@ -272,7 +269,6 @@ async def post(self, request) -> JSONResponse: class UploadTaskInfo(HTTPEndpoint): def get(self, request) -> JSONResponse: - auth.check_is_demo_without_info() project_id = request.path_params["project_id"] task_id = request.path_params["task_id"] user_id = request.query_params["user_id"] diff --git a/app.py b/app.py index 54d50b18..c8ca9687 100644 --- a/app.py +++ b/app.py @@ -3,10 +3,7 @@ from api.healthcheck import Healthcheck from starlette.middleware import Middleware from api.misc import ( - BaseConfigRest, FullConfigRest, - IsDemoRest, - IsManagedRest, ) from api.project import ProjectDetails from api.transfer import ( @@ -124,7 +121,6 @@ ) routes = [ - Route("/base_config", BaseConfigRest), Route("/full_config", FullConfigRest), Route("/notify/{path:path}", Notify), Route("/healthcheck", Healthcheck), @@ -145,8 +141,6 @@ CognitionPrepareProject, ), Route("/project/{project_id:str}/import/task/{task_id:str}", UploadTaskInfo), - Route("/is_managed", IsManagedRest), - Route("/is_demo", IsDemoRest), Mount("/api", app=fastapi_app, name="REST API"), Mount( "/internal/api", app=fastapi_app_internal, name="INTERNAL REST API" diff --git a/base_config.json b/base_config.json index b82e8f59..8df4b168 100644 --- a/base_config.json +++ b/base_config.json @@ -1,14 +1,8 @@ { - "is_managed": null, - "is_demo": null, - "allow_data_tracking": true, "s3_region": null, + "KERN_S3_ENDPOINT": null, "spacy_downloads": [ "en_core_web_sm", "de_core_news_sm" - ], - "tokens": { - "INTERCOM": "" - }, - "KERN_S3_ENDPOINT": null + ] } \ No newline at end of file diff --git a/config_handler.py b/config_handler.py index 3c4d9f0d..0d236d05 100644 --- a/config_handler.py +++ b/config_handler.py @@ -4,7 +4,6 @@ from notify_handler import notify_others_about_change_thread from fastapi import responses, status -__blacklist_base_config = ["is_managed", "is_demo"] __config = None BASE_CONFIG_PATH = "base_config.json" @@ -100,14 +99,9 @@ def __load_and_remove_outdated_config_keys(): __save_current_config() -def get_config(basic: bool = True) -> Dict[str, Any]: - global __config, __blacklist_base_config - if not basic: - return __config - - return { - key: __config[key] for key in __config if key not in __blacklist_base_config - } +def get_config() -> Dict[str, Any]: + global __config + return __config def change_json(config_data) -> responses.PlainTextResponse: @@ -128,12 +122,4 @@ def change_json(config_data) -> responses.PlainTextResponse: def full_config_json() -> responses.JSONResponse: - return responses.JSONResponse( - status_code=status.HTTP_200_OK, content=get_config(False) - ) - - -def base_config_json() -> responses.JSONResponse: - return responses.JSONResponse( - status_code=status.HTTP_200_OK, content=get_config(True) - ) + return responses.JSONResponse(status_code=status.HTTP_200_OK, content=get_config()) diff --git a/controller/auth/manager.py b/controller/auth/manager.py index 84464290..ed285527 100644 --- a/controller/auth/manager.py +++ b/controller/auth/manager.py @@ -1,10 +1,8 @@ from typing import Any, Dict from fastapi import Request -from config_handler import get_config_value from exceptions.exceptions import ( AuthManagerError, - NotAllowedInDemoError, ProjectAccessError, ) import jwt @@ -14,7 +12,6 @@ from submodules.model import enums, exceptions from submodules.model.business_objects import organization from submodules.model.models import Organization, Project, User -from controller.misc import manager as misc_manager import sqlalchemy DEV_USER_ID = "741df1c2-a531-43b6-b259-df23bc78e9a2" @@ -127,26 +124,6 @@ def check_is_admin(request: Any) -> bool: return False -def check_demo_access(info: Any) -> None: - if not check_is_admin(info.context["request"]) and get_config_value("is_demo"): - check_black_white(info) - - -def check_black_white(info: Any): - black_white = misc_manager.get_black_white_demo() - if str(info.parent_type) == "Mutation": - if info.field_name not in black_white["mutations"]: - raise NotAllowedInDemoError - elif str(info.parent_type) == "Query": - if info.field_name in black_white["queries"]: - raise NotAllowedInDemoError - - -def check_is_demo_without_info() -> None: - if get_config_value("is_demo"): - raise NotAllowedInDemoError - - def check_is_single_organization() -> bool: return len(organization_manager.get_all_organizations()) == 1 diff --git a/controller/embedding/manager.py b/controller/embedding/manager.py index 8183459a..38bb6a2a 100644 --- a/controller/embedding/manager.py +++ b/controller/embedding/manager.py @@ -42,14 +42,11 @@ def get_current_terms_text( return term_text -def get_recommended_encoders(is_managed: bool) -> List[Any]: - # only use is_managed if it is really managed +def get_recommended_encoders() -> List[Any]: # can run into circular import problems if directly resolved here by helper method recommendations = connector.request_listing_recommended_encoders() - if is_managed: - existing_models = model_manager.get_model_provider_info() - else: - existing_models = [] + existing_models = model_manager.get_model_provider_info() + for model in existing_models: not_yet_known = ( len( diff --git a/controller/information_source/manager.py b/controller/information_source/manager.py index 41b81e53..79e05986 100644 --- a/controller/information_source/manager.py +++ b/controller/information_source/manager.py @@ -1,6 +1,5 @@ import os from typing import List -from config_handler import get_config_value from controller.information_source.util import resolve_source_return_type from submodules.model import InformationSource, LabelingTask, enums from submodules.model.business_objects import ( @@ -86,7 +85,6 @@ def delete_information_source(project_id: str, source_id: str) -> None: if ( information_source_item.type == enums.InformationSourceType.ACTIVE_LEARNING.value - and get_config_value("is_managed") ): daemon.run_without_db_token( __delete_active_learner_from_inference_dir, project_id, source_id diff --git a/controller/misc/black_white_demo.py b/controller/misc/black_white_demo.py deleted file mode 100644 index b57e5296..00000000 --- a/controller/misc/black_white_demo.py +++ /dev/null @@ -1,89 +0,0 @@ -from typing import Dict, List - - -def get_black_white_demo() -> Dict[str, List[str]]: - global __whitelist_mutation_demo_parsed - global __blacklist_query_demo_parsed - - if not __whitelist_mutation_demo_parsed: - __parse_black_white_list() - toReturn = {"mutations": [], "queries": []} - for v in __whitelist_mutation_demo_parsed: - toReturn["mutations"].append(v) - for v in __blacklist_query_demo_parsed: - toReturn["queries"].append(v) - - return toReturn - - -def __snake_case_to_camel_case(str: str): - return "".join( - [ - word.title() if idx > 0 else word.lower() - for idx, word in enumerate(str.split("_")) - ] - ) - - -def __parse_black_white_list(): - global __whitelist_mutation_demo - global __blacklist_query_demo - global __whitelist_mutation_demo_parsed - global __blacklist_query_demo_parsed - - tmp = {} - for v in __whitelist_mutation_demo: - tmp[v[0].lower() + v[1:]] = v - __whitelist_mutation_demo_parsed = tmp - tmp = {} - for v in __blacklist_query_demo: - tmp[__snake_case_to_camel_case(v)] = v - __blacklist_query_demo_parsed = tmp - - -# CAUTION: this is not necessarily the class name but often times similar or equal. This is the schema name we would use in gql -__whitelist_mutation_demo = { - "CreateDataSlice", - "UpdateDataSlice", - "DeleteDataSlice", - "CreateOutlierSlice", - "UpdateSliceTypeManual", - "CreateInformationSource", - # "DeleteInformationSource", - "ToggleInformationSource", - "SetAllInformationSourceSelected", - # "UpdateInformationSource", - "CreateKnowledgeBase", - # "DeleteKnowledgeBase", - # "UpdateKnowledgeBase", - "AddTermToKnowledgeBase", - "PasteKnowledgeTerms", - "UpdateKnowledgeTerm", - "DeleteKnowledgeTerm", - "BlacklistTerm", - # "CreateLabelingTaskLabel", - "UpdateLabelColor", - "UpdateLabelHotkey", - # "DeleteLabelingTaskLabel", - "PostEvent", - "CreateNotification", - "AddClassificationLabelsToRecord", - "AddExtractionLabelToRecord", - "SetGoldStarAnnotationForTask", - "DeleteRecordLabelAssociationByIds", - "DeleteGoldStarAssociationForTask", - "UpdateRlaIsValidManual", -} - - -# Function names without resolve_ -__blacklist_query_demo = { - "upload_credentials_and_id", - "upload_task_by_id", - "prepare_project_export", -} - - -# Parsed to a dict with gql query names -__whitelist_mutation_demo_parsed = None -__blacklist_query_demo_parsed = None diff --git a/controller/misc/manager.py b/controller/misc/manager.py index 38c3bfcf..c8db7771 100644 --- a/controller/misc/manager.py +++ b/controller/misc/manager.py @@ -1,6 +1,4 @@ from typing import Any, Dict, List -from config_handler import change_json, get_config_value -from controller.misc import black_white_demo from fast_api.types import ServiceVersionResult from submodules.model.global_objects import customer_button from datetime import datetime @@ -19,23 +17,6 @@ BASE_URI_UPDATER = os.getenv("UPDATER") -def check_is_managed() -> bool: - return get_config_value("is_managed") - - -def check_is_demo() -> bool: - return get_config_value("is_demo") - - -def update_config(dict_str: str) -> None: - config_data = {"dict_string": dict_str} - return change_json(config_data) - - -def get_black_white_demo() -> Dict[str, List[str]]: - return black_white_demo.get_black_white_demo() - - def get_version_overview() -> List[ServiceVersionResult]: updater_version_overview = __updater_version_overview() date_format = "%Y-%m-%dT%H:%M:%S.%f" # 2022-09-06T12:10:39.167397 diff --git a/controller/organization/manager.py b/controller/organization/manager.py index 4ec72419..5bb805e0 100644 --- a/controller/organization/manager.py +++ b/controller/organization/manager.py @@ -1,5 +1,4 @@ from typing import Any, List, Dict, Optional, Union -from config_handler import get_config_value from submodules.model import enums from submodules.model.business_objects import organization, general, user @@ -101,18 +100,6 @@ def get_overview_stats(org_id: str) -> List[Dict[str, Union[str, int]]]: return organization.get_organization_overview_stats(org_id) -def can_create_local(org: bool = True) -> bool: - if get_config_value("is_managed"): - return False - existing_orgs = organization.get_all() - checkvalue = 0 if org else 1 - if len(existing_orgs) != checkvalue: - return False - if user.get_count_assigned() != 0: - return False - return True - - def __check_notification(org_id: str, key: str, value: Any): if key in ["gdpr_compliant"]: notification.send_organization_update( diff --git a/controller/payload/payload_scheduler.py b/controller/payload/payload_scheduler.py index 2a1db438..420b8f2c 100644 --- a/controller/payload/payload_scheduler.py +++ b/controller/payload/payload_scheduler.py @@ -12,7 +12,6 @@ from dateutil import parser import datetime -from config_handler import get_config_value from exceptions.exceptions import PayloadSchedulerError from submodules.model import enums from submodules.model.business_objects import ( @@ -509,9 +508,7 @@ def read_container_logs_thread( def get_inference_dir() -> str: - if get_config_value("is_managed"): - return os.getenv("INFERENCE_DIR") - return None + return os.getenv("INFERENCE_DIR") def update_records( diff --git a/exceptions/exceptions.py b/exceptions/exceptions.py index ce743be7..fa7a4102 100644 --- a/exceptions/exceptions.py +++ b/exceptions/exceptions.py @@ -18,14 +18,6 @@ class MissingArgumentsException(Exception): pass -class NotAllowedInDemoError(Exception): - pass - - -class NotAllowedInOpenSourceError(Exception): - pass - - class BadPasswordError(Exception): pass diff --git a/fast_api/models.py b/fast_api/models.py index baaeb25a..6385027e 100644 --- a/fast_api/models.py +++ b/fast_api/models.py @@ -210,10 +210,6 @@ class ArchiveAdminMessageBody(BaseModel): archived_reason: StrictStr -class UpdateConfigBody(BaseModel): - dict_str: StrictStr - - class ChangeUserRoleBody(BaseModel): user_id: StrictStr role: StrictStr @@ -444,7 +440,3 @@ class UpdateCustomerButton(BaseModel): location: Optional[CustomerButtonLocation] = None visible: Optional[StrictBool] = None config: Optional[Dict[StrictStr, Any]] = None - - -class ChangeRequest(BaseModel): - dict_string: str diff --git a/fast_api/routes/embedding.py b/fast_api/routes/embedding.py index 9f722f86..5c7d36d0 100644 --- a/fast_api/routes/embedding.py +++ b/fast_api/routes/embedding.py @@ -2,7 +2,6 @@ from fast_api.models import CreateEmbeddingBody, UpdateEmbeddingBody from fast_api.routes.client_response import pack_json_result -from controller.misc import manager as misc from fastapi import APIRouter, Body, Depends, Request from controller.embedding import manager from controller.task_master import manager as task_master_manager @@ -30,8 +29,7 @@ def get_embedding_platforms(): @router.get("/recommended-encoders") def data_slices(request: Request, project_id: Optional[str] = None) -> List: - is_managed = misc.check_is_managed() - data = manager.get_recommended_encoders(is_managed) + data = manager.get_recommended_encoders() for v in data: v["applicability"] = json.dumps(v["applicability"]) return pack_json_result({"data": {"recommendedEncoders": data}}) diff --git a/fast_api/routes/misc.py b/fast_api/routes/misc.py index 44c741c9..54adf984 100644 --- a/fast_api/routes/misc.py +++ b/fast_api/routes/misc.py @@ -1,11 +1,8 @@ import json -from fastapi import APIRouter, Body, Request, status, responses +from fastapi import APIRouter, Body, Request, status from fastapi.responses import PlainTextResponse -from config_handler import base_config_json, change_json -from exceptions.exceptions import ProjectAccessError from fast_api.models import ( CancelTaskBody, - ChangeRequest, ModelProviderDeleteModelBody, ModelProviderDownloadModelBody, CreateCustomerButton, @@ -15,7 +12,6 @@ from typing import Dict, Optional from controller.auth import manager as auth from controller.misc import manager -from controller.misc import manager as misc from controller.monitor import manager as controller_manager from controller.model_provider import manager as model_provider_manager from controller.task_master import manager as task_master_manager @@ -39,32 +35,6 @@ def get_is_admin(request: Request) -> Dict: return pack_json_result({"data": {"isAdmin": data}}) -@router.post("/change-config") -def change_config_r(body: ChangeRequest = Body(...)): - try: - config_data = json.loads(body.dict_string) - return change_json(config_data) - except Exception as e: - return responses.PlainTextResponse( - f"Error: {str(e)}", status_code=status.HTTP_500_INTERNAL_SERVER_ERROR - ) - - -@router.get("/base-config-default") -def get_base_config() -> Dict: - return base_config_json() - - -@router.get("/is-demo") -def get_is_demo(request: Request) -> Dict: - is_demo = False - try: - auth.check_demo_access(request.state.info) - except Exception: - is_demo = True - return pack_json_result({"data": {"isDemo": is_demo}}) - - @router.get("/version-overview") def get_version_overview(request: Request) -> Dict: data = manager.get_version_overview() @@ -81,11 +51,8 @@ def has_updates(request: Request) -> Dict: def model_provider_delete_model( request: Request, body: ModelProviderDeleteModelBody = Body(...) ): - if misc.check_is_managed(): - if not auth.check_is_single_organization(): - auth.check_admin_access(request.state.info) - else: - raise ProjectAccessError("Not allowed in open source version.") + if not auth.check_is_single_organization(): + auth.check_admin_access(request.state.info) model_provider_manager.model_provider_delete_model(body.model_name) return pack_json_result({"data": {"modelProviderDeleteModel": {"ok": True}}}) @@ -95,11 +62,8 @@ def model_provider_delete_model( def model_provider_download_model( request: Request, body: ModelProviderDownloadModelBody = Body(...) ): - if misc.check_is_managed(): - if not auth.check_is_single_organization(): - auth.check_admin_access(request.state.info) - else: - raise ProjectAccessError("Not allowed in open source version.") + if not auth.check_is_single_organization(): + auth.check_admin_access(request.state.info) model_provider_manager.model_provider_download_model(body.model_name) return pack_json_result({"data": {"modelProviderDownloadModel": {"ok": True}}}) diff --git a/fast_api/routes/organization.py b/fast_api/routes/organization.py index 076dfb75..8314d8e2 100644 --- a/fast_api/routes/organization.py +++ b/fast_api/routes/organization.py @@ -1,6 +1,5 @@ import json from fastapi import APIRouter, Request, Body -from config_handler import get_config_value from fast_api.models import ( AddUserToOrganizationBody, ArchiveAdminMessageBody, @@ -12,7 +11,6 @@ DeleteUserBody, MappedSortedPaginatedUsers, RemoveUserToOrganizationBody, - UpdateConfigBody, UserLanguageDisplay, ) from controller.auth import manager as auth_manager @@ -24,7 +22,6 @@ from controller.admin_message import manager as admin_message_manager from controller.organization import manager as organization_manager from controller.user import manager as user_manager -from controller.misc import manager as misc from fast_api.routes.client_response import get_silent_success, pack_json_result from submodules.model.business_objects import organization @@ -139,11 +136,7 @@ def all_admin_messages(request: Request, limit: int = 100) -> str: @router.post("/create-organization") def create_organization(request: Request, body: CreateOrganizationBody = Body(...)): - if get_config_value("is_managed"): - auth_manager.check_admin_access(request.state.info) - else: - if not organization_manager.can_create_local(): - auth_manager.check_admin_access(request.state.info) + auth_manager.check_admin_access(request.state.info) organization = organization_manager.create_organization(body.name) return {"data": {"createOrganization": {"organization": organization}}} @@ -152,11 +145,7 @@ def create_organization(request: Request, body: CreateOrganizationBody = Body(.. def add_user_to_organization( request: Request, body: AddUserToOrganizationBody = Body(...) ): - if get_config_value("is_managed"): - auth_manager.check_admin_access(request.state.info) - else: - if not organization_manager.can_create_local(False): - auth_manager.check_admin_access(request.state.info) + auth_manager.check_admin_access(request.state.info) user_manager.update_organization_of_user(body.organization_name, body.user_mail) return pack_json_result({"data": {"addUserToOrganization": {"ok": True}}}) @@ -172,31 +161,11 @@ def remove_user_from_organization( @router.post("/change-organization") def change_organization(request: Request, body: ChangeOrganizationBody = Body(...)): - if get_config_value("is_managed"): - auth_manager.check_admin_access(request.state.info) + auth_manager.check_admin_access(request.state.info) organization_manager.change_organization(body.org_id, json.loads(body.changes)) return pack_json_result({"data": {"changeOrganization": {"ok": True}}}) -@router.post("/update-config") -def update_config(request: Request, body: UpdateConfigBody = Body(...)): - if misc.check_is_managed(): - print( - "config should only be changed for open source/local version to prevent limit issues" - ) - return - misc.update_config(body.dict_str) - orgs = organization.get_all() - if not orgs or len(orgs) != 1: - print("local version should only have one organization") - return - - for org in orgs: - # send to all so all are notified about the change - notification.send_organization_update(None, "config_updated", True, str(org.id)) - return pack_json_result({"data": {"updateConfig": {"ok": True}}}) - - @router.get("/user-roles") def get_user_roles(request: Request): auth_manager.check_admin_access(request.state.info) diff --git a/fast_api/routes/project.py b/fast_api/routes/project.py index ad1a5ccd..3b0425ce 100644 --- a/fast_api/routes/project.py +++ b/fast_api/routes/project.py @@ -31,8 +31,6 @@ to_frontend_obj_raw, ) from util import notification -from controller.misc import manager as misc -from exceptions.exceptions import NotAllowedInOpenSourceError from submodules.model.business_objects import notification as notification_model from submodules.model.business_objects import tokenization, task_queue @@ -292,9 +290,6 @@ def record_export_by_project_id(project_id: str) -> str: @router.get("/model-provider-info") def get_model_provider_info(request: Request) -> Dict: - if not misc.check_is_managed(): - raise NotAllowedInOpenSourceError - data = model_manager.get_model_provider_info() return pack_json_result({"data": {"modelProviderInfo": data}}) diff --git a/middleware/database_session.py b/middleware/database_session.py index 8b44548a..cb3f52dc 100644 --- a/middleware/database_session.py +++ b/middleware/database_session.py @@ -1,10 +1,5 @@ import logging from fastapi import Request -from fastapi.responses import JSONResponse -from exceptions.exceptions import ( - DatabaseSessionError, - NotAllowedInDemoError, -) from fast_api.routes.fastapi_resolve_info import FastAPIResolveInfo from middleware.query_mapping import path_query_map from submodules.model.business_objects import general @@ -26,11 +21,6 @@ async def handle_db_session(request: Request, call_next): request.state.info = info request.state.parsed = {} - if request.url.hostname != "localhost" or request.url.port != 7051: - access_response = _check_access(request, info) - if access_response is not None: - return access_response - log_request = auth_manager.extract_state_info(request, "log_request") length = request.headers.get("content-length") @@ -50,33 +40,6 @@ async def handle_db_session(request: Request, call_next): general.remove_and_refresh_session(session_token) -def _check_access(request, info): - try: - auth_manager.check_demo_access(info) - except NotAllowedInDemoError: - return JSONResponse( - status_code=401, - content={"message": "Unauthorized access"}, - ) - except DatabaseSessionError as e: - return JSONResponse( - status_code=400, - content={"message": e.message}, - ) - except ValueError as e: - return JSONResponse( - status_code=400, - content={"message": str(e)}, - ) - except Exception: - return JSONResponse( - status_code=500, - content={"message": "Internal server error"}, - ) - - return None - - def _prepare_info(request): field_name = None parent_type = None