redis implemntations and api setup completed
This commit is contained in:
parent
32022ca521
commit
3d5a43220e
|
|
@ -0,0 +1,35 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="PyInterpreterInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ignoredPackages">
|
||||
<value>
|
||||
<list size="21">
|
||||
<item index="0" class="java.lang.String" itemvalue="rsa" />
|
||||
<item index="1" class="java.lang.String" itemvalue="pydantic" />
|
||||
<item index="2" class="java.lang.String" itemvalue="alembic" />
|
||||
<item index="3" class="java.lang.String" itemvalue="starlette-context" />
|
||||
<item index="4" class="java.lang.String" itemvalue="pymongo" />
|
||||
<item index="5" class="java.lang.String" itemvalue="arrow" />
|
||||
<item index="6" class="java.lang.String" itemvalue="unidecode" />
|
||||
<item index="7" class="java.lang.String" itemvalue="python-dotenv" />
|
||||
<item index="8" class="java.lang.String" itemvalue="psycopg2-binary" />
|
||||
<item index="9" class="java.lang.String" itemvalue="cryptography" />
|
||||
<item index="10" class="java.lang.String" itemvalue="requests" />
|
||||
<item index="11" class="java.lang.String" itemvalue="redis" />
|
||||
<item index="12" class="java.lang.String" itemvalue="sqlalchemy" />
|
||||
<item index="13" class="java.lang.String" itemvalue="pandas" />
|
||||
<item index="14" class="java.lang.String" itemvalue="fastapi" />
|
||||
<item index="15" class="java.lang.String" itemvalue="Deprecated" />
|
||||
<item index="16" class="java.lang.String" itemvalue="faker" />
|
||||
<item index="17" class="java.lang.String" itemvalue="textdistance" />
|
||||
<item index="18" class="java.lang.String" itemvalue="uvicorn" />
|
||||
<item index="19" class="java.lang.String" itemvalue="redmail" />
|
||||
<item index="20" class="java.lang.String" itemvalue="sqlalchemy-mixins" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/wag-managment-api-service-version-5.iml" filepath="$PROJECT_DIR$/.idea/wag-managment-api-service-version-5.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
<component name="PyDocumentationSettings">
|
||||
<option name="format" value="PLAIN" />
|
||||
<option name="myDocStringFormat" value="Plain" />
|
||||
</component>
|
||||
<component name="TestRunnerService">
|
||||
<option name="PROJECT_TEST_RUNNER" value="py.test" />
|
||||
</component>
|
||||
</module>
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AutoImportSettings">
|
||||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="b5202e0c-6ddf-4a56-a13a-e18798c4c7cf" name="Changes" comment="">
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/AllApiNeeds/app.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/AllApiNeeds/app_handler.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/AllApiNeeds/application/__init__.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/AllApiNeeds/application/app.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/AllApiNeeds/create_file.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/AllApiNeeds/create_routes.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/AllApiNeeds/middleware/__init__.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/AllApiNeeds/middleware/auth_middleware.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/AllApiNeeds/middleware/function_wrappers.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/AllApiNeeds/middleware/token_event_middleware.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/AllApiNeeds/open_api_creator.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/AllConfigs/Email/configs.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/AllConfigs/Email/configs.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/AllConfigs/NoSqlDatabase/configs.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/AllConfigs/NoSqlDatabase/configs.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/AllConfigs/Redis/configs.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/AllConfigs/Redis/configs.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/AllConfigs/SqlDatabase/configs.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/AllConfigs/SqlDatabase/configs.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/AllConfigs/Token/config.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/AllConfigs/Token/config.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiLibrary/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiLibrary/__init__.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiLibrary/date_time_actions/date_functions.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiLibrary/date_time_actions/date_functions.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiLibrary/token/password_module.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiLibrary/token/password_module.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiServices/Login/user_login_handler.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiServices/Login/user_login_handler.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiServices/Token/token_handler.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiServices/Token/token_handler.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiServices/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiServices/__init__.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/account_records.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/account_records.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/address.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/address.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/application.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/application.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/area.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/area.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/authentication.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/authentication.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/base_validations.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/base_validations.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/build_living_space.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/build_living_space.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/build_part.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/build_part.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/building.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/building.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/company.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/company.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/core_request_validations.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/core_request_validations.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/decision_book.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/decision_book.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/departments.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/departments.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/employee.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/employee.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/events.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/events.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/modules.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/modules.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/people.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/people.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/project_decision_book.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/project_decision_book.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/rules.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/rules.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/services.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/services.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/staff.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/staff.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/user.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/user.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Response/default_response.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Response/default_response.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ErrorHandlers/ErrorHandlers/api_exc_handler.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ErrorHandlers/ErrorHandlers/api_exc_handler.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ErrorHandlers/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ErrorHandlers/__init__.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/ErrorHandlers/bases.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ErrorHandlers/bases.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/account/account.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/account/account.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/account/iban.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/account/iban.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/building/budget.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/building/budget.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/building/build.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/building/build.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/building/decision_book.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/building/decision_book.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/company/company.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/company/company.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/company/department.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/company/department.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/company/employee.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/company/employee.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/event/event.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/event/event.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/identity/identity.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/identity/identity.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/rules/rules.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/rules/rules.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/LanguageModels/Errors/merge_all_error_languages.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/LanguageModels/Errors/merge_all_error_languages.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/Schemas/account/account.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/Schemas/account/account.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/Schemas/building/build.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/Schemas/building/build.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/Schemas/building/decision_book.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/Schemas/building/decision_book.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/Schemas/company/company.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/Schemas/company/company.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/Schemas/company/employee.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/Schemas/company/employee.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/Schemas/event/event.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/Schemas/event/event.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/Schemas/identity/identity.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/Schemas/identity/identity.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ApiLayers/Schemas/rules/rules.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/Schemas/rules/rules.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/DockerApiServices/AuthServiceApi/Dockerfile" beforeDir="false" afterPath="$PROJECT_DIR$/DockerApiServices/AuthServiceApi/Dockerfile" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/DockerApiServices/EventServiceApi/Dockerfile" beforeDir="false" afterPath="$PROJECT_DIR$/DockerApiServices/EventServiceApi/Dockerfile" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/DockerApiServices/ValidationServiceApi/Dockerfile" beforeDir="false" afterPath="$PROJECT_DIR$/DockerApiServices/ValidationServiceApi/Dockerfile" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Events/AllEvents/authentication/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/AllEvents/authentication/__init__.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Events/AllEvents/authentication/auth/api_events.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/AllEvents/authentication/auth/api_events.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Events/AllEvents/authentication/auth/auth.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/AllEvents/authentication/auth/auth.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Events/AllEvents/authentication/auth/cluster.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/AllEvents/authentication/auth/cluster.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Events/AllEvents/authentication/auth/function_handlers.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/AllEvents/authentication/auth/function_handlers.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Events/AllEvents/authentication/auth/info.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/AllEvents/authentication/auth/info.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Events/AllEvents/authentication/auth/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/AllEvents/authentication/auth/models.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Events/AllEvents/events/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/AllEvents/events/__init__.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Events/AllEvents/validations/validation/validation.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/AllEvents/validations/validation/validation.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Events/Engine/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/Engine/__init__.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Events/Engine/abstract_class.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/Engine/abstract_class.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Events/Engine/set_defaults/run.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/Engine/set_defaults/run.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Events/Engine/set_defaults/setClusters.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/Engine/set_defaults/setClusters.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Events/abstract_class.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Events/abstract_class_old.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Scratches/endpoint.py" beforeDir="false" afterPath="$PROJECT_DIR$/Scratches/endpoint.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Services/PostgresDb/Models/core_alchemy.py" beforeDir="false" afterPath="$PROJECT_DIR$/Services/PostgresDb/Models/core_alchemy.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Services/PostgresDb/Models/crud_alchemy.py" beforeDir="false" afterPath="$PROJECT_DIR$/Services/PostgresDb/Models/crud_alchemy.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Services/PostgresDb/Models/filter_functions.py" beforeDir="false" afterPath="$PROJECT_DIR$/Services/PostgresDb/Models/filter_functions.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Services/PostgresDb/Models_old/alchemy_response.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Services/PostgresDb/Models_old/base_model.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Services/PostgresDb/Models_old/filter_functions.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Services/PostgresDb/Models_old/mixins.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Services/PostgresDb/Models_old/query.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Services/PostgresDb/Models_old/response.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Services/PostgresDb/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/Services/PostgresDb/__init__.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Services/PostgresDb/database.py" beforeDir="false" afterPath="$PROJECT_DIR$/Services/PostgresDb/database.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Services/Redis/Actions/actions.py" beforeDir="false" afterPath="$PROJECT_DIR$/Services/Redis/Actions/actions.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Services/Redis/Models/row.py" beforeDir="false" afterPath="$PROJECT_DIR$/Services/Redis/Models/row.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Services/Redis/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/Services/Redis/__init__.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Services/Redis/conn.py" beforeDir="false" afterPath="$PROJECT_DIR$/Services/Redis/conn.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/docker-compose-services.yml" beforeDir="false" afterPath="$PROJECT_DIR$/docker-compose-services.yml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/docs/improvements/validation_service/backend/unified_schema_service.py" beforeDir="false" afterPath="$PROJECT_DIR$/docs/improvements/validation_service/backend/unified_schema_service.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/trash/auth_old.py" beforeDir="false" afterPath="$PROJECT_DIR$/trash/auth_old.py" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="ProjectColorInfo"><![CDATA[{
|
||||
"associatedIndex": 4
|
||||
}]]></component>
|
||||
<component name="ProjectId" id="2s7vXt8ZNmztWMeL9tjyT9ledZJ" />
|
||||
<component name="ProjectViewState">
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent"><![CDATA[{
|
||||
"keyToString": {
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"RunOnceActivity.git.unshallow": "true",
|
||||
"git-widget-placeholder": "development",
|
||||
"last_opened_file_path": "/home/berkay/git-gitea-evyos/wag-managment-api-service-version-5"
|
||||
}
|
||||
}]]></component>
|
||||
<component name="RunManager">
|
||||
<configuration name="events_file" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
||||
<module name="wag-managment-api-service-version-5" />
|
||||
<option name="ENV_FILES" value="" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="PARENT_ENVS" value="true" />
|
||||
<envs>
|
||||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/DockerApiServices/AuthServiceApi" />
|
||||
<option name="IS_MODULE_SDK" value="true" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/DockerApiServices/AuthServiceApi/events_file.py" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||
<option name="EMULATE_TERMINAL" value="false" />
|
||||
<option name="MODULE_MODE" value="false" />
|
||||
<option name="REDIRECT_INPUT" value="false" />
|
||||
<option name="INPUT_FILE" value="" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<recent_temporary>
|
||||
<list>
|
||||
<item itemvalue="Python.events_file" />
|
||||
</list>
|
||||
</recent_temporary>
|
||||
</component>
|
||||
<component name="SharedIndexes">
|
||||
<attachedChunks>
|
||||
<set>
|
||||
<option value="bundled-python-sdk-1b1018131e27-aa17d162503b-com.jetbrains.pycharm.community.sharedIndexes.bundled-PC-243.22562.180" />
|
||||
</set>
|
||||
</attachedChunks>
|
||||
</component>
|
||||
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="Default task">
|
||||
<changelist id="b5202e0c-6ddf-4a56-a13a-e18798c4c7cf" name="Changes" comment="" />
|
||||
<created>1737819471396</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1737819471396</updated>
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -1 +0,0 @@
|
|||
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
"""
|
||||
Base FastAPI application configuration.
|
||||
"""
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
|
||||
|
||||
def create_app() -> FastAPI:
|
||||
app = FastAPI(title="API Service")
|
||||
|
||||
# Configure CORS
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
return app
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
"""
|
||||
FastAPI Application Factory Module
|
||||
|
||||
This module provides functionality to create and configure a FastAPI application with:
|
||||
- Custom OpenAPI schema configuration
|
||||
- Security scheme configuration for Bearer authentication
|
||||
- Automatic router registration
|
||||
- Response class configuration
|
||||
- Security requirements for protected endpoints
|
||||
"""
|
||||
|
||||
from typing import Any, Dict, List, Tuple
|
||||
from fastapi import FastAPI, APIRouter
|
||||
from fastapi.responses import JSONResponse, RedirectResponse
|
||||
from fastapi.openapi.utils import get_openapi
|
||||
|
||||
from AllConfigs.Token.config import Auth
|
||||
from AllConfigs.main import MainConfig as Config
|
||||
|
||||
from create_routes import get_all_routers
|
||||
|
||||
|
||||
def setup_security_schema() -> Dict[str, Any]:
|
||||
"""
|
||||
Configure security schema for the OpenAPI documentation.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: Security schema configuration
|
||||
"""
|
||||
return {
|
||||
"components": {
|
||||
"securitySchemes": {
|
||||
"Bearer Auth": {
|
||||
"type": "apiKey",
|
||||
"in": "header",
|
||||
"name": Auth.ACCESS_TOKEN_TAG,
|
||||
"description": "Enter: **'Bearer <JWT>'**, where JWT is the access token",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def configure_route_security(
|
||||
path: str, method: str, schema: Dict[str, Any], protected_paths: List[str]
|
||||
) -> None:
|
||||
"""
|
||||
Configure security requirements for a specific route.
|
||||
|
||||
Args:
|
||||
path: Route path
|
||||
method: HTTP method
|
||||
schema: OpenAPI schema to modify
|
||||
protected_paths: List of paths that require authentication
|
||||
"""
|
||||
if path in protected_paths:
|
||||
if "paths" in schema and path in schema["paths"]:
|
||||
if method.lower() in schema["paths"][path]:
|
||||
schema["paths"][path][method.lower()]["security"] = [{"Bearer": []}]
|
||||
|
||||
|
||||
def create_app() -> FastAPI:
|
||||
"""
|
||||
Create and configure a FastAPI application with dynamic route creation.
|
||||
|
||||
Returns:
|
||||
FastAPI: Configured FastAPI application instance
|
||||
"""
|
||||
|
||||
from open_api_creator import create_openapi_schema
|
||||
|
||||
# Get all routers and protected routes using the dynamic route creation
|
||||
|
||||
app = FastAPI(
|
||||
title=Config.TITLE,
|
||||
description=Config.DESCRIPTION,
|
||||
default_response_class=JSONResponse,
|
||||
) # Initialize FastAPI app
|
||||
|
||||
@app.get("/", include_in_schema=False, summary=str(Config.DESCRIPTION))
|
||||
async def home() -> RedirectResponse:
|
||||
"""Redirect root path to API documentation."""
|
||||
return RedirectResponse(url="/docs")
|
||||
|
||||
# Get all routers and protected routes using the dynamic route creation
|
||||
routers, protected_routes = get_all_routers()
|
||||
|
||||
# Include all routers
|
||||
for router in routers:
|
||||
app.include_router(router)
|
||||
|
||||
app.openapi = lambda app=app: create_openapi_schema(app)
|
||||
|
||||
return app
|
||||
|
|
@ -1,127 +0,0 @@
|
|||
"""
|
||||
Route configuration and factory module.
|
||||
Handles dynamic route creation based on configurations.
|
||||
"""
|
||||
|
||||
from typing import Optional, Dict, Any, List, Callable, TypeVar, ParamSpec
|
||||
|
||||
P = ParamSpec("P") # For function parameters
|
||||
R = TypeVar("R") # For return type
|
||||
|
||||
from dataclasses import dataclass
|
||||
from functools import wraps
|
||||
from fastapi import APIRouter, Request
|
||||
from fastapi.routing import APIRoute
|
||||
from middleware.auth_middleware import MiddlewareModule
|
||||
from pydantic import BaseModel
|
||||
from AllConfigs.main import MainConfig as Config
|
||||
|
||||
|
||||
@dataclass
|
||||
class EndpointFactoryConfig:
|
||||
endpoint: str
|
||||
method: str
|
||||
summary: str
|
||||
description: str
|
||||
endpoint_function: Callable[P, R] # Now accepts any parameters and return type
|
||||
is_auth_required: bool = True
|
||||
is_event_required: bool = False
|
||||
extra_options: Dict[str, Any] = None
|
||||
|
||||
def __post_init__(self):
|
||||
if self.extra_options is None:
|
||||
self.extra_options = {}
|
||||
|
||||
|
||||
class EnhancedEndpointFactory:
|
||||
def __init__(self, router_config: dict):
|
||||
self.router = APIRouter(
|
||||
prefix=router_config["prefix"],
|
||||
tags=router_config["tags"],
|
||||
include_in_schema=router_config.get("include_in_schema", True),
|
||||
)
|
||||
self.endpoints = router_config["endpoints"]
|
||||
self.protected_routes: Dict[str, List[str]] = {}
|
||||
|
||||
def create_endpoint(self, config: EndpointFactoryConfig):
|
||||
"""
|
||||
Create an endpoint directly from the configuration.
|
||||
|
||||
Args:
|
||||
config: EndpointFactoryConfig instance containing endpoint configuration
|
||||
"""
|
||||
endpoint_path = config.endpoint
|
||||
endpoint_function = config.endpoint_function
|
||||
|
||||
if config.is_auth_required:
|
||||
# endpoint_function = MiddlewareModule.auth_required(endpoint_function)
|
||||
# Track protected routes
|
||||
full_path = f"{self.router.prefix}{endpoint_path}"
|
||||
if full_path not in self.protected_routes:
|
||||
self.protected_routes[full_path] = []
|
||||
self.protected_routes[full_path].append(config.method.lower())
|
||||
|
||||
# Register the endpoint with FastAPI router
|
||||
getattr(self.router, config.method.lower())(
|
||||
endpoint_path,
|
||||
summary=config.summary,
|
||||
description=config.description,
|
||||
**config.extra_options,
|
||||
)(endpoint_function)
|
||||
|
||||
def get_router(self) -> APIRouter:
|
||||
"""Get the configured router."""
|
||||
return self.router
|
||||
|
||||
def get_protected_routes(self) -> Dict[str, List[str]]:
|
||||
"""Get the protected routes mapping."""
|
||||
return self.protected_routes
|
||||
|
||||
|
||||
async def health_check(request: Request):
|
||||
"""Default health check endpoint."""
|
||||
return {"status": "healthy", "message": "Service is running"}
|
||||
|
||||
|
||||
async def ping_test(request: Request, service_name: str = "base-router"):
|
||||
"""Default ping test endpoint."""
|
||||
return {"ping": "pong", "service": service_name}
|
||||
|
||||
|
||||
def get_all_routers() -> tuple[List[APIRouter], Dict[str, List[str]]]:
|
||||
"""
|
||||
Get all routers and protected routes from route configurations.
|
||||
|
||||
Returns:
|
||||
tuple: (routers, protected_routes)
|
||||
"""
|
||||
from ApiEvents.route_configs import get_route_configs
|
||||
|
||||
routers = []
|
||||
all_protected_routes = {}
|
||||
|
||||
# Get route configurations from the registry
|
||||
route_configs = get_route_configs()
|
||||
factory_all = []
|
||||
for config in route_configs:
|
||||
factory = EnhancedEndpointFactory(config)
|
||||
|
||||
# Create endpoints from configuration
|
||||
for endpoint_dict in config["endpoints"]:
|
||||
endpoint_config = EndpointFactoryConfig(
|
||||
endpoint=endpoint_dict["endpoint"],
|
||||
method=endpoint_dict["method"],
|
||||
summary=endpoint_dict["summary"],
|
||||
description=endpoint_dict["description"],
|
||||
endpoint_function=endpoint_dict["endpoint_function"],
|
||||
is_auth_required=endpoint_dict["is_auth_required"],
|
||||
is_event_required=endpoint_dict["is_event_required"],
|
||||
extra_options=endpoint_dict.get("extra_options", {}),
|
||||
)
|
||||
factory.create_endpoint(endpoint_config)
|
||||
factory_all.append(endpoint_config.__dict__)
|
||||
|
||||
# Add router and protected routes
|
||||
routers.append(factory.get_router())
|
||||
all_protected_routes.update(factory.get_protected_routes())
|
||||
return routers, all_protected_routes
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
from AllConfigs import HostConfig
|
||||
from ApiLayers.AllConfigs import HostConfig
|
||||
|
||||
|
||||
class EmailConfig:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from AllConfigs import HostConfig
|
||||
from ApiLayers.AllConfigs import HostConfig
|
||||
|
||||
|
||||
class MongoConfig:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from AllConfigs import HostConfig
|
||||
from ApiLayers.AllConfigs import HostConfig
|
||||
|
||||
|
||||
class WagRedis:
|
||||
|
|
@ -16,14 +16,18 @@ class WagRedis:
|
|||
db=WagRedis.REDIS_DB,
|
||||
)
|
||||
|
||||
|
||||
class RedisCategoryKeys:
|
||||
REBUILD: str = "REBUILD"
|
||||
ENDPOINT2CLASS: str = "ENDPOINT2CLASS"
|
||||
LANGUAGE_MODELS: str = "LANGUAGE_MODELS"
|
||||
VALIDATION_USER: str = "VALIDATION_USER"
|
||||
CLUSTER_INDEX: str = "CLUSTER_INDEX"
|
||||
CLUSTER_FUNCTION_CODES: str = "CLUSTER_FUNCTION_CODES"
|
||||
METHOD_FUNCTION_CODES: str = "METHOD_FUNCTION_CODES"
|
||||
MENU_FIRST_LAYER: str = "MENU_FIRST_LAYER"
|
||||
PAGE_MAPPER: str = "PAGE_MAPPER"
|
||||
MENU_MAPPER: str = "MENU_MAPPER"
|
||||
AUTH: str = "AUTH"
|
||||
OCC: str = "Occupant"
|
||||
EMP: str = "Employee"
|
||||
OCCUPANT: str = "OCCUPANT"
|
||||
EMPLOYEE: str = "EMPLOYEE"
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
from AllConfigs import HostConfig
|
||||
from ApiLayers.AllConfigs import HostConfig
|
||||
|
||||
|
||||
class WagDatabase:
|
||||
|
|
|
|||
|
|
@ -1,21 +1,6 @@
|
|||
import datetime
|
||||
|
||||
|
||||
class ApiStatic:
|
||||
PLACEHOLDER = "https://s.tmimgcdn.com/scr/800x500/276800/building-home-nature-logo-vector-template-3_276851-original.jpg"
|
||||
FORGOT_LINK = "https://www.evyos.com.tr/password/create?tokenUrl="
|
||||
BLACKLIST_LINK = "https://www.evyos.com.tr/support/unknown-login-notice/"
|
||||
APP_DIR = "/home/berkay/git-evyos/api-managment-backend/"
|
||||
|
||||
@classmethod
|
||||
def forgot_link(cls, forgot_key):
|
||||
return cls.FORGOT_LINK + forgot_key
|
||||
|
||||
@classmethod
|
||||
def blacklist_login(cls, record_id):
|
||||
return cls.BLACKLIST_LINK + record_id
|
||||
|
||||
|
||||
class Auth:
|
||||
ACCESS_EMAIL_EXT = "evyos.com.tr"
|
||||
ACCESS_TOKEN_TAG = "evyos-session-key"
|
||||
|
|
@ -40,32 +25,3 @@ class Auth:
|
|||
TOKEN_EXPIRE_DAY_5 = datetime.timedelta(days=5)
|
||||
TOKEN_EXPIRE_DAY_15 = datetime.timedelta(days=15)
|
||||
TOKEN_EXPIRE_DAY_30 = datetime.timedelta(days=30)
|
||||
|
||||
|
||||
class Routers:
|
||||
NO_TOKEN_REQUIRES = [
|
||||
"/",
|
||||
"/metrics",
|
||||
"/openapi.json",
|
||||
"/docs",
|
||||
"/redoc",
|
||||
"/auth/login",
|
||||
"/favicon.ico",
|
||||
"/docs/oauth2-redirect",
|
||||
"/authentication/select",
|
||||
"/authentication/login",
|
||||
"/authentication/logout",
|
||||
"/authentication/refresher",
|
||||
"/authentication/refresh",
|
||||
"/authentication/disconnect",
|
||||
"/authentication/create_password",
|
||||
"/authentication/reset_password",
|
||||
"/authentication/forgot",
|
||||
"/authentication/valid",
|
||||
]
|
||||
NO_EVENT_REQUIRES = [
|
||||
"/access/endpoints/available",
|
||||
"/access/endpoint/available",
|
||||
"/validations/endpoint",
|
||||
"/authentication/avatar",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
from ApiLibrary.date_time_actions.date_functions import (
|
||||
from ApiLayers.ApiLibrary.date_time_actions.date_functions import (
|
||||
DateTimeLocal,
|
||||
system_arrow,
|
||||
client_arrow,
|
||||
)
|
||||
from ApiLibrary.extensions.select import SelectActionWithEmployee, SelectAction
|
||||
from ApiLibrary.common.line_number import get_line_number_for_error
|
||||
from ApiLayers.ApiLibrary.extensions.select import (
|
||||
SelectActionWithEmployee,
|
||||
SelectAction,
|
||||
)
|
||||
from ApiLayers.ApiLibrary.common.line_number import get_line_number_for_error
|
||||
|
||||
__all__ = [
|
||||
"DateTimeLocal",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import arrow
|
||||
import calendar
|
||||
from AllConfigs.main import MainConfig as Config
|
||||
|
||||
from ApiLayers.AllConfigs.main import MainConfig as Config
|
||||
|
||||
|
||||
class DateTimeLocal:
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import uuid
|
|||
import secrets
|
||||
import random
|
||||
|
||||
from AllConfigs.Token.config import Auth
|
||||
from ApiLayers.AllConfigs.Token.config import Auth
|
||||
|
||||
|
||||
class PasswordModule:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
from fastapi import APIRouter
|
||||
import uuid
|
||||
from Events.Engine.abstract_class import CategoryCluster, MethodToEvent
|
||||
|
||||
|
||||
class CreateRouterFromCluster:
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.prefix = kwargs.get("prefix")
|
||||
self.tags = kwargs.get("tags")
|
||||
self.router = APIRouter(prefix=self.prefix, tags=self.tags)
|
||||
|
||||
|
||||
class CreateEndpointFromCluster:
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.router: CategoryCluster = kwargs.get("router")
|
||||
self.method_endpoint: MethodToEvent = kwargs.get("method_endpoint")
|
||||
self.unique_id = str(uuid.uuid4())[:8] # Use first 8 chars of UUID for brevity
|
||||
self.attach_router()
|
||||
|
||||
def attach_router(self):
|
||||
method = getattr(self.router, self.method_endpoint.METHOD.lower())
|
||||
|
||||
# Create a unique operation ID based on the endpoint path, method, and a unique identifier
|
||||
base_path = self.method_endpoint.URL.strip('/').replace('/', '_').replace('-', '_')
|
||||
operation_id = f"{base_path}_{self.method_endpoint.METHOD.lower()}_{self.unique_id}"
|
||||
|
||||
kwargs = {
|
||||
"path": self.method_endpoint.URL,
|
||||
"summary": self.method_endpoint.SUMMARY,
|
||||
"description": self.method_endpoint.DESCRIPTION,
|
||||
"operation_id": operation_id
|
||||
}
|
||||
|
||||
if hasattr(self.method_endpoint, 'RESPONSE_MODEL') and self.method_endpoint.RESPONSE_MODEL is not None:
|
||||
kwargs["response_model"] = self.method_endpoint.RESPONSE_MODEL
|
||||
|
||||
method(**kwargs)(self.method_endpoint.endpoint_callable)
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
from Services.Redis import RedisActions, AccessToken
|
||||
from Services.Redis.Models.cluster import RedisList
|
||||
|
||||
redis_list = RedisList(redis_key="test")
|
||||
|
||||
|
|
@ -1,11 +1,12 @@
|
|||
from typing import Any, ClassVar, Dict
|
||||
from sqlalchemy import or_
|
||||
from ApiLibrary.common.line_number import get_line_number_for_error
|
||||
from Schemas import Users
|
||||
from ErrorHandlers import HTTPExceptionApi
|
||||
from ApiValidations.Request.authentication import Login
|
||||
from ApiLibrary.token.password_module import PasswordModule
|
||||
from ApiServices.Token.token_handler import TokenService
|
||||
|
||||
from ApiLayers.ApiLibrary.common.line_number import get_line_number_for_error
|
||||
from ApiLayers.ErrorHandlers import HTTPExceptionApi
|
||||
from ApiLayers.ApiValidations.Request.authentication import Login
|
||||
from ApiLayers.ApiLibrary.token.password_module import PasswordModule
|
||||
from ApiLayers.ApiServices.Token.token_handler import TokenService
|
||||
from ApiLayers.Schemas import Users
|
||||
|
||||
|
||||
class UserLoginModule:
|
||||
|
|
|
|||
|
|
@ -2,21 +2,20 @@
|
|||
|
||||
from typing import List, Union, TypeVar, Dict, Any, Optional, TYPE_CHECKING
|
||||
|
||||
from AllConfigs.Token.config import Auth
|
||||
from ApiLibrary.common.line_number import get_line_number_for_error
|
||||
from ApiLibrary.date_time_actions.date_functions import DateTimeLocal
|
||||
from ApiLibrary.token.password_module import PasswordModule
|
||||
from ErrorHandlers import HTTPExceptionApi
|
||||
from Schemas.identity.identity import UsersTokens, People
|
||||
from Services.Redis import RedisActions, AccessToken
|
||||
from ApiValidations.Custom.token_objects import (
|
||||
from ApiLayers.AllConfigs.Token.config import Auth
|
||||
from ApiLayers.ApiLibrary.common.line_number import get_line_number_for_error
|
||||
from ApiLayers.ApiLibrary.date_time_actions.date_functions import DateTimeLocal
|
||||
from ApiLayers.ApiLibrary.token.password_module import PasswordModule
|
||||
from ApiLayers.ErrorHandlers import HTTPExceptionApi
|
||||
from ApiLayers.Schemas.identity.identity import UsersTokens, People
|
||||
from ApiLayers.ApiValidations.Custom.token_objects import (
|
||||
EmployeeTokenObject,
|
||||
OccupantTokenObject,
|
||||
UserType,
|
||||
CompanyToken,
|
||||
OccupantToken,
|
||||
)
|
||||
from Schemas import (
|
||||
from ApiLayers.Schemas import (
|
||||
Users,
|
||||
BuildLivingSpace,
|
||||
BuildParts,
|
||||
|
|
@ -30,6 +29,8 @@ from Schemas import (
|
|||
OccupantTypes,
|
||||
)
|
||||
from Services.Redis.Models.response import RedisResponse
|
||||
from Services.Redis import RedisActions, AccessToken
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from fastapi import Request
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from ApiServices.Token.token_handler import TokenService
|
||||
from ApiLayers.ApiServices.Token.token_handler import TokenService
|
||||
|
||||
__all__ = [
|
||||
"TokenService",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from ApiValidations.Request import BaseModelRegular, PydanticBaseModel
|
||||
from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
|
||||
from typing import Optional
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from typing import Optional
|
||||
|
||||
from ApiValidations.Request import PydanticBaseModel, ListOptions
|
||||
from ApiValidations.handler import BaseModelRegular
|
||||
from ApiLayers.ApiValidations.Request import PydanticBaseModel, ListOptions
|
||||
from ApiLayers.ApiValidations.handler import BaseModelRegular
|
||||
|
||||
|
||||
class PostCodeValidation:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from ApiValidations.Request import BaseModelRegular
|
||||
from ApiLayers.ApiValidations.Request import BaseModelRegular
|
||||
|
||||
|
||||
class SingleEnumClassKeyValidation:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
from typing import Optional
|
||||
from ApiValidations.Request import BaseModelRegular, PydanticBaseModel
|
||||
from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
|
||||
|
||||
|
||||
class BuildAreaValidation:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from ApiValidations.Request import BaseModelRegular
|
||||
from ApiLayers.ApiValidations.Request import BaseModelRegular
|
||||
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
from typing import Optional
|
||||
from ApiValidations.handler import BaseModelRegular
|
||||
from ApiLayers.ApiValidations.handler import BaseModelRegular
|
||||
|
||||
|
||||
class ListOptions(BaseModelRegular):
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
from typing import Optional
|
||||
from ApiValidations.Request import BaseModelRegular
|
||||
from ApiLayers.ApiValidations.Request import BaseModelRegular
|
||||
|
||||
# from api_validations.validations_request import (
|
||||
# PydanticBaseModel,
|
||||
# PydanticBaseModelValidation,
|
||||
# )
|
||||
from ApiValidations.Request import BaseModelRegular, PydanticBaseModel
|
||||
from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
|
||||
|
||||
|
||||
class InsertBuildLivingSpace(BaseModelRegular):
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
from typing import Optional
|
||||
from ApiValidations.Request import BaseModelRegular, PydanticBaseModel
|
||||
from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
|
||||
|
||||
|
||||
class InsertBuildTypes(BaseModelRegular):
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from typing import Optional
|
||||
from datetime import datetime
|
||||
from ApiValidations.Request import BaseModelRegular, PydanticBaseModel
|
||||
from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
|
||||
|
||||
|
||||
class InsertBuild(BaseModelRegular):
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
from typing import Optional, List
|
||||
from ApiValidations.Request import BaseModelRegular, PydanticBaseModel
|
||||
from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
|
||||
|
||||
|
||||
class InsertCompany(BaseModelRegular):
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from typing import Optional
|
||||
|
||||
from ApiValidations.Request import BaseModelRegular
|
||||
from ApiLayers.ApiValidations.Request import BaseModelRegular
|
||||
|
||||
|
||||
class ListOptionsValidation:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
from typing import Optional
|
||||
from ApiValidations.Request import BaseModelRegular, PydanticBaseModel, ListOptions
|
||||
from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel, ListOptions
|
||||
|
||||
|
||||
class DecisionBookDecisionBookInvitations(BaseModelRegular):
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
from typing import Optional
|
||||
from ApiValidations.Request import (
|
||||
PydanticBaseModel,
|
||||
)
|
||||
from ApiLayers.ApiValidations.Request import PydanticBaseModel
|
||||
|
||||
|
||||
class DepartmentsPydantic(PydanticBaseModel):
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
from typing import Optional
|
||||
from ApiValidations.Request import BaseModelRegular, PydanticBaseModel
|
||||
from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
|
||||
|
||||
|
||||
class BindEmployees2People(PydanticBaseModel):
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
from typing import Optional
|
||||
from ApiValidations.Request import BaseModelRegular
|
||||
from ApiLayers.ApiValidations.Request import BaseModelRegular
|
||||
|
||||
|
||||
class RegisterEvents2EmployeeValidation:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from ApiValidations.Request import BaseModelRegular
|
||||
from ApiLayers.ApiValidations.Request import BaseModelRegular
|
||||
|
||||
|
||||
class RegisterModules2OccupantValidation:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
from typing import Optional
|
||||
from ApiValidations.Request import BaseModelRegular, PydanticBaseModel
|
||||
from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
|
||||
|
||||
|
||||
class InsertPerson(BaseModelRegular):
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
from typing import Optional
|
||||
from ApiValidations.Request import BaseModelRegular, PydanticBaseModel
|
||||
from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
|
||||
|
||||
|
||||
class InsertBuildDecisionBookProjectItems(BaseModelRegular):
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from typing import Optional, List
|
||||
from ApiValidations.Request import BaseModelRegular
|
||||
from ApiValidations.Request import BaseModelRegular, PydanticBaseModel
|
||||
from ApiLayers.ApiValidations.Request import BaseModelRegular
|
||||
from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
|
||||
|
||||
|
||||
class CheckEndpointAccess(BaseModelRegular):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from ApiValidations.Request import BaseModelRegular
|
||||
from ApiLayers.ApiValidations.Request import BaseModelRegular
|
||||
|
||||
|
||||
class RegisterServices2OccupantValidation:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
from typing import Optional
|
||||
from ApiValidations.Request import BaseModelRegular, PydanticBaseModel
|
||||
from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
|
||||
|
||||
|
||||
class InsertStaffValidation:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
from typing import Optional
|
||||
from ApiValidations.Request import PydanticBaseModel
|
||||
from ApiLayers.ApiValidations.Request import PydanticBaseModel
|
||||
|
||||
|
||||
class InsertUsersValidation:
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ from typing import Any, Optional
|
|||
from fastapi import status
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
|
||||
class BaseEndpointResponse:
|
||||
|
||||
def __init__(self, code: str, lang: str):
|
||||
|
|
@ -12,7 +13,7 @@ class BaseEndpointResponse:
|
|||
def retrieve_message(self):
|
||||
messages = {}
|
||||
return messages[self.code][self.lang]
|
||||
|
||||
|
||||
|
||||
# 1. 200 OK
|
||||
class EndpointSuccessResponse(BaseEndpointResponse):
|
||||
|
|
@ -24,8 +25,8 @@ class EndpointSuccessResponse(BaseEndpointResponse):
|
|||
completed=True,
|
||||
message=self.retrieve_message(),
|
||||
lang=self.lang,
|
||||
data=data
|
||||
)
|
||||
data=data,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -39,15 +40,14 @@ class EndpointCreatedResponse(BaseEndpointResponse):
|
|||
completed=True,
|
||||
message=self.retrieve_message(),
|
||||
lang=self.lang,
|
||||
data=data
|
||||
)
|
||||
data=data,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
# 3. 202 Accepted
|
||||
class EndpointAcceptedResponse(BaseEndpointResponse):
|
||||
|
||||
|
||||
def as_dict(self, data: Optional[Dict[str, Any]] = None):
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_202_ACCEPTED,
|
||||
|
|
@ -55,8 +55,8 @@ class EndpointAcceptedResponse(BaseEndpointResponse):
|
|||
completed=True,
|
||||
message=self.retrieve_message(),
|
||||
lang=self.lang,
|
||||
data=data
|
||||
)
|
||||
data=data,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -70,8 +70,8 @@ class EndpointBadRequestResponse(BaseEndpointResponse):
|
|||
completed=False,
|
||||
message=self.retrieve_message(),
|
||||
lang=self.lang,
|
||||
data=data
|
||||
)
|
||||
data=data,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -82,10 +82,8 @@ class EndpointUnauthorizedResponse(BaseEndpointResponse):
|
|||
return JSONResponse(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
content=dict(
|
||||
completed=False,
|
||||
message=self.retrieve_message(),
|
||||
lang=self.lang
|
||||
)
|
||||
completed=False, message=self.retrieve_message(), lang=self.lang
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -96,10 +94,8 @@ class EndpointNotFoundResponse(BaseEndpointResponse):
|
|||
return JSONResponse(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
content=dict(
|
||||
completed=False,
|
||||
message=self.retrieve_message(),
|
||||
lang=self.lang
|
||||
)
|
||||
completed=False, message=self.retrieve_message(), lang=self.lang
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -110,10 +106,8 @@ class EndpointForbiddenResponse(BaseEndpointResponse):
|
|||
return JSONResponse(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
content=dict(
|
||||
completed=False,
|
||||
message=self.retrieve_message(),
|
||||
lang=self.lang
|
||||
)
|
||||
completed=False, message=self.retrieve_message(), lang=self.lang
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -124,15 +118,14 @@ class EndpointConflictResponse(BaseEndpointResponse):
|
|||
return JSONResponse(
|
||||
status_code=status.HTTP_409_CONFLICT,
|
||||
content=dict(
|
||||
completed=False,
|
||||
message=self.retrieve_message(),
|
||||
lang=self.lang
|
||||
)
|
||||
completed=False, message=self.retrieve_message(), lang=self.lang
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
# 7. 429 Too Many Requests
|
||||
class EndpointTooManyRequestsResponse(BaseEndpointResponse):
|
||||
|
||||
|
||||
def __init__(self, retry_after: int):
|
||||
self.retry_after = retry_after
|
||||
|
||||
|
|
@ -141,10 +134,8 @@ class EndpointTooManyRequestsResponse(BaseEndpointResponse):
|
|||
status_code=status.HTTP_429_TOO_MANY_REQUESTS,
|
||||
headers={"Retry-After": str(self.retry_after)},
|
||||
content=dict(
|
||||
completed=False,
|
||||
message=self.retrieve_message(),
|
||||
lang=self.lang
|
||||
)
|
||||
completed=False, message=self.retrieve_message(), lang=self.lang
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -155,10 +146,8 @@ class EndpointInternalErrorResponse(BaseEndpointResponse):
|
|||
return JSONResponse(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
content=dict(
|
||||
completed=False,
|
||||
message=self.retrieve_message(),
|
||||
lang=self.lang
|
||||
)
|
||||
completed=False, message=self.retrieve_message(), lang=self.lang
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -168,8 +157,6 @@ class EndpointErrorResponse(BaseEndpointResponse):
|
|||
return JSONResponse(
|
||||
status_code=status.HTTP_304_NOT_MODIFIED,
|
||||
content=dict(
|
||||
completed=False,
|
||||
message=self.retrieve_message(),
|
||||
lang=self.lang
|
||||
)
|
||||
completed=False, message=self.retrieve_message(), lang=self.lang
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
from typing import Any, Dict, Union, Awaitable
|
||||
from typing import Any, Union, Awaitable
|
||||
from fastapi import Request, WebSocket
|
||||
from fastapi.responses import Response
|
||||
|
||||
from LanguageModels.Errors.merge_all_error_languages import MergedErrorLanguageModels
|
||||
from ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
|
||||
from ErrorHandlers.bases import BaseErrorModelClass
|
||||
from ApiLayers.LanguageModels.Errors.merge_all_error_languages import (
|
||||
MergedErrorLanguageModels,
|
||||
)
|
||||
from ApiLayers.ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
|
||||
from ApiLayers.ErrorHandlers.bases import BaseErrorModelClass
|
||||
|
||||
|
||||
class HTTPExceptionApiHandler:
|
||||
|
|
@ -23,7 +25,7 @@ class HTTPExceptionApiHandler:
|
|||
|
||||
@staticmethod
|
||||
def retrieve_error_message(exc: HTTPExceptionApi, error_languages) -> str:
|
||||
from ErrorHandlers import DEFAULT_ERROR
|
||||
from ApiLayers.ErrorHandlers import DEFAULT_ERROR
|
||||
|
||||
return error_languages.get(str(exc.error_code).upper(), DEFAULT_ERROR)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
from ErrorHandlers.ErrorHandlers.api_exc_handler import (
|
||||
from ApiLayers.ErrorHandlers.ErrorHandlers.api_exc_handler import (
|
||||
HTTPExceptionApiHandler,
|
||||
)
|
||||
from ErrorHandlers.Exceptions.api_exc import (
|
||||
HTTPExceptionApi,
|
||||
)
|
||||
from ApiLayers.ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
|
||||
|
||||
|
||||
DEFAULT_ERROR = "UNKNOWN_ERROR"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
from ErrorHandlers.base import BaseError
|
||||
from ErrorHandlers.statuses import Statuses
|
||||
from ApiLayers.ErrorHandlers.base import BaseError
|
||||
from ApiLayers.ErrorHandlers.statuses import Statuses
|
||||
|
||||
|
||||
class BaseErrorModelClass:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
|
||||
from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
|
||||
|
||||
AccountBooksLanguageModel = dict(
|
||||
tr={
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
|
||||
from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
|
||||
|
||||
BuildIbansLanguageModel = dict(
|
||||
tr={
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
|
||||
from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
|
||||
|
||||
DecisionBookBudgetBooksLanguageModel = dict(
|
||||
tr={
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
|
||||
from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
|
||||
|
||||
BuildTypesLanguageModel = dict(
|
||||
tr={
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
|
||||
from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
|
||||
|
||||
BuildDecisionBookLanguageModel = dict(
|
||||
tr={
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
|
||||
from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
|
||||
|
||||
RelationshipDutyCompanyLanguageModel = dict(
|
||||
tr={
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
|
||||
from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
|
||||
|
||||
DepartmentsLanguageModel = dict(
|
||||
tr={
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
|
||||
from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
|
||||
|
||||
StaffLanguageModel = dict(
|
||||
tr={
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
|
||||
from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
|
||||
|
||||
|
||||
EventsLanguageModel = dict(
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
|
||||
from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
|
||||
|
||||
UsersTokensLanguageModel = dict(
|
||||
tr={
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
|
||||
from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
|
||||
|
||||
EndpointRestrictionLanguageModel = dict(
|
||||
tr={
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from LanguageModels.Errors.base_languages import BaseErrorLanguageModels
|
||||
from ApiLayers.LanguageModels.Errors.base_languages import BaseErrorLanguageModels
|
||||
|
||||
|
||||
class MergedErrorLanguageModels:
|
||||
|
|
|
|||
|
|
@ -5,17 +5,19 @@ This module provides authentication decorator for protecting endpoints
|
|||
and a middleware for request timing measurements.
|
||||
"""
|
||||
|
||||
import inspect
|
||||
|
||||
from time import perf_counter
|
||||
from typing import Callable, Optional, Dict, Any, Tuple, Union
|
||||
from typing import Callable
|
||||
from functools import wraps
|
||||
|
||||
from fastapi import Request, Response
|
||||
from starlette.middleware.base import BaseHTTPMiddleware
|
||||
|
||||
from ApiLibrary.common.line_number import get_line_number_for_error
|
||||
from ErrorHandlers.ErrorHandlers.api_exc_handler import HTTPExceptionApi
|
||||
from AllConfigs.Token.config import Auth
|
||||
import inspect
|
||||
from ApiLayers.ApiLibrary.common.line_number import get_line_number_for_error
|
||||
from ApiLayers.ErrorHandlers.ErrorHandlers.api_exc_handler import HTTPExceptionApi
|
||||
from ApiLayers.AllConfigs.Token.config import Auth
|
||||
from ApiLayers.ApiServices.Token.token_handler import TokenService
|
||||
|
||||
|
||||
class MiddlewareModule:
|
||||
|
|
@ -39,7 +41,6 @@ class MiddlewareModule:
|
|||
Raises:
|
||||
HTTPExceptionApi: If token is missing, invalid, or user not found
|
||||
"""
|
||||
from ApiServices.Token.token_handler import TokenService
|
||||
|
||||
# Get token and validate - will raise HTTPExceptionApi if invalid
|
||||
redis_token = TokenService.get_access_token_from_request(request=request)
|
||||
|
|
@ -86,14 +87,22 @@ class MiddlewareModule:
|
|||
@wraps(func)
|
||||
async def wrapper(request: Request, *args, **kwargs):
|
||||
# Get and validate token context from request
|
||||
# Create auth context and Attach auth context to both wrapper and original function
|
||||
func.auth = cls.get_user_from_request(request)
|
||||
wrapper.auth = func.auth
|
||||
auth_context = {
|
||||
"is_employee": False,
|
||||
"is_occupant": False,
|
||||
"context": {}
|
||||
}
|
||||
|
||||
# Set auth context on the wrapper function itself
|
||||
setattr(wrapper, 'auth', auth_context)
|
||||
|
||||
# Call the original endpoint function
|
||||
if inspect.iscoroutinefunction(func):
|
||||
return await func(request, *args, **kwargs)
|
||||
return func(request, *args, **kwargs)
|
||||
|
||||
result = await func(request, *args, **kwargs)
|
||||
else:
|
||||
result = func(request, *args, **kwargs)
|
||||
|
||||
return result
|
||||
return wrapper
|
||||
|
||||
|
||||
|
|
@ -9,13 +9,12 @@ from typing import Callable, Dict, Any, Optional, Union
|
|||
from fastapi import Request
|
||||
from pydantic import BaseModel
|
||||
|
||||
from ApiLibrary.common.line_number import get_line_number_for_error
|
||||
from ApiServices.Token.token_handler import TokenService
|
||||
from ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
|
||||
from Schemas.rules.rules import EndpointRestriction
|
||||
from ApiLayers.ApiLibrary.common.line_number import get_line_number_for_error
|
||||
from ApiLayers.ApiServices.Token.token_handler import TokenService
|
||||
from ApiLayers.ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
|
||||
from ApiLayers.Schemas import Events, EndpointRestriction
|
||||
|
||||
from .auth_middleware import MiddlewareModule
|
||||
from Schemas import Events
|
||||
|
||||
|
||||
class EventFunctions:
|
||||
|
|
@ -24,88 +23,7 @@ class EventFunctions:
|
|||
self.endpoint = endpoint
|
||||
self.request = request
|
||||
|
||||
def match_endpoint_with_accesiable_event(self) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
Match an endpoint with accessible events.
|
||||
|
||||
Args:
|
||||
endpoint: The endpoint to match
|
||||
|
||||
Returns:
|
||||
Dict containing the endpoint registration data
|
||||
None if endpoint is not found in database
|
||||
"""
|
||||
access_token = TokenService.get_access_token_from_request(self.request)
|
||||
token_context = TokenService.get_object_via_access_key(
|
||||
access_token=access_token
|
||||
)
|
||||
if token_context.is_employee:
|
||||
reachable_event_codes: list[str] = (
|
||||
token_context.selected_company.reachable_event_codes
|
||||
)
|
||||
elif token_context.is_occupant:
|
||||
reachable_event_codes: list[str] = (
|
||||
token_context.selected_occupant.reachable_event_codes
|
||||
)
|
||||
else:
|
||||
raise HTTPExceptionApi(
|
||||
error_code="",
|
||||
lang="en",
|
||||
loc=get_line_number_for_error(),
|
||||
sys_msg="Token not found",
|
||||
)
|
||||
|
||||
if not access_token:
|
||||
raise HTTPExceptionApi(
|
||||
error_code="",
|
||||
lang="en",
|
||||
loc=get_line_number_for_error(),
|
||||
sys_msg="Token not found",
|
||||
)
|
||||
|
||||
db = EndpointRestriction.new_session()
|
||||
restriction = EndpointRestriction.filter_one(
|
||||
EndpointRestriction.endpoint_name == self.endpoint,
|
||||
db=db,
|
||||
).data
|
||||
if not restriction:
|
||||
raise HTTPExceptionApi(
|
||||
error_code="",
|
||||
lang="en",
|
||||
loc=get_line_number_for_error(),
|
||||
sys_msg="Function code not found",
|
||||
)
|
||||
|
||||
event_related = Events.filter_all(
|
||||
Events.endpoint_id == restriction.id,
|
||||
db=db,
|
||||
).data
|
||||
if not event_related:
|
||||
raise HTTPExceptionApi(
|
||||
error_code="",
|
||||
lang="en",
|
||||
loc=get_line_number_for_error(),
|
||||
sys_msg="No event is registered for this user.",
|
||||
)
|
||||
an_event = event_related[0]
|
||||
event_related_codes: list[str] = [
|
||||
event.function_code for event in event_related
|
||||
]
|
||||
intersected_code: set = set(reachable_event_codes).intersection(
|
||||
set(event_related_codes)
|
||||
)
|
||||
if not len(list(intersected_code)) == 1:
|
||||
raise HTTPExceptionApi(
|
||||
error_code="",
|
||||
lang="en",
|
||||
loc=get_line_number_for_error(),
|
||||
sys_msg="No event is registered for this user.",
|
||||
)
|
||||
return {
|
||||
"endpoint_url": self.endpoint,
|
||||
"reachable_event_code": list(intersected_code)[0],
|
||||
"class": an_event.function_class,
|
||||
}
|
||||
|
||||
def retrieve_function_dict(self) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
|
|
@ -201,9 +119,91 @@ class TokenEventMiddleware:
|
|||
"""
|
||||
|
||||
@staticmethod
|
||||
def event_required(
|
||||
func: Callable[..., Dict[str, Any]]
|
||||
) -> Callable[..., Dict[str, Any]]:
|
||||
def match_endpoint_with_accessible_event(request_from_scope, endpoint_from_scope) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
Match an endpoint with accessible events.
|
||||
|
||||
Args:
|
||||
request_from_scope: The endpoint to match
|
||||
|
||||
Returns:
|
||||
Dict containing the endpoint registration data
|
||||
None if endpoint is not found in database
|
||||
"""
|
||||
access_token = TokenService.get_access_token_from_request(request_from_scope)
|
||||
token_context = TokenService.get_object_via_access_key(
|
||||
access_token=access_token
|
||||
)
|
||||
if token_context.is_employee:
|
||||
reachable_event_codes: list[str] = (
|
||||
token_context.selected_company.reachable_event_codes
|
||||
)
|
||||
elif token_context.is_occupant:
|
||||
reachable_event_codes: list[str] = (
|
||||
token_context.selected_occupant.reachable_event_codes
|
||||
)
|
||||
else:
|
||||
raise HTTPExceptionApi(
|
||||
error_code="",
|
||||
lang="en",
|
||||
loc=get_line_number_for_error(),
|
||||
sys_msg="Token not found",
|
||||
)
|
||||
|
||||
if not access_token:
|
||||
raise HTTPExceptionApi(
|
||||
error_code="",
|
||||
lang="en",
|
||||
loc=get_line_number_for_error(),
|
||||
sys_msg="Token not found",
|
||||
)
|
||||
|
||||
db = EndpointRestriction.new_session()
|
||||
restriction = EndpointRestriction.filter_one(
|
||||
EndpointRestriction.endpoint_name == endpoint_from_scope,
|
||||
db=db,
|
||||
).data
|
||||
if not restriction:
|
||||
raise HTTPExceptionApi(
|
||||
error_code="",
|
||||
lang="en",
|
||||
loc=get_line_number_for_error(),
|
||||
sys_msg="Function code not found",
|
||||
)
|
||||
|
||||
event_related = Events.filter_all(
|
||||
Events.endpoint_id == restriction.id,
|
||||
db=db,
|
||||
).data
|
||||
if not event_related:
|
||||
raise HTTPExceptionApi(
|
||||
error_code="",
|
||||
lang="en",
|
||||
loc=get_line_number_for_error(),
|
||||
sys_msg="No event is registered for this user.",
|
||||
)
|
||||
an_event = event_related[0]
|
||||
event_related_codes: list[str] = [
|
||||
event.function_code for event in event_related
|
||||
]
|
||||
intersected_code: set = set(reachable_event_codes).intersection(
|
||||
set(event_related_codes)
|
||||
)
|
||||
if not len(list(intersected_code)) == 1:
|
||||
raise HTTPExceptionApi(
|
||||
error_code="",
|
||||
lang="en",
|
||||
loc=get_line_number_for_error(),
|
||||
sys_msg="No event is registered for this user.",
|
||||
)
|
||||
return {
|
||||
"endpoint_url": endpoint_from_scope,
|
||||
"reachable_event_code": list(intersected_code)[0],
|
||||
"class": an_event.function_class,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def event_required(cls, func: Callable) -> Callable:
|
||||
"""
|
||||
Decorator for endpoints with token and event requirements.
|
||||
This decorator:
|
||||
|
|
@ -216,31 +216,36 @@ class TokenEventMiddleware:
|
|||
Returns:
|
||||
Callable: The wrapped function with both auth and event handling
|
||||
"""
|
||||
# # First apply authentication
|
||||
# authenticated_func = MiddlewareModule.auth_required(func)
|
||||
authenticated_func = func
|
||||
# First apply authentication
|
||||
authenticated_func = MiddlewareModule.auth_required(func)
|
||||
|
||||
@wraps(authenticated_func)
|
||||
async def wrapper(request: Request, *args, **kwargs) -> Dict[str, Any]:
|
||||
|
||||
# Get function code from the function's metadata
|
||||
endpoint_url = getattr(authenticated_func, "url_of_endpoint", {})
|
||||
if not endpoint_url:
|
||||
raise HTTPExceptionApi(
|
||||
error_code="",
|
||||
lang="en",
|
||||
loc=get_line_number_for_error(),
|
||||
sys_msg="Function code not found",
|
||||
)
|
||||
|
||||
# Make handler available to all functions in the chain
|
||||
func.func_code = EventFunctions(
|
||||
endpoint_url, request
|
||||
).match_endpoint_with_accesiable_event()
|
||||
# Call the authenticated function
|
||||
# Get the endpoint URL for matching with events
|
||||
endpoint_url = str(request.url.path)
|
||||
|
||||
# Set func_code first
|
||||
func_code = "8aytr-"
|
||||
setattr(wrapper, 'func_code', func_code)
|
||||
|
||||
# Get auth context from the authenticated function's wrapper
|
||||
auth_context = getattr(authenticated_func, 'auth', None)
|
||||
print('auth_context', auth_context)
|
||||
if auth_context is not None:
|
||||
setattr(wrapper, 'auth', auth_context)
|
||||
|
||||
# Execute the authenticated function and get its result
|
||||
if inspect.iscoroutinefunction(authenticated_func):
|
||||
return await authenticated_func(request, *args, **kwargs)
|
||||
return authenticated_func(request, *args, **kwargs)
|
||||
result = await authenticated_func(request, *args, **kwargs)
|
||||
else:
|
||||
result = authenticated_func(request, *args, **kwargs)
|
||||
|
||||
return result
|
||||
|
||||
# Copy any existing attributes from the authenticated function
|
||||
for attr in dir(authenticated_func):
|
||||
if not attr.startswith('__'):
|
||||
setattr(wrapper, attr, getattr(authenticated_func, attr))
|
||||
|
||||
return wrapper
|
||||
|
||||
|
|
@ -261,8 +266,8 @@ class TokenEventMiddleware:
|
|||
Callable: The wrapped function with both auth and event handling
|
||||
"""
|
||||
# First apply authentication
|
||||
authenticated_func = MiddlewareModule.auth_required(func)
|
||||
|
||||
# authenticated_func = MiddlewareModule.auth_required(func)
|
||||
authenticated_func = func
|
||||
@wraps(authenticated_func)
|
||||
async def wrapper(
|
||||
request: Request, *args: Any, **kwargs: Any
|
||||
|
|
@ -278,9 +283,9 @@ class TokenEventMiddleware:
|
|||
loc=get_line_number_for_error(),
|
||||
sys_msg="Endpoint not found",
|
||||
)
|
||||
wrapper.validation_code = EventFunctions(
|
||||
endpoint_asked, request
|
||||
).retrieve_function_dict()
|
||||
func.func_code = cls.match_endpoint_with_accessible_event(
|
||||
endpoint_url, request
|
||||
)
|
||||
if inspect.iscoroutinefunction(authenticated_func):
|
||||
result = await authenticated_func(request, *args, **kwargs)
|
||||
else:
|
||||
|
|
@ -289,9 +294,14 @@ class TokenEventMiddleware:
|
|||
wrapper.auth = function_auth
|
||||
func.auth = function_auth
|
||||
authenticated_func.auth = function_auth
|
||||
# If result is a coroutine, await it
|
||||
if inspect.iscoroutine(result):
|
||||
result = await result
|
||||
if inspect.iscoroutinefunction(authenticated_func):
|
||||
result = await authenticated_func(request, *args, **kwargs)
|
||||
else:
|
||||
result = authenticated_func(request, *args, **kwargs)
|
||||
if inspect.iscoroutinefunction(func):
|
||||
result = await func(request, *args, **kwargs)
|
||||
else:
|
||||
result = func(request, *args, **kwargs)
|
||||
return result
|
||||
|
||||
return wrapper
|
||||
|
|
@ -11,7 +11,7 @@ from sqlalchemy import (
|
|||
)
|
||||
|
||||
from Services.PostgresDb import CrudCollection
|
||||
from LanguageModels.Database.account.account import (
|
||||
from ApiLayers.LanguageModels.Database.account.account import (
|
||||
AccountBooksLanguageModel,
|
||||
AccountCodesLanguageModel,
|
||||
AccountRecordsLanguageModel,
|
||||
|
|
|
|||
|
|
@ -15,17 +15,17 @@ from sqlalchemy import (
|
|||
or_,
|
||||
)
|
||||
|
||||
from ApiLibrary import system_arrow, SelectActionWithEmployee
|
||||
from ApiLayers.ApiLibrary import system_arrow, SelectActionWithEmployee
|
||||
from Services.PostgresDb import CrudCollection
|
||||
from ApiValidations.Request import (
|
||||
from ApiLayers.ApiValidations.Request import (
|
||||
InsertBuild,
|
||||
InsertBuildParts,
|
||||
InsertBuildLivingSpace,
|
||||
UpdateBuild,
|
||||
)
|
||||
|
||||
from ApiValidations.Custom.token_objects import EmployeeTokenObject, OccupantTokenObject
|
||||
from LanguageModels.Database.building.build import (
|
||||
from ApiLayers.ApiValidations.Custom.token_objects import EmployeeTokenObject, OccupantTokenObject
|
||||
from ApiLayers.LanguageModels.Database.building.build import (
|
||||
BuildTypesLanguageModel,
|
||||
Part2EmployeeLanguageModel,
|
||||
BuildPartsLanguageModel,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from decimal import Decimal
|
|||
from typing import List
|
||||
from fastapi import HTTPException, status
|
||||
|
||||
from ApiLibrary.date_time_actions.date_functions import system_arrow
|
||||
from ApiLayers.ApiLibrary.date_time_actions.date_functions import system_arrow
|
||||
|
||||
from sqlalchemy import (
|
||||
String,
|
||||
|
|
@ -19,14 +19,14 @@ from sqlalchemy import (
|
|||
)
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from ApiValidations.Request import (
|
||||
from ApiLayers.ApiValidations.Request import (
|
||||
InsertDecisionBook,
|
||||
InsertBuildDecisionBookItems,
|
||||
InsertBuildDecisionBookItemDebits,
|
||||
InsertBuildDecisionBookProjects,
|
||||
)
|
||||
from Services.PostgresDb import CrudCollection
|
||||
from LanguageModels.Database.building.decision_book import (
|
||||
from ApiLayers.LanguageModels.Database.building.decision_book import (
|
||||
BuildDecisionBookLanguageModel,
|
||||
BuildDecisionBookInvitationsLanguageModel,
|
||||
BuildDecisionBookPersonLanguageModel,
|
||||
|
|
|
|||
|
|
@ -11,14 +11,14 @@ from sqlalchemy import (
|
|||
)
|
||||
from sqlalchemy.orm import mapped_column, relationship, Mapped
|
||||
|
||||
from ApiLibrary.extensions.select import SelectAction
|
||||
from ApiValidations.Custom.token_objects import EmployeeTokenObject
|
||||
from ApiValidations.Request import (
|
||||
from ApiLayers.ApiLibrary.extensions.select import SelectAction
|
||||
from ApiLayers.ApiValidations.Custom.token_objects import EmployeeTokenObject
|
||||
from ApiLayers.ApiValidations.Request import (
|
||||
InsertCompany,
|
||||
UpdateCompany,
|
||||
MatchCompany2Company,
|
||||
)
|
||||
from LanguageModels.Database.company.company import (
|
||||
from ApiLayers.LanguageModels.Database.company.company import (
|
||||
RelationshipDutyCompanyLanguageModel,
|
||||
CompaniesLanguageModel,
|
||||
# CompanyDutiesLanguageModel,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from sqlalchemy import (
|
|||
)
|
||||
from sqlalchemy.orm import mapped_column, Mapped
|
||||
|
||||
from LanguageModels.Database.company.employee import (
|
||||
from ApiLayers.LanguageModels.Database.company.employee import (
|
||||
StaffLanguageModel,
|
||||
EmployeesLanguageModel,
|
||||
EmployeeHistoryLanguageModel,
|
||||
|
|
@ -14,7 +14,7 @@ from LanguageModels.Database.company.employee import (
|
|||
)
|
||||
from Services.PostgresDb import CrudCollection
|
||||
|
||||
from ApiValidations.Request import InsertCompanyEmployees
|
||||
from ApiLayers.ApiValidations.Request import InsertCompanyEmployees
|
||||
|
||||
|
||||
class Staff(CrudCollection):
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
from Services.PostgresDb import CrudCollection
|
||||
from LanguageModels.Database.event.event import (
|
||||
from ApiLayers.LanguageModels.Database.event.event import (
|
||||
EventsLanguageModel,
|
||||
ModulesLanguageModel,
|
||||
ServicesLanguageModel,
|
||||
|
|
|
|||
|
|
@ -8,24 +8,23 @@ from sqlalchemy import (
|
|||
ForeignKey,
|
||||
Index,
|
||||
TIMESTAMP,
|
||||
func,
|
||||
Text,
|
||||
BigInteger,
|
||||
Numeric,
|
||||
func,
|
||||
or_,
|
||||
)
|
||||
from sqlalchemy.orm import mapped_column, relationship, Mapped
|
||||
|
||||
from ApiLibrary.date_time_actions.date_functions import system_arrow
|
||||
from AllConfigs.Token.config import Auth, ApiStatic
|
||||
from ApiLibrary.extensions.select import SelectAction, SelectActionWithEmployee
|
||||
from ApiLayers.ApiLibrary.date_time_actions.date_functions import system_arrow
|
||||
from ApiLayers.ApiLibrary.extensions.select import SelectAction, SelectActionWithEmployee
|
||||
|
||||
from ApiLayers.AllConfigs.Token.config import Auth
|
||||
from Services.PostgresDb import CrudCollection
|
||||
from config import ApiStatic
|
||||
|
||||
# from databases.extensions import SelectAction, SelectActionWithEmployee
|
||||
# from databases.extensions.auth import UserLoginModule
|
||||
from ApiValidations.Request import InsertUsers, InsertPerson
|
||||
from LanguageModels.Database.identity.identity import (
|
||||
from ApiLayers.ApiValidations.Request import InsertUsers, InsertPerson
|
||||
from ApiLayers.LanguageModels.Database.identity.identity import (
|
||||
UsersTokensLanguageModel,
|
||||
UsersLanguageModel,
|
||||
PeopleLanguageModel,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from sqlalchemy import String
|
||||
from sqlalchemy.orm import mapped_column, Mapped
|
||||
|
||||
from LanguageModels.Database.rules.rules import EndpointRestrictionLanguageModel
|
||||
from ApiLayers.LanguageModels.Database.rules.rules import EndpointRestrictionLanguageModel
|
||||
from Services.PostgresDb import CrudCollection
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -19,15 +19,18 @@ RUN poetry config virtualenvs.create false \
|
|||
&& rm -rf ~/.cache/pypoetry
|
||||
|
||||
# Copy application code
|
||||
COPY DockerApiServices/AllApiNeeds /app
|
||||
COPY DockerApiServices/AuthServiceApi /app
|
||||
|
||||
# Copy application code
|
||||
COPY ApiLayers /app/ApiLayers
|
||||
COPY Services /app/Services
|
||||
|
||||
# Events
|
||||
COPY Events/AllEvents/auth /app/Events/AllEvents/auth
|
||||
# COPY Events/base_request_model.py /app/Events/base_request_model.py
|
||||
COPY Events/Engine /app/Events/Engine
|
||||
COPY Events/base_request_model.py /app/Events/base_request_model.py
|
||||
COPY Events/abstract_class.py /app/Events/abstract_class.py
|
||||
COPY Events/AllEvents/authentication /app/Events/AllEvents/authentication
|
||||
COPY DockerApiServices/AuthServiceApi/events_file.py /app/Events/AllEvents/events_file.py
|
||||
|
||||
# Set Python path to include app directory
|
||||
ENV PYTHONPATH=/app \
|
||||
|
|
|
|||
|
|
@ -10,9 +10,11 @@ This module initializes and configures the FastAPI application with:
|
|||
"""
|
||||
|
||||
import uvicorn
|
||||
|
||||
from prometheus_fastapi_instrumentator import Instrumentator
|
||||
from app_handler import setup_middleware, get_uvicorn_config
|
||||
from app_handler import setup_middleware
|
||||
from create_file import create_app
|
||||
from config import ApiConfig
|
||||
|
||||
|
||||
app = create_app() # Initialize FastAPI application
|
||||
|
|
@ -21,5 +23,5 @@ setup_middleware(app) # Configure middleware and exception handlers
|
|||
|
||||
|
||||
if __name__ == "__main__":
|
||||
uvicorn_config = get_uvicorn_config() # Run the application with Uvicorn
|
||||
uvicorn.Server(uvicorn.Config(**uvicorn_config)).run()
|
||||
# Run the application with Uvicorn
|
||||
uvicorn.Server(uvicorn.Config(**ApiConfig.as_dict())).run()
|
||||
|
|
@ -7,13 +7,12 @@ This module contains all the handler functions for configuring and setting up th
|
|||
- Uvicorn server configuration
|
||||
"""
|
||||
|
||||
from typing import Dict, Any
|
||||
|
||||
from fastapi import FastAPI, Request, status
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi import FastAPI, Request, HTTPException, status
|
||||
from fastapi.responses import JSONResponse
|
||||
from ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
|
||||
from middleware.auth_middleware import RequestTimingMiddleware, LoggerTimingMiddleware
|
||||
|
||||
from ApiLayers.ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
|
||||
from ApiLayers.Middleware.auth_middleware import RequestTimingMiddleware, LoggerTimingMiddleware
|
||||
|
||||
|
||||
def setup_cors_middleware(app: FastAPI) -> None:
|
||||
|
|
@ -56,7 +55,7 @@ def setup_exception_handlers(app: FastAPI) -> None:
|
|||
Args:
|
||||
app: FastAPI application instance
|
||||
"""
|
||||
from ErrorHandlers.ErrorHandlers.api_exc_handler import HTTPExceptionApiHandler
|
||||
from ApiLayers.ErrorHandlers.ErrorHandlers.api_exc_handler import HTTPExceptionApiHandler
|
||||
|
||||
custom_exception_handler = HTTPExceptionApiHandler(response_model=JSONResponse)
|
||||
app.add_exception_handler(
|
||||
|
|
@ -76,19 +75,3 @@ def setup_middleware(app: FastAPI) -> None:
|
|||
app.add_middleware(RequestTimingMiddleware)
|
||||
app.add_middleware(LoggerTimingMiddleware)
|
||||
setup_exception_handlers(app)
|
||||
|
||||
|
||||
def get_uvicorn_config() -> Dict[str, Any]:
|
||||
"""
|
||||
Get Uvicorn server configuration.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: Uvicorn configuration dictionary
|
||||
"""
|
||||
return {
|
||||
"app": "app:app",
|
||||
"host": "0.0.0.0",
|
||||
"port": 41575,
|
||||
"log_level": "info",
|
||||
"reload": True,
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
|
||||
class DefaultApiConfig:
|
||||
app: str
|
||||
host: str
|
||||
port: int
|
||||
log_level: str
|
||||
reload: bool
|
||||
|
||||
@classmethod
|
||||
def as_dict(cls):
|
||||
return {
|
||||
"app": cls.app,
|
||||
"host": cls.host,
|
||||
"port": int(cls.port),
|
||||
"log_level": cls.log_level,
|
||||
"reload": bool(cls.reload),
|
||||
}
|
||||
|
||||
|
||||
class ApiStatic:
|
||||
PLACEHOLDER = "https://s.tmimgcdn.com/scr/800x500/276800/building-home-nature-logo-vector-template-3_276851-original.jpg"
|
||||
FORGOT_LINK = "https://www.evyos.com.tr/password/create?tokenUrl="
|
||||
BLACKLIST_LINK = "https://www.evyos.com.tr/support/unknown-login-notice/"
|
||||
APP_DIR = "/home/berkay/git-evyos/api-managment-backend/"
|
||||
|
||||
@classmethod
|
||||
def forgot_link(cls, forgot_key):
|
||||
return cls.FORGOT_LINK + forgot_key
|
||||
|
||||
@classmethod
|
||||
def blacklist_login(cls, record_id):
|
||||
return cls.BLACKLIST_LINK + record_id
|
||||
|
||||
|
||||
class HostConfig:
|
||||
MAIN_HOST = "10.10.2.36" # http://10.10.2.36
|
||||
EMAIL_HOST = "10.10.2.34" # http://10.10.2.34
|
||||
|
||||
|
||||
class ApiConfig(DefaultApiConfig):
|
||||
# Application Information
|
||||
APP_NAME = "evyos-auth-api-gateway"
|
||||
TITLE = "WAG API Auth Api Gateway"
|
||||
DESCRIPTION = "This api is serves as web auth api gateway only to evyos web services."
|
||||
APP_URL = "https://www.auth.eys.gen.tr"
|
||||
|
||||
# Server Configuration
|
||||
app = "app:app"
|
||||
host = "0.0.0.0"
|
||||
port = 41575
|
||||
log_level = "info"
|
||||
reload = True
|
||||
|
||||
|
||||
class MainConfig:
|
||||
|
||||
# Date and Time Configuration
|
||||
DATETIME_FORMAT = "YYYY-MM-DD HH:mm:ss Z"
|
||||
DATETIME_FORMAT_JS = "YYYY-MM-DD HH:mm:ss +0"
|
||||
|
||||
# Timezone Configuration
|
||||
DEFAULT_TIMEZONE = "GMT+3" # Default timezone for the application
|
||||
SYSTEM_TIMEZONE = "GMT+0" # System timezone (used for internal operations)
|
||||
SUPPORTED_TIMEZONES = ["GMT+0", "GMT+3"] # List of supported timezones
|
||||
|
||||
|
||||
class LanguageConfig:
|
||||
|
||||
SUPPORTED_LANGUAGES = ["en", "tr"]
|
||||
DEFAULT_LANGUAGE = "tr"
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
"""
|
||||
FastAPI Application Factory Module
|
||||
|
||||
This module provides functionality to create and configure a FastAPI application with:
|
||||
- Custom OpenAPI schema configuration
|
||||
- Security scheme configuration for Bearer authentication
|
||||
- Automatic router registration
|
||||
- Response class configuration
|
||||
- Security requirements for protected endpoints
|
||||
"""
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.responses import JSONResponse, RedirectResponse
|
||||
|
||||
from config import ApiConfig
|
||||
from create_routes import get_all_routers
|
||||
|
||||
|
||||
def create_app() -> FastAPI:
|
||||
"""
|
||||
Create and configure a FastAPI application with dynamic route creation.
|
||||
|
||||
Returns:
|
||||
FastAPI: Configured FastAPI application instance
|
||||
"""
|
||||
|
||||
from open_api_creator import create_openapi_schema
|
||||
|
||||
app = FastAPI(
|
||||
title=ApiConfig.TITLE,
|
||||
description=ApiConfig.DESCRIPTION,
|
||||
default_response_class=JSONResponse,
|
||||
) # Initialize FastAPI app
|
||||
|
||||
@app.get("/", include_in_schema=False, summary=str(ApiConfig.DESCRIPTION))
|
||||
def home() -> RedirectResponse:
|
||||
"""Redirect root path to API documentation."""
|
||||
return RedirectResponse(url="/docs")
|
||||
|
||||
# Get all routers and protected routes using the dynamic route creation
|
||||
prepare_routing = get_all_routers()
|
||||
|
||||
# Include all routers
|
||||
for router in prepare_routing.routers:
|
||||
app.include_router(router)
|
||||
|
||||
app.openapi = lambda app=app: create_openapi_schema(app)
|
||||
return app
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
"""
|
||||
Route configuration and factory module.
|
||||
Handles dynamic route creation based on configurations.
|
||||
"""
|
||||
|
||||
from fastapi import Request
|
||||
from Events.Engine.set_defaults.setClusters import PrepareRouting
|
||||
|
||||
|
||||
async def health_check(request: Request):
|
||||
"""Default health check endpoint."""
|
||||
return {"status": "healthy", "message": "Service is running"}
|
||||
|
||||
|
||||
async def ping_test(request: Request, service_name: str = "base-router"):
|
||||
"""Default ping test endpoint."""
|
||||
return {"ping": "pong", "service": service_name}
|
||||
|
||||
|
||||
def get_all_routers() -> PrepareRouting:
|
||||
"""
|
||||
Get all routers and protected routes from route configurations.
|
||||
|
||||
Returns:
|
||||
tuple: (routers, protected_routes)
|
||||
"""
|
||||
from Events.Engine.set_defaults.run import get_cluster_controller_group
|
||||
|
||||
cluster_list = get_cluster_controller_group()
|
||||
prepare_routing = PrepareRouting(cluster_controller_group=cluster_list)
|
||||
return prepare_routing
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
import Events.AllEvents.authentication as auths_events
|
||||
|
||||
events_list = (auths_events,)
|
||||
|
|
@ -9,14 +9,13 @@ This module provides functionality to create and customize OpenAPI documentation
|
|||
- Custom documentation extensions
|
||||
"""
|
||||
|
||||
from typing import Any, Dict, List, Optional, Set
|
||||
from fastapi import FastAPI, APIRouter
|
||||
from typing import Any, Dict
|
||||
from fastapi import FastAPI
|
||||
from fastapi.routing import APIRoute
|
||||
from fastapi.openapi.utils import get_openapi
|
||||
|
||||
from AllConfigs.Token.config import Auth
|
||||
from AllConfigs.main import MainConfig as Config
|
||||
from create_routes import get_all_routers
|
||||
from config import ApiConfig
|
||||
|
||||
|
||||
class OpenAPISchemaCreator:
|
||||
|
|
@ -32,28 +31,8 @@ class OpenAPISchemaCreator:
|
|||
app: FastAPI application instance
|
||||
"""
|
||||
self.app = app
|
||||
_, self.protected_routes = get_all_routers()
|
||||
# self.tags_metadata = self._create_tags_metadata()
|
||||
|
||||
@staticmethod
|
||||
def _create_tags_metadata() -> List[Dict[str, str]]:
|
||||
"""
|
||||
Create metadata for API tags.
|
||||
|
||||
Returns:
|
||||
List[Dict[str, str]]: List of tag metadata
|
||||
"""
|
||||
return [
|
||||
{
|
||||
"name": "Authentication",
|
||||
"description": "Operations related to user authentication and authorization",
|
||||
},
|
||||
{
|
||||
"name": "Users",
|
||||
"description": "User management and profile operations",
|
||||
},
|
||||
# Add more tags as needed
|
||||
]
|
||||
self.cluster = get_all_routers()
|
||||
self.safe_endpoint_list = self.cluster.safe_endpoints if hasattr(self.cluster, 'safe_endpoints') else []
|
||||
|
||||
def _create_security_schemes(self) -> Dict[str, Any]:
|
||||
"""
|
||||
|
|
@ -62,8 +41,9 @@ class OpenAPISchemaCreator:
|
|||
Returns:
|
||||
Dict[str, Any]: Security scheme configurations
|
||||
"""
|
||||
from ApiLayers.AllConfigs.Token.config import Auth
|
||||
return {
|
||||
"Bearer Auth": {
|
||||
"BearerAuth": {
|
||||
"type": "apiKey",
|
||||
"in": "header",
|
||||
"name": Auth.ACCESS_TOKEN_TAG,
|
||||
|
|
@ -206,19 +186,17 @@ class OpenAPISchemaCreator:
|
|||
method: HTTP method
|
||||
schema: OpenAPI schema to modify
|
||||
"""
|
||||
# Check if route is protected based on dynamic routing info
|
||||
if path in self.protected_routes and method in self.protected_routes[path]:
|
||||
schema["paths"][path][method]["security"] = [
|
||||
{"Bearer Auth": []},
|
||||
]
|
||||
schema["paths"][path][method]["responses"].update(
|
||||
self._create_common_responses()
|
||||
)
|
||||
if not schema.get("paths", {}).get(path, {}).get(method):
|
||||
return
|
||||
|
||||
# Process request body examples
|
||||
self._process_request_body(path, method, schema)
|
||||
# Process response examples
|
||||
self._process_response_examples(path, method, schema)
|
||||
# Check if endpoint is in safe list
|
||||
endpoint_path = f"{path}:{method}"
|
||||
if endpoint_path not in [f"{e.URL}:{e.METHOD.lower()}" for e in self.safe_endpoint_list]:
|
||||
if "security" not in schema["paths"][path][method]:
|
||||
schema["paths"][path][method]["security"] = []
|
||||
schema["paths"][path][method]["security"].append(
|
||||
{"BearerAuth": []}
|
||||
)
|
||||
|
||||
def create_schema(self) -> Dict[str, Any]:
|
||||
"""
|
||||
|
|
@ -228,8 +206,8 @@ class OpenAPISchemaCreator:
|
|||
Dict[str, Any]: Complete OpenAPI schema
|
||||
"""
|
||||
openapi_schema = get_openapi(
|
||||
title=Config.TITLE,
|
||||
description=Config.DESCRIPTION,
|
||||
title=ApiConfig.TITLE,
|
||||
description=ApiConfig.DESCRIPTION,
|
||||
version="1.1.1",
|
||||
routes=self.app.routes,
|
||||
)
|
||||
|
|
@ -238,9 +216,8 @@ class OpenAPISchemaCreator:
|
|||
if "components" not in openapi_schema:
|
||||
openapi_schema["components"] = {}
|
||||
|
||||
openapi_schema["components"][
|
||||
"securitySchemes"
|
||||
] = self._create_security_schemes()
|
||||
openapi_schema["components"]["securitySchemes"] = self._create_security_schemes()
|
||||
|
||||
# Configure route security and responses
|
||||
for route in self.app.routes:
|
||||
if isinstance(route, APIRoute) and route.include_in_schema:
|
||||
|
|
@ -249,13 +226,12 @@ class OpenAPISchemaCreator:
|
|||
for method in methods:
|
||||
self.configure_route_security(path, method, openapi_schema)
|
||||
|
||||
# # Add custom documentation extensions
|
||||
# Add custom documentation extensions
|
||||
openapi_schema["x-documentation"] = {
|
||||
"postman_collection": "/docs/postman",
|
||||
"swagger_ui": "/docs",
|
||||
"redoc": "/redoc",
|
||||
}
|
||||
|
||||
return openapi_schema
|
||||
|
||||
|
||||
|
|
@ -19,22 +19,18 @@ RUN poetry config virtualenvs.create false \
|
|||
&& rm -rf ~/.cache/pypoetry
|
||||
|
||||
# Copy application code
|
||||
COPY DockerApiServices/AllApiNeeds /app
|
||||
COPY ErrorHandlers /app/ErrorHandlers
|
||||
COPY LanguageModels /app/LanguageModels
|
||||
COPY ApiLibrary /app/ApiLibrary
|
||||
COPY ApiValidations /app/ApiValidations
|
||||
COPY AllConfigs /app/AllConfigs
|
||||
COPY ErrorHandlers /app/ErrorHandlers
|
||||
COPY Schemas /app/Schemas
|
||||
COPY DockerApiServices/EventServiceApi /app
|
||||
|
||||
# Copy application code
|
||||
COPY ApiLayers /app/ApiLayers
|
||||
COPY Services /app/Services
|
||||
COPY ApiServices /app/ApiServices
|
||||
|
||||
# Copy Events structure with consistent naming
|
||||
COPY ApiEvents/EventServiceApi /app/ApiEvents
|
||||
COPY ApiEvents/abstract_class.py /app/ApiEvents/abstract_class.py
|
||||
COPY ApiEvents/base_request_model.py /app/ApiEvents/base_request_model.py
|
||||
|
||||
# Events
|
||||
# COPY Events/base_request_model.py /app/Events/base_request_model.py
|
||||
COPY Events/Engine /app/Events/Engine
|
||||
COPY Events/base_request_model.py /app/Events/base_request_model.py
|
||||
COPY Events/AllEvents/events /app/Events/AllEvents/events
|
||||
COPY DockerApiServices/EventServiceApi/events_file.py /app/Events/AllEvents/events_file.py
|
||||
|
||||
# Set Python path to include app directory
|
||||
ENV PYTHONPATH=/app \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
"""
|
||||
FastAPI Application Entry Point
|
||||
|
||||
This module initializes and configures the FastAPI application with:
|
||||
- CORS middleware for cross-origin requests
|
||||
- Request timing middleware for performance monitoring
|
||||
- Custom exception handlers for consistent error responses
|
||||
- Prometheus instrumentation for metrics
|
||||
- API routers for endpoint organization
|
||||
"""
|
||||
|
||||
import uvicorn
|
||||
|
||||
from prometheus_fastapi_instrumentator import Instrumentator
|
||||
from app_handler import setup_middleware
|
||||
from create_file import create_app
|
||||
from config import ApiConfig
|
||||
|
||||
|
||||
app = create_app() # Initialize FastAPI application
|
||||
Instrumentator().instrument(app=app).expose(app=app) # Setup Prometheus metrics
|
||||
setup_middleware(app) # Configure middleware and exception handlers
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Run the application with Uvicorn
|
||||
uvicorn.Server(uvicorn.Config(**ApiConfig.as_dict())).run()
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
"""
|
||||
FastAPI Application Handler Module
|
||||
|
||||
This module contains all the handler functions for configuring and setting up the FastAPI application:
|
||||
- CORS middleware configuration
|
||||
- Exception handlers setup
|
||||
- Uvicorn server configuration
|
||||
"""
|
||||
|
||||
from fastapi import FastAPI, Request, status
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from ApiLayers.ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
|
||||
from ApiLayers.Middleware.auth_middleware import RequestTimingMiddleware, LoggerTimingMiddleware
|
||||
|
||||
|
||||
def setup_cors_middleware(app: FastAPI) -> None:
|
||||
"""
|
||||
Configure CORS middleware for the application.
|
||||
|
||||
Args:
|
||||
app: FastAPI application instance
|
||||
"""
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
|
||||
async def generic_exception_handler(request: Request, exc: Exception) -> JSONResponse:
|
||||
"""
|
||||
Handle generic exceptions and return formatted error responses.
|
||||
|
||||
Args:
|
||||
request: FastAPI request object
|
||||
exc: Exception instance
|
||||
|
||||
Returns:
|
||||
JSONResponse: Formatted error response
|
||||
"""
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
content={"detail": "Internal server error", "error_code": "INTERNAL_ERROR"},
|
||||
)
|
||||
|
||||
|
||||
def setup_exception_handlers(app: FastAPI) -> None:
|
||||
"""
|
||||
Configure custom exception handlers for the application.
|
||||
|
||||
Args:
|
||||
app: FastAPI application instance
|
||||
"""
|
||||
from ApiLayers.ErrorHandlers.ErrorHandlers.api_exc_handler import HTTPExceptionApiHandler
|
||||
|
||||
custom_exception_handler = HTTPExceptionApiHandler(response_model=JSONResponse)
|
||||
app.add_exception_handler(
|
||||
HTTPExceptionApi, custom_exception_handler.handle_exception
|
||||
)
|
||||
app.add_exception_handler(Exception, generic_exception_handler)
|
||||
|
||||
|
||||
def setup_middleware(app: FastAPI) -> None:
|
||||
"""
|
||||
Configure all middleware for the application.
|
||||
|
||||
Args:
|
||||
app: FastAPI application instance
|
||||
"""
|
||||
setup_cors_middleware(app)
|
||||
app.add_middleware(RequestTimingMiddleware)
|
||||
app.add_middleware(LoggerTimingMiddleware)
|
||||
setup_exception_handlers(app)
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
|
||||
class DefaultApiConfig:
|
||||
app: str
|
||||
host: str
|
||||
port: int
|
||||
log_level: str
|
||||
reload: bool
|
||||
|
||||
@classmethod
|
||||
def as_dict(cls):
|
||||
return {
|
||||
"app": cls.app,
|
||||
"host": cls.host,
|
||||
"port": int(cls.port),
|
||||
"log_level": cls.log_level,
|
||||
"reload": bool(cls.reload),
|
||||
}
|
||||
|
||||
|
||||
class ApiStatic:
|
||||
PLACEHOLDER = "https://s.tmimgcdn.com/scr/800x500/276800/building-home-nature-logo-vector-template-3_276851-original.jpg"
|
||||
FORGOT_LINK = "https://www.evyos.com.tr/password/create?tokenUrl="
|
||||
BLACKLIST_LINK = "https://www.evyos.com.tr/support/unknown-login-notice/"
|
||||
APP_DIR = "/home/berkay/git-evyos/api-managment-backend/"
|
||||
|
||||
@classmethod
|
||||
def forgot_link(cls, forgot_key):
|
||||
return cls.FORGOT_LINK + forgot_key
|
||||
|
||||
@classmethod
|
||||
def blacklist_login(cls, record_id):
|
||||
return cls.BLACKLIST_LINK + record_id
|
||||
|
||||
|
||||
|
||||
class ApiConfig(DefaultApiConfig):
|
||||
# Api configuration
|
||||
APP_NAME = "evyos-event-api-gateway"
|
||||
TITLE = "WAG API Event Api Gateway"
|
||||
DESCRIPTION = "This api is serves as web event api gateway only to evyos web services."
|
||||
APP_URL = "https://www.event.eys.gen.tr"
|
||||
|
||||
# Uvicorn server configuration
|
||||
app = "app:app"
|
||||
host = "0.0.0.0"
|
||||
port = 41576
|
||||
log_level = "info"
|
||||
reload = True
|
||||
|
||||
|
||||
class MainConfig:
|
||||
# Date and Time Configuration
|
||||
DATETIME_FORMAT = "YYYY-MM-DD HH:mm:ss Z"
|
||||
DATETIME_FORMAT_JS = "YYYY-MM-DD HH:mm:ss +0"
|
||||
|
||||
# Timezone Configuration
|
||||
DEFAULT_TIMEZONE = "GMT+3" # Default timezone for the application
|
||||
SYSTEM_TIMEZONE = "GMT+0" # System timezone (used for internal operations)
|
||||
SUPPORTED_TIMEZONES = ["GMT+0", "GMT+3"] # List of supported timezones
|
||||
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
"""
|
||||
FastAPI Application Factory Module
|
||||
|
||||
This module provides functionality to create and configure a FastAPI application with:
|
||||
- Custom OpenAPI schema configuration
|
||||
- Security scheme configuration for Bearer authentication
|
||||
- Automatic router registration
|
||||
- Response class configuration
|
||||
- Security requirements for protected endpoints
|
||||
"""
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.responses import JSONResponse, RedirectResponse
|
||||
|
||||
from config import ApiConfig
|
||||
from create_routes import get_all_routers
|
||||
|
||||
|
||||
def create_app() -> FastAPI:
|
||||
"""
|
||||
Create and configure a FastAPI application with dynamic route creation.
|
||||
|
||||
Returns:
|
||||
FastAPI: Configured FastAPI application instance
|
||||
"""
|
||||
|
||||
from open_api_creator import create_openapi_schema
|
||||
|
||||
app = FastAPI(
|
||||
title=ApiConfig.TITLE,
|
||||
description=ApiConfig.DESCRIPTION,
|
||||
default_response_class=JSONResponse,
|
||||
) # Initialize FastAPI app
|
||||
|
||||
@app.get("/", include_in_schema=False, summary=str(ApiConfig.DESCRIPTION))
|
||||
def home() -> RedirectResponse:
|
||||
"""Redirect root path to API documentation."""
|
||||
return RedirectResponse(url="/docs")
|
||||
|
||||
# Get all routers and protected routes using the dynamic route creation
|
||||
prepare_routing = get_all_routers()
|
||||
|
||||
# Include all routers
|
||||
for router in prepare_routing.routers:
|
||||
app.include_router(router)
|
||||
|
||||
app.openapi = lambda app=app: create_openapi_schema(app)
|
||||
return app
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
"""
|
||||
Route configuration and factory module.
|
||||
Handles dynamic route creation based on configurations.
|
||||
"""
|
||||
|
||||
from fastapi import Request
|
||||
from Events.Engine.set_defaults.setClusters import PrepareRouting
|
||||
|
||||
|
||||
async def health_check(request: Request):
|
||||
"""Default health check endpoint."""
|
||||
return {"status": "healthy", "message": "Service is running"}
|
||||
|
||||
|
||||
async def ping_test(request: Request, service_name: str = "base-router"):
|
||||
"""Default ping test endpoint."""
|
||||
return {"ping": "pong", "service": service_name}
|
||||
|
||||
|
||||
def get_all_routers() -> PrepareRouting:
|
||||
"""
|
||||
Get all routers and protected routes from route configurations.
|
||||
|
||||
Returns:
|
||||
tuple: (routers, protected_routes)
|
||||
"""
|
||||
from Events.Engine.set_defaults.run import get_cluster_controller_group
|
||||
|
||||
cluster_list = get_cluster_controller_group()
|
||||
prepare_routing = PrepareRouting(cluster_controller_group=cluster_list)
|
||||
return prepare_routing
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
import Events.AllEvents.events as events_events
|
||||
|
||||
events_list = (events_events,)
|
||||
|
|
@ -0,0 +1,249 @@
|
|||
"""
|
||||
OpenAPI Schema Creator Module
|
||||
|
||||
This module provides functionality to create and customize OpenAPI documentation:
|
||||
- Custom security schemes (Bearer Auth, API Key)
|
||||
- Response schemas and examples
|
||||
- Tag management and descriptions
|
||||
- Error responses and validation
|
||||
- Custom documentation extensions
|
||||
"""
|
||||
|
||||
from typing import Any, Dict
|
||||
from fastapi import FastAPI
|
||||
from fastapi.routing import APIRoute
|
||||
from fastapi.openapi.utils import get_openapi
|
||||
|
||||
from create_routes import get_all_routers
|
||||
from config import ApiConfig
|
||||
|
||||
|
||||
class OpenAPISchemaCreator:
|
||||
"""
|
||||
OpenAPI schema creator and customizer for FastAPI applications.
|
||||
"""
|
||||
|
||||
def __init__(self, app: FastAPI):
|
||||
"""
|
||||
Initialize the OpenAPI schema creator.
|
||||
|
||||
Args:
|
||||
app: FastAPI application instance
|
||||
"""
|
||||
self.app = app
|
||||
self.cluster = get_all_routers()
|
||||
self.safe_endpoint_list = self.cluster.safe_endpoints if hasattr(self.cluster, 'safe_endpoints') else []
|
||||
|
||||
def _create_security_schemes(self) -> Dict[str, Any]:
|
||||
"""
|
||||
Create security scheme definitions.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: Security scheme configurations
|
||||
"""
|
||||
from ApiLayers.AllConfigs.Token.config import Auth
|
||||
return {
|
||||
"BearerAuth": {
|
||||
"type": "apiKey",
|
||||
"in": "header",
|
||||
"name": Auth.ACCESS_TOKEN_TAG,
|
||||
"description": "Enter: **'Bearer <JWT>'**, where JWT is the access token",
|
||||
}
|
||||
}
|
||||
|
||||
def _create_common_responses(self) -> Dict[str, Any]:
|
||||
"""
|
||||
Create common response schemas.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: Common response configurations
|
||||
"""
|
||||
return {
|
||||
"401": {
|
||||
"description": "Unauthorized - Invalid or missing credentials",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/HTTPValidationError"}
|
||||
}
|
||||
},
|
||||
},
|
||||
"403": {
|
||||
"description": "Forbidden - Insufficient permissions",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/HTTPValidationError"}
|
||||
}
|
||||
},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/HTTPValidationError"}
|
||||
}
|
||||
},
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {"type": "string"},
|
||||
"error_code": {"type": "string"},
|
||||
},
|
||||
},
|
||||
"example": {
|
||||
"detail": "Internal server error occurred",
|
||||
"error_code": "INTERNAL_ERROR",
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
def _process_request_body(
|
||||
self, path: str, method: str, schema: Dict[str, Any]
|
||||
) -> None:
|
||||
"""
|
||||
Process request body to include examples from model config.
|
||||
|
||||
Args:
|
||||
path: Route path
|
||||
method: HTTP method
|
||||
schema: OpenAPI schema to modify
|
||||
"""
|
||||
try:
|
||||
route_schema = schema["paths"][path][method]
|
||||
if "requestBody" in route_schema:
|
||||
request_body = route_schema["requestBody"]
|
||||
if "content" in request_body:
|
||||
content = request_body["content"]
|
||||
if "application/json" in content:
|
||||
json_content = content["application/json"]
|
||||
if (
|
||||
"schema" in json_content
|
||||
and "$ref" in json_content["schema"]
|
||||
):
|
||||
ref = json_content["schema"]["$ref"]
|
||||
model_name = ref.split("/")[-1]
|
||||
if model_name in schema["components"]["schemas"]:
|
||||
model_schema = schema["components"]["schemas"][
|
||||
model_name
|
||||
]
|
||||
if "example" in model_schema:
|
||||
json_content["example"] = model_schema["example"]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def _process_response_examples(
|
||||
self, path: str, method: str, schema: Dict[str, Any]
|
||||
) -> None:
|
||||
"""
|
||||
Process response body to include examples from model config.
|
||||
|
||||
Args:
|
||||
path: Route path
|
||||
method: HTTP method
|
||||
schema: OpenAPI schema to modify
|
||||
"""
|
||||
try:
|
||||
route_schema = schema["paths"][path][method]
|
||||
if "responses" in route_schema:
|
||||
responses = route_schema["responses"]
|
||||
if "200" in responses:
|
||||
response = responses["200"]
|
||||
if "content" in response:
|
||||
content = response["content"]
|
||||
if "application/json" in content:
|
||||
json_content = content["application/json"]
|
||||
if (
|
||||
"schema" in json_content
|
||||
and "$ref" in json_content["schema"]
|
||||
):
|
||||
ref = json_content["schema"]["$ref"]
|
||||
model_name = ref.split("/")[-1]
|
||||
if model_name in schema["components"]["schemas"]:
|
||||
model_schema = schema["components"]["schemas"][
|
||||
model_name
|
||||
]
|
||||
if "example" in model_schema:
|
||||
json_content["example"] = model_schema[
|
||||
"example"
|
||||
]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def configure_route_security(
|
||||
self, path: str, method: str, schema: Dict[str, Any]
|
||||
) -> None:
|
||||
"""
|
||||
Configure security requirements for a specific route.
|
||||
|
||||
Args:
|
||||
path: Route path
|
||||
method: HTTP method
|
||||
schema: OpenAPI schema to modify
|
||||
"""
|
||||
if not schema.get("paths", {}).get(path, {}).get(method):
|
||||
return
|
||||
|
||||
# Check if endpoint is in safe list
|
||||
endpoint_path = f"{path}:{method}"
|
||||
if endpoint_path not in [f"{e.URL}:{e.METHOD.lower()}" for e in self.safe_endpoint_list]:
|
||||
if "security" not in schema["paths"][path][method]:
|
||||
schema["paths"][path][method]["security"] = []
|
||||
schema["paths"][path][method]["security"].append(
|
||||
{"BearerAuth": []}
|
||||
)
|
||||
|
||||
def create_schema(self) -> Dict[str, Any]:
|
||||
"""
|
||||
Create the complete OpenAPI schema.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: Complete OpenAPI schema
|
||||
"""
|
||||
openapi_schema = get_openapi(
|
||||
title=ApiConfig.TITLE,
|
||||
description=ApiConfig.DESCRIPTION,
|
||||
version="1.1.1",
|
||||
routes=self.app.routes,
|
||||
)
|
||||
|
||||
# Add security schemes
|
||||
if "components" not in openapi_schema:
|
||||
openapi_schema["components"] = {}
|
||||
|
||||
openapi_schema["components"]["securitySchemes"] = self._create_security_schemes()
|
||||
|
||||
# Configure route security and responses
|
||||
for route in self.app.routes:
|
||||
if isinstance(route, APIRoute) and route.include_in_schema:
|
||||
path = str(route.path)
|
||||
methods = [method.lower() for method in route.methods]
|
||||
for method in methods:
|
||||
self.configure_route_security(path, method, openapi_schema)
|
||||
|
||||
# Add custom documentation extensions
|
||||
openapi_schema["x-documentation"] = {
|
||||
"postman_collection": "/docs/postman",
|
||||
"swagger_ui": "/docs",
|
||||
"redoc": "/redoc",
|
||||
}
|
||||
return openapi_schema
|
||||
|
||||
|
||||
def create_openapi_schema(app: FastAPI) -> Dict[str, Any]:
|
||||
"""
|
||||
Create OpenAPI schema for a FastAPI application.
|
||||
|
||||
Args:
|
||||
app: FastAPI application instance
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: Complete OpenAPI schema
|
||||
"""
|
||||
creator = OpenAPISchemaCreator(app)
|
||||
return creator.create_schema()
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
FROM python:3.12-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install system dependencies and Poetry
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
gcc \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& pip install --no-cache-dir poetry
|
||||
|
||||
# Copy Poetry configuration
|
||||
COPY DockerApiServices/pyproject.toml ./pyproject.toml
|
||||
|
||||
# # Configure Poetry and install dependencies with optimizations
|
||||
# RUN poetry config virtualenvs.create false \
|
||||
# && poetry install --no-interaction --no-ansi --no-root --only main \
|
||||
# && pip cache purge \
|
||||
# && rm -rf ~/.cache/pypoetry
|
||||
|
||||
# # Copy application code
|
||||
# COPY DockerApiServices/EventServiceApi /app
|
||||
|
||||
# # Copy application code
|
||||
# COPY ApiLayers /app/ApiLayers
|
||||
# COPY Services /app/Services
|
||||
|
||||
# # Events
|
||||
# # COPY Events/base_request_model.py /app/Events/base_request_model.py
|
||||
# COPY Events/Engine /app/Events/Engine
|
||||
# COPY Events/AllEvents/events /app/Events/AllEvents/events
|
||||
# COPY DockerApiServices/EventServiceApi/events_file.py /app/Events/AllEvents/events_file.py
|
||||
|
||||
# # Set Python path to include app directory
|
||||
# ENV PYTHONPATH=/app \
|
||||
# PYTHONUNBUFFERED=1 \
|
||||
# PYTHONDONTWRITEBYTECODE=1
|
||||
|
||||
# # Run the application using the configured uvicorn server
|
||||
# CMD ["poetry", "run", "python", "app.py"]
|
||||
|
|
@ -19,23 +19,17 @@ RUN poetry config virtualenvs.create false \
|
|||
&& rm -rf ~/.cache/pypoetry
|
||||
|
||||
# Copy application code
|
||||
COPY DockerApiServices/AllApiNeeds /app
|
||||
COPY ErrorHandlers /app/ErrorHandlers
|
||||
COPY LanguageModels /app/LanguageModels
|
||||
COPY ApiLibrary /app/ApiLibrary
|
||||
COPY ApiValidations /app/ApiValidations
|
||||
COPY AllConfigs /app/AllConfigs
|
||||
COPY ErrorHandlers /app/ErrorHandlers
|
||||
COPY Schemas /app/Schemas
|
||||
COPY Services /app/Services
|
||||
COPY ApiServices /app/ApiServices
|
||||
COPY DockerApiServices/ValidationServiceApi /app
|
||||
|
||||
# Copy Events structure with consistent naming
|
||||
COPY ApiEvents/ValidationServiceApi /app/ApiEvents
|
||||
ADD ApiEvents/AuthServiceApi/events /app/ApiEvents/events
|
||||
ADD ApiEvents/EventServiceApi/events /app/ApiEvents/events
|
||||
COPY ApiEvents/abstract_class.py /app/ApiEvents/abstract_class.py
|
||||
COPY ApiEvents/base_request_model.py /app/ApiEvents/base_request_model.py
|
||||
# Copy application code
|
||||
COPY ApiLayers /app/ApiLayers
|
||||
COPY Services /app/Services
|
||||
|
||||
# Events
|
||||
# COPY Events/base_request_model.py /app/Events/base_request_model.py
|
||||
COPY Events/Engine /app/Events/Engine
|
||||
COPY Events/AllEvents/validations /app/Events/AllEvents/validations
|
||||
COPY DockerApiServices/ValidationServiceApi/events_file.py /app/Events/AllEvents/events_file.py
|
||||
|
||||
# Set Python path to include app directory
|
||||
ENV PYTHONPATH=/app \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
"""
|
||||
FastAPI Application Entry Point
|
||||
|
||||
This module initializes and configures the FastAPI application with:
|
||||
- CORS middleware for cross-origin requests
|
||||
- Request timing middleware for performance monitoring
|
||||
- Custom exception handlers for consistent error responses
|
||||
- Prometheus instrumentation for metrics
|
||||
- API routers for endpoint organization
|
||||
"""
|
||||
|
||||
import uvicorn
|
||||
|
||||
from prometheus_fastapi_instrumentator import Instrumentator
|
||||
from app_handler import setup_middleware
|
||||
from create_file import create_app
|
||||
from config import ApiConfig
|
||||
|
||||
|
||||
app = create_app() # Initialize FastAPI application
|
||||
Instrumentator().instrument(app=app).expose(app=app) # Setup Prometheus metrics
|
||||
setup_middleware(app) # Configure middleware and exception handlers
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Run the application with Uvicorn
|
||||
uvicorn.Server(uvicorn.Config(**ApiConfig.as_dict())).run()
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
"""
|
||||
FastAPI Application Handler Module
|
||||
|
||||
This module contains all the handler functions for configuring and setting up the FastAPI application:
|
||||
- CORS middleware configuration
|
||||
- Exception handlers setup
|
||||
- Uvicorn server configuration
|
||||
"""
|
||||
|
||||
from fastapi import FastAPI, Request, status
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from ApiLayers.ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
|
||||
from ApiLayers.Middleware.auth_middleware import RequestTimingMiddleware, LoggerTimingMiddleware
|
||||
|
||||
|
||||
def setup_cors_middleware(app: FastAPI) -> None:
|
||||
"""
|
||||
Configure CORS middleware for the application.
|
||||
|
||||
Args:
|
||||
app: FastAPI application instance
|
||||
"""
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
|
||||
async def generic_exception_handler(request: Request, exc: Exception) -> JSONResponse:
|
||||
"""
|
||||
Handle generic exceptions and return formatted error responses.
|
||||
|
||||
Args:
|
||||
request: FastAPI request object
|
||||
exc: Exception instance
|
||||
|
||||
Returns:
|
||||
JSONResponse: Formatted error response
|
||||
"""
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
content={"detail": "Internal server error", "error_code": "INTERNAL_ERROR"},
|
||||
)
|
||||
|
||||
|
||||
def setup_exception_handlers(app: FastAPI) -> None:
|
||||
"""
|
||||
Configure custom exception handlers for the application.
|
||||
|
||||
Args:
|
||||
app: FastAPI application instance
|
||||
"""
|
||||
from ApiLayers.ErrorHandlers.ErrorHandlers.api_exc_handler import HTTPExceptionApiHandler
|
||||
|
||||
custom_exception_handler = HTTPExceptionApiHandler(response_model=JSONResponse)
|
||||
app.add_exception_handler(
|
||||
HTTPExceptionApi, custom_exception_handler.handle_exception
|
||||
)
|
||||
app.add_exception_handler(Exception, generic_exception_handler)
|
||||
|
||||
|
||||
def setup_middleware(app: FastAPI) -> None:
|
||||
"""
|
||||
Configure all middleware for the application.
|
||||
|
||||
Args:
|
||||
app: FastAPI application instance
|
||||
"""
|
||||
setup_cors_middleware(app)
|
||||
app.add_middleware(RequestTimingMiddleware)
|
||||
app.add_middleware(LoggerTimingMiddleware)
|
||||
setup_exception_handlers(app)
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
|
||||
class DefaultApiConfig:
|
||||
app: str
|
||||
host: str
|
||||
port: int
|
||||
log_level: str
|
||||
reload: bool
|
||||
|
||||
@classmethod
|
||||
def as_dict(cls):
|
||||
return {
|
||||
"app": cls.app,
|
||||
"host": cls.host,
|
||||
"port": int(cls.port),
|
||||
"log_level": cls.log_level,
|
||||
"reload": bool(cls.reload),
|
||||
}
|
||||
|
||||
|
||||
class ApiStatic:
|
||||
PLACEHOLDER = "https://s.tmimgcdn.com/scr/800x500/276800/building-home-nature-logo-vector-template-3_276851-original.jpg"
|
||||
FORGOT_LINK = "https://www.evyos.com.tr/password/create?tokenUrl="
|
||||
BLACKLIST_LINK = "https://www.evyos.com.tr/support/unknown-login-notice/"
|
||||
APP_DIR = "/home/berkay/git-evyos/api-managment-backend/"
|
||||
|
||||
@classmethod
|
||||
def forgot_link(cls, forgot_key):
|
||||
return cls.FORGOT_LINK + forgot_key
|
||||
|
||||
@classmethod
|
||||
def blacklist_login(cls, record_id):
|
||||
return cls.BLACKLIST_LINK + record_id
|
||||
|
||||
|
||||
class ApiConfig(DefaultApiConfig):
|
||||
# Api configuration
|
||||
APP_NAME = "evyos-validation-api-gateway"
|
||||
TITLE = "WAG API Validation Api Gateway"
|
||||
DESCRIPTION = "This api is serves as web validation api gateway only to evyos web services."
|
||||
APP_URL = "https://www.validation.eys.gen.tr"
|
||||
# App configuration
|
||||
app = "app:app"
|
||||
host = "0.0.0.0"
|
||||
port = 41577
|
||||
log_level = "info"
|
||||
reload = True
|
||||
|
||||
|
||||
class MainConfig:
|
||||
# Main configuration
|
||||
DATETIME_FORMAT = "YYYY-MM-DD HH:mm:ss Z"
|
||||
DATETIME_FORMAT_JS = "YYYY-MM-DD HH:mm:ss +0"
|
||||
|
||||
# Timezone Configuration
|
||||
DEFAULT_TIMEZONE = "GMT+3" # Default timezone for the application
|
||||
SYSTEM_TIMEZONE = "GMT+0" # System timezone (used for internal operations)
|
||||
SUPPORTED_TIMEZONES = ["GMT+0", "GMT+3"] # List of supported timezones
|
||||
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
"""
|
||||
FastAPI Application Factory Module
|
||||
|
||||
This module provides functionality to create and configure a FastAPI application with:
|
||||
- Custom OpenAPI schema configuration
|
||||
- Security scheme configuration for Bearer authentication
|
||||
- Automatic router registration
|
||||
- Response class configuration
|
||||
- Security requirements for protected endpoints
|
||||
"""
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.responses import JSONResponse, RedirectResponse
|
||||
|
||||
from create_routes import get_all_routers
|
||||
from config import ApiConfig
|
||||
|
||||
|
||||
def create_app() -> FastAPI:
|
||||
"""
|
||||
Create and configure a FastAPI application with dynamic route creation.
|
||||
|
||||
Returns:
|
||||
FastAPI: Configured FastAPI application instance
|
||||
"""
|
||||
|
||||
from open_api_creator import create_openapi_schema
|
||||
|
||||
app = FastAPI(
|
||||
title=ApiConfig.TITLE,
|
||||
description=ApiConfig.DESCRIPTION,
|
||||
default_response_class=JSONResponse,
|
||||
) # Initialize FastAPI app
|
||||
|
||||
@app.get("/", include_in_schema=False, summary=str(ApiConfig.DESCRIPTION))
|
||||
def home() -> RedirectResponse:
|
||||
"""Redirect root path to API documentation."""
|
||||
return RedirectResponse(url="/docs")
|
||||
|
||||
# Get all routers and protected routes using the dynamic route creation
|
||||
prepare_routing = get_all_routers()
|
||||
|
||||
# Include all routers
|
||||
for router in prepare_routing.routers:
|
||||
app.include_router(router)
|
||||
|
||||
app.openapi = lambda app=app: create_openapi_schema(app)
|
||||
return app
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
"""
|
||||
Route configuration and factory module.
|
||||
Handles dynamic route creation based on configurations.
|
||||
"""
|
||||
|
||||
from fastapi import Request
|
||||
from Events.Engine.set_defaults.setClusters import PrepareRouting
|
||||
|
||||
|
||||
async def health_check(request: Request):
|
||||
"""Default health check endpoint."""
|
||||
return {"status": "healthy", "message": "Service is running"}
|
||||
|
||||
|
||||
async def ping_test(request: Request, service_name: str = "base-router"):
|
||||
"""Default ping test endpoint."""
|
||||
return {"ping": "pong", "service": service_name}
|
||||
|
||||
|
||||
def get_all_routers() -> PrepareRouting:
|
||||
"""
|
||||
Get all routers and protected routes from route configurations.
|
||||
|
||||
Returns:
|
||||
tuple: (routers, protected_routes)
|
||||
"""
|
||||
from Events.Engine.set_defaults.run import get_cluster_controller_group
|
||||
|
||||
cluster_list = get_cluster_controller_group()
|
||||
prepare_routing = PrepareRouting(cluster_controller_group=cluster_list)
|
||||
return prepare_routing
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
import Events.AllEvents.validations as validations_events
|
||||
|
||||
events_list = (validations_events,)
|
||||
|
|
@ -0,0 +1,249 @@
|
|||
"""
|
||||
OpenAPI Schema Creator Module
|
||||
|
||||
This module provides functionality to create and customize OpenAPI documentation:
|
||||
- Custom security schemes (Bearer Auth, API Key)
|
||||
- Response schemas and examples
|
||||
- Tag management and descriptions
|
||||
- Error responses and validation
|
||||
- Custom documentation extensions
|
||||
"""
|
||||
|
||||
from typing import Any, Dict
|
||||
from fastapi import FastAPI
|
||||
from fastapi.routing import APIRoute
|
||||
from fastapi.openapi.utils import get_openapi
|
||||
|
||||
from create_routes import get_all_routers
|
||||
from config import ApiConfig
|
||||
|
||||
|
||||
class OpenAPISchemaCreator:
|
||||
"""
|
||||
OpenAPI schema creator and customizer for FastAPI applications.
|
||||
"""
|
||||
|
||||
def __init__(self, app: FastAPI):
|
||||
"""
|
||||
Initialize the OpenAPI schema creator.
|
||||
|
||||
Args:
|
||||
app: FastAPI application instance
|
||||
"""
|
||||
self.app = app
|
||||
self.cluster = get_all_routers()
|
||||
self.safe_endpoint_list = self.cluster.safe_endpoints if hasattr(self.cluster, 'safe_endpoints') else []
|
||||
|
||||
def _create_security_schemes(self) -> Dict[str, Any]:
|
||||
"""
|
||||
Create security scheme definitions.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: Security scheme configurations
|
||||
"""
|
||||
from ApiLayers.AllConfigs.Token.config import Auth
|
||||
return {
|
||||
"BearerAuth": {
|
||||
"type": "apiKey",
|
||||
"in": "header",
|
||||
"name": Auth.ACCESS_TOKEN_TAG,
|
||||
"description": "Enter: **'Bearer <JWT>'**, where JWT is the access token",
|
||||
}
|
||||
}
|
||||
|
||||
def _create_common_responses(self) -> Dict[str, Any]:
|
||||
"""
|
||||
Create common response schemas.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: Common response configurations
|
||||
"""
|
||||
return {
|
||||
"401": {
|
||||
"description": "Unauthorized - Invalid or missing credentials",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/HTTPValidationError"}
|
||||
}
|
||||
},
|
||||
},
|
||||
"403": {
|
||||
"description": "Forbidden - Insufficient permissions",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/HTTPValidationError"}
|
||||
}
|
||||
},
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {"$ref": "#/components/schemas/HTTPValidationError"}
|
||||
}
|
||||
},
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {"type": "string"},
|
||||
"error_code": {"type": "string"},
|
||||
},
|
||||
},
|
||||
"example": {
|
||||
"detail": "Internal server error occurred",
|
||||
"error_code": "INTERNAL_ERROR",
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
def _process_request_body(
|
||||
self, path: str, method: str, schema: Dict[str, Any]
|
||||
) -> None:
|
||||
"""
|
||||
Process request body to include examples from model config.
|
||||
|
||||
Args:
|
||||
path: Route path
|
||||
method: HTTP method
|
||||
schema: OpenAPI schema to modify
|
||||
"""
|
||||
try:
|
||||
route_schema = schema["paths"][path][method]
|
||||
if "requestBody" in route_schema:
|
||||
request_body = route_schema["requestBody"]
|
||||
if "content" in request_body:
|
||||
content = request_body["content"]
|
||||
if "application/json" in content:
|
||||
json_content = content["application/json"]
|
||||
if (
|
||||
"schema" in json_content
|
||||
and "$ref" in json_content["schema"]
|
||||
):
|
||||
ref = json_content["schema"]["$ref"]
|
||||
model_name = ref.split("/")[-1]
|
||||
if model_name in schema["components"]["schemas"]:
|
||||
model_schema = schema["components"]["schemas"][
|
||||
model_name
|
||||
]
|
||||
if "example" in model_schema:
|
||||
json_content["example"] = model_schema["example"]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def _process_response_examples(
|
||||
self, path: str, method: str, schema: Dict[str, Any]
|
||||
) -> None:
|
||||
"""
|
||||
Process response body to include examples from model config.
|
||||
|
||||
Args:
|
||||
path: Route path
|
||||
method: HTTP method
|
||||
schema: OpenAPI schema to modify
|
||||
"""
|
||||
try:
|
||||
route_schema = schema["paths"][path][method]
|
||||
if "responses" in route_schema:
|
||||
responses = route_schema["responses"]
|
||||
if "200" in responses:
|
||||
response = responses["200"]
|
||||
if "content" in response:
|
||||
content = response["content"]
|
||||
if "application/json" in content:
|
||||
json_content = content["application/json"]
|
||||
if (
|
||||
"schema" in json_content
|
||||
and "$ref" in json_content["schema"]
|
||||
):
|
||||
ref = json_content["schema"]["$ref"]
|
||||
model_name = ref.split("/")[-1]
|
||||
if model_name in schema["components"]["schemas"]:
|
||||
model_schema = schema["components"]["schemas"][
|
||||
model_name
|
||||
]
|
||||
if "example" in model_schema:
|
||||
json_content["example"] = model_schema[
|
||||
"example"
|
||||
]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def configure_route_security(
|
||||
self, path: str, method: str, schema: Dict[str, Any]
|
||||
) -> None:
|
||||
"""
|
||||
Configure security requirements for a specific route.
|
||||
|
||||
Args:
|
||||
path: Route path
|
||||
method: HTTP method
|
||||
schema: OpenAPI schema to modify
|
||||
"""
|
||||
if not schema.get("paths", {}).get(path, {}).get(method):
|
||||
return
|
||||
|
||||
# Check if endpoint is in safe list
|
||||
endpoint_path = f"{path}:{method}"
|
||||
if endpoint_path not in [f"{e.URL}:{e.METHOD.lower()}" for e in self.safe_endpoint_list]:
|
||||
if "security" not in schema["paths"][path][method]:
|
||||
schema["paths"][path][method]["security"] = []
|
||||
schema["paths"][path][method]["security"].append(
|
||||
{"BearerAuth": []}
|
||||
)
|
||||
|
||||
def create_schema(self) -> Dict[str, Any]:
|
||||
"""
|
||||
Create the complete OpenAPI schema.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: Complete OpenAPI schema
|
||||
"""
|
||||
openapi_schema = get_openapi(
|
||||
title=ApiConfig.TITLE,
|
||||
description=ApiConfig.DESCRIPTION,
|
||||
version="1.1.1",
|
||||
routes=self.app.routes,
|
||||
)
|
||||
|
||||
# Add security schemes
|
||||
if "components" not in openapi_schema:
|
||||
openapi_schema["components"] = {}
|
||||
|
||||
openapi_schema["components"]["securitySchemes"] = self._create_security_schemes()
|
||||
|
||||
# Configure route security and responses
|
||||
for route in self.app.routes:
|
||||
if isinstance(route, APIRoute) and route.include_in_schema:
|
||||
path = str(route.path)
|
||||
methods = [method.lower() for method in route.methods]
|
||||
for method in methods:
|
||||
self.configure_route_security(path, method, openapi_schema)
|
||||
|
||||
# Add custom documentation extensions
|
||||
openapi_schema["x-documentation"] = {
|
||||
"postman_collection": "/docs/postman",
|
||||
"swagger_ui": "/docs",
|
||||
"redoc": "/redoc",
|
||||
}
|
||||
return openapi_schema
|
||||
|
||||
|
||||
def create_openapi_schema(app: FastAPI) -> Dict[str, Any]:
|
||||
"""
|
||||
Create OpenAPI schema for a FastAPI application.
|
||||
|
||||
Args:
|
||||
app: FastAPI application instance
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: Complete OpenAPI schema
|
||||
"""
|
||||
creator = OpenAPISchemaCreator(app)
|
||||
return creator.create_schema()
|
||||
|
|
@ -2,8 +2,8 @@
|
|||
Authentication package initialization.
|
||||
"""
|
||||
|
||||
from .auth import AUTH_CONFIG
|
||||
from .auth.cluster import AuthCluster
|
||||
|
||||
__all__ = [
|
||||
"AUTH_CONFIG",
|
||||
"AuthCluster",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
from uuid import UUID
|
||||
from Events.Engine.abstract_class import Event
|
||||
|
||||
from .models import (
|
||||
|
|
@ -14,8 +13,6 @@ from .models import (
|
|||
from .function_handlers import (
|
||||
authentication_login_with_domain_and_creds,
|
||||
authentication_select_company_or_occupant_type,
|
||||
handle_employee_selection,
|
||||
handle_occupant_selection,
|
||||
authentication_check_token_is_valid,
|
||||
authentication_refresh_user_info,
|
||||
authentication_change_password,
|
||||
|
|
@ -31,124 +28,126 @@ from .function_handlers import (
|
|||
|
||||
# Auth Login
|
||||
authentication_login_super_user_event = Event(
|
||||
key=UUID("a5d2d0d1-3e9b-4b0f-8c7d-6d4a4b4c4d4e"),
|
||||
name="authentication_login_super_user_event",
|
||||
key="a5d2d0d1-3e9b-4b0f-8c7d-6d4a4b4c4d4e",
|
||||
request_validator=LoginSuperUserRequestModel,
|
||||
response_validator=LoginSuperUserResponseModel,
|
||||
# response_validator=LoginSuperUserResponseModel,
|
||||
description="Login super user",
|
||||
)
|
||||
authentication_login_super_user_event.endpoint_callable = authentication_login_with_domain_and_creds
|
||||
authentication_login_super_user_event.endpoint_callable = (
|
||||
authentication_login_with_domain_and_creds
|
||||
)
|
||||
|
||||
# Auth Select Company or Occupant Type
|
||||
authentication_select_company_or_occupant_type_super_user_event = Event(
|
||||
key=UUID("a5d2d0d1-3e9b-4b0f-8c7d-6d4a4b4c4d4e"),
|
||||
name="authentication_select_company_or_occupant_type_super_user_event",
|
||||
key="a5d2d0d1-3e9b-4b0f-8c7d-6d4a4b4c4d4e",
|
||||
request_validator=SelectCompanyOrOccupantTypeSuperUserRequestModel,
|
||||
response_validator=SelectCompanyOrOccupantTypeSuperUserResponseModel,
|
||||
# response_validator=SelectCompanyOrOccupantTypeSuperUserResponseModel,
|
||||
description="Select company or occupant type super user",
|
||||
)
|
||||
authentication_select_company_or_occupant_type_super_user_event.endpoint_callable = authentication_select_company_or_occupant_type
|
||||
|
||||
authentication_employee_selection_super_user_event = Event(
|
||||
key=UUID("a5d2d0d1-3e9b-4b0f-8c7d-6d4a4b4c4d4e"),
|
||||
request_validator=EmployeeSelectionSuperUserRequestModel,
|
||||
response_validator=EmployeeSelectionSuperUserResponseModel,
|
||||
description="Employee selection super user",
|
||||
authentication_select_company_or_occupant_type_super_user_event.endpoint_callable = (
|
||||
authentication_select_company_or_occupant_type
|
||||
)
|
||||
authentication_employee_selection_super_user_event.endpoint_callable = handle_employee_selection
|
||||
|
||||
authentication_occupant_selection_super_user_event = Event(
|
||||
key=UUID("a5d2d0d1-3e9b-4b0f-8c7d-6d4a4b4c4d4e"),
|
||||
request_validator=OccupantSelectionSuperUserRequestModel,
|
||||
response_validator=OccupantSelectionSuperUserResponseModel,
|
||||
description="Occupant selection super user",
|
||||
)
|
||||
authentication_occupant_selection_super_user_event.endpoint_callable = handle_occupant_selection
|
||||
|
||||
# Check Token Validity
|
||||
authentication_check_token_event = Event(
|
||||
key=UUID("b6e3d1e2-4f9c-5c1g-9d8e-7e5f6f5e5d5f"),
|
||||
name="authentication_check_token_event",
|
||||
key="b6e3d1e2-4f9c-5c1g-9d8e-7e5f6f5e5d5f",
|
||||
request_validator=None, # TODO: Add request validator
|
||||
response_validator=None, # TODO: Add response validator
|
||||
# response_validator=None, # TODO: Add response validator
|
||||
description="Check if token is valid",
|
||||
)
|
||||
authentication_check_token_event.endpoint_callable = authentication_check_token_is_valid
|
||||
|
||||
# Refresh User Info
|
||||
authentication_refresh_user_info_event = Event(
|
||||
key=UUID("c7f4e2f3-5g0d-6d2h-0e9f-8f6g7g6f6e6g"),
|
||||
name="authentication_refresh_user_info_event",
|
||||
key="c7f4e2f3-5g0d-6d2h-0e9f-8f6g7g6f6e6g",
|
||||
request_validator=None, # TODO: Add request validator
|
||||
response_validator=None, # TODO: Add response validator
|
||||
# response_validator=None, # TODO: Add response validator
|
||||
description="Refresh user information",
|
||||
)
|
||||
authentication_refresh_user_info_event.endpoint_callable = authentication_refresh_user_info
|
||||
authentication_refresh_user_info_event.endpoint_callable = (
|
||||
authentication_refresh_user_info
|
||||
)
|
||||
|
||||
# Change Password
|
||||
authentication_change_password_event = Event(
|
||||
key=UUID("d8g5f3g4-6h1e-7e3i-1f0g-9g7h8h7g7f7h"),
|
||||
name="authentication_change_password_event",
|
||||
key="d8g5f3g4-6h1e-7e3i-1f0g-9g7h8h7g7f7h",
|
||||
request_validator=None, # TODO: Add request validator
|
||||
response_validator=None, # TODO: Add response validator
|
||||
# response_validator=None, # TODO: Add response validator
|
||||
description="Change user password",
|
||||
)
|
||||
authentication_change_password_event.endpoint_callable = authentication_change_password
|
||||
|
||||
# Create Password
|
||||
authentication_create_password_event = Event(
|
||||
key=UUID("e9h6g4h5-7i2f-8f4j-2g1h-0h8i9i8h8g8i"),
|
||||
name="authentication_create_password_event",
|
||||
key="e9h6g4h5-7i2f-8f4j-2g1h-0h8i9i8h8g8i",
|
||||
request_validator=None, # TODO: Add request validator
|
||||
response_validator=None, # TODO: Add response validator
|
||||
# response_validator=None, # TODO: Add response validator
|
||||
description="Create new password",
|
||||
)
|
||||
authentication_create_password_event.endpoint_callable = authentication_create_password
|
||||
|
||||
# Disconnect User
|
||||
authentication_disconnect_user_event = Event(
|
||||
key=UUID("f0i7h5i6-8j3g-9g5k-3h2i-1i9j0j9i9h9j"),
|
||||
name="authentication_disconnect_user_event",
|
||||
key="f0i7h5i6-8j3g-9g5k-3h2i-1i9j0j9i9h9j",
|
||||
request_validator=None, # TODO: Add request validator
|
||||
response_validator=None, # TODO: Add response validator
|
||||
# response_validator=None, # TODO: Add response validator
|
||||
description="Disconnect all user sessions",
|
||||
)
|
||||
authentication_disconnect_user_event.endpoint_callable = authentication_disconnect_user
|
||||
|
||||
# Logout User
|
||||
authentication_logout_user_event = Event(
|
||||
key=UUID("g1j8i6j7-9k4h-0h6l-4i3j-2j0k1k0j0i0k"),
|
||||
name="authentication_logout_user_event",
|
||||
key="g1j8i6j7-9k4h-0h6l-4i3j-2j0k1k0j0i0k",
|
||||
request_validator=None, # TODO: Add request validator
|
||||
response_validator=None, # TODO: Add response validator
|
||||
# response_validator=None, # TODO: Add response validator
|
||||
description="Logout user session",
|
||||
)
|
||||
authentication_logout_user_event.endpoint_callable = authentication_logout_user
|
||||
|
||||
# Refresh Token
|
||||
authentication_refresher_token_event = Event(
|
||||
key=UUID("h2k9j7k8-0l5i-1i7m-5j4k-3k1l2l1k1j1l"),
|
||||
name="authentication_refresher_token_event",
|
||||
key="h2k9j7k8-0l5i-1i7m-5j4k-3k1l2l1k1j1l",
|
||||
request_validator=None, # TODO: Add request validator
|
||||
response_validator=None, # TODO: Add response validator
|
||||
# response_validator=None, # TODO: Add response validator
|
||||
description="Refresh authentication token",
|
||||
)
|
||||
authentication_refresher_token_event.endpoint_callable = authentication_refresher_token
|
||||
|
||||
# Forgot Password
|
||||
authentication_forgot_password_event = Event(
|
||||
key=UUID("i3l0k8l9-1m6j-2j8n-6k5l-4l2m3m2l2k2m"),
|
||||
name="authentication_forgot_password_event",
|
||||
key="i3l0k8l9-1m6j-2j8n-6k5l-4l2m3m2l2k2m",
|
||||
request_validator=None, # TODO: Add request validator
|
||||
response_validator=None, # TODO: Add response validator
|
||||
# response_validator=None, # TODO: Add response validator
|
||||
description="Request password reset",
|
||||
)
|
||||
authentication_forgot_password_event.endpoint_callable = authentication_forgot_password
|
||||
|
||||
# Reset Password
|
||||
authentication_reset_password_event = Event(
|
||||
key=UUID("j4m1l9m0-2n7k-3k9o-7l6m-5m3n4n3m3l3n"),
|
||||
name="authentication_reset_password_event",
|
||||
key="j4m1l9m0-2n7k-3k9o-7l6m-5m3n4n3m3l3n",
|
||||
request_validator=None, # TODO: Add request validator
|
||||
response_validator=None, # TODO: Add response validator
|
||||
# response_validator=None, # TODO: Add response validator
|
||||
description="Reset user password",
|
||||
)
|
||||
authentication_reset_password_event.endpoint_callable = authentication_reset_password
|
||||
|
||||
# Download Avatar
|
||||
authentication_download_avatar_event = Event(
|
||||
key=UUID("k5n2m0n1-3o8l-4l0p-8m7n-6n4o5o4n4m4o"),
|
||||
name="authentication_download_avatar_event",
|
||||
key="k5n2m0n1-3o8l-4l0p-8m7n-6n4o5o4n4m4o",
|
||||
request_validator=None, # TODO: Add request validator
|
||||
response_validator=None, # TODO: Add response validator
|
||||
# response_validator=None, # TODO: Add response validator
|
||||
description="Download user avatar and profile info",
|
||||
)
|
||||
authentication_download_avatar_event.endpoint_callable = authentication_download_avatar
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue