redis implemntations and api setup completed

This commit is contained in:
berkay 2025-01-25 20:59:47 +03:00
parent 32022ca521
commit 3d5a43220e
138 changed files with 2888 additions and 1117 deletions

View File

@ -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>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

8
.idea/modules.xml Normal file
View File

@ -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>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@ -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>

185
.idea/workspace.xml Normal file
View File

@ -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>

View File

@ -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

View File

@ -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 &lt;JWT&gt;'**, 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

View File

@ -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

View File

@ -1,4 +1,4 @@
from AllConfigs import HostConfig from ApiLayers.AllConfigs import HostConfig
class EmailConfig: class EmailConfig:

View File

@ -1,4 +1,4 @@
from AllConfigs import HostConfig from ApiLayers.AllConfigs import HostConfig
class MongoConfig: class MongoConfig:

View File

@ -1,4 +1,4 @@
from AllConfigs import HostConfig from ApiLayers.AllConfigs import HostConfig
class WagRedis: class WagRedis:
@ -16,14 +16,18 @@ class WagRedis:
db=WagRedis.REDIS_DB, db=WagRedis.REDIS_DB,
) )
class RedisCategoryKeys: class RedisCategoryKeys:
REBUILD: str = "REBUILD"
ENDPOINT2CLASS: str = "ENDPOINT2CLASS"
LANGUAGE_MODELS: str = "LANGUAGE_MODELS" LANGUAGE_MODELS: str = "LANGUAGE_MODELS"
VALIDATION_USER: str = "VALIDATION_USER" VALIDATION_USER: str = "VALIDATION_USER"
CLUSTER_INDEX: str = "CLUSTER_INDEX"
CLUSTER_FUNCTION_CODES: str = "CLUSTER_FUNCTION_CODES" CLUSTER_FUNCTION_CODES: str = "CLUSTER_FUNCTION_CODES"
METHOD_FUNCTION_CODES: str = "METHOD_FUNCTION_CODES" METHOD_FUNCTION_CODES: str = "METHOD_FUNCTION_CODES"
MENU_FIRST_LAYER: str = "MENU_FIRST_LAYER" MENU_FIRST_LAYER: str = "MENU_FIRST_LAYER"
PAGE_MAPPER: str = "PAGE_MAPPER" PAGE_MAPPER: str = "PAGE_MAPPER"
MENU_MAPPER: str = "MENU_MAPPER" MENU_MAPPER: str = "MENU_MAPPER"
AUTH: str = "AUTH" AUTH: str = "AUTH"
OCC: str = "Occupant" OCCUPANT: str = "OCCUPANT"
EMP: str = "Employee" EMPLOYEE: str = "EMPLOYEE"

View File

@ -1,4 +1,4 @@
from AllConfigs import HostConfig from ApiLayers.AllConfigs import HostConfig
class WagDatabase: class WagDatabase:

View File

@ -1,21 +1,6 @@
import datetime 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: class Auth:
ACCESS_EMAIL_EXT = "evyos.com.tr" ACCESS_EMAIL_EXT = "evyos.com.tr"
ACCESS_TOKEN_TAG = "evyos-session-key" ACCESS_TOKEN_TAG = "evyos-session-key"
@ -40,32 +25,3 @@ class Auth:
TOKEN_EXPIRE_DAY_5 = datetime.timedelta(days=5) TOKEN_EXPIRE_DAY_5 = datetime.timedelta(days=5)
TOKEN_EXPIRE_DAY_15 = datetime.timedelta(days=15) TOKEN_EXPIRE_DAY_15 = datetime.timedelta(days=15)
TOKEN_EXPIRE_DAY_30 = datetime.timedelta(days=30) 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",
]

View File

@ -1,10 +1,13 @@
from ApiLibrary.date_time_actions.date_functions import ( from ApiLayers.ApiLibrary.date_time_actions.date_functions import (
DateTimeLocal, DateTimeLocal,
system_arrow, system_arrow,
client_arrow, client_arrow,
) )
from ApiLibrary.extensions.select import SelectActionWithEmployee, SelectAction from ApiLayers.ApiLibrary.extensions.select import (
from ApiLibrary.common.line_number import get_line_number_for_error SelectActionWithEmployee,
SelectAction,
)
from ApiLayers.ApiLibrary.common.line_number import get_line_number_for_error
__all__ = [ __all__ = [
"DateTimeLocal", "DateTimeLocal",

View File

@ -1,6 +1,7 @@
import arrow import arrow
import calendar import calendar
from AllConfigs.main import MainConfig as Config
from ApiLayers.AllConfigs.main import MainConfig as Config
class DateTimeLocal: class DateTimeLocal:

View File

@ -3,7 +3,7 @@ import uuid
import secrets import secrets
import random import random
from AllConfigs.Token.config import Auth from ApiLayers.AllConfigs.Token.config import Auth
class PasswordModule: class PasswordModule:

View File

@ -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)

View File

@ -0,0 +1,5 @@
from Services.Redis import RedisActions, AccessToken
from Services.Redis.Models.cluster import RedisList
redis_list = RedisList(redis_key="test")

View File

@ -1,11 +1,12 @@
from typing import Any, ClassVar, Dict from typing import Any, ClassVar, Dict
from sqlalchemy import or_ from sqlalchemy import or_
from ApiLibrary.common.line_number import get_line_number_for_error
from Schemas import Users from ApiLayers.ApiLibrary.common.line_number import get_line_number_for_error
from ErrorHandlers import HTTPExceptionApi from ApiLayers.ErrorHandlers import HTTPExceptionApi
from ApiValidations.Request.authentication import Login from ApiLayers.ApiValidations.Request.authentication import Login
from ApiLibrary.token.password_module import PasswordModule from ApiLayers.ApiLibrary.token.password_module import PasswordModule
from ApiServices.Token.token_handler import TokenService from ApiLayers.ApiServices.Token.token_handler import TokenService
from ApiLayers.Schemas import Users
class UserLoginModule: class UserLoginModule:

View File

@ -2,21 +2,20 @@
from typing import List, Union, TypeVar, Dict, Any, Optional, TYPE_CHECKING from typing import List, Union, TypeVar, Dict, Any, Optional, TYPE_CHECKING
from AllConfigs.Token.config import Auth from ApiLayers.AllConfigs.Token.config import Auth
from ApiLibrary.common.line_number import get_line_number_for_error from ApiLayers.ApiLibrary.common.line_number import get_line_number_for_error
from ApiLibrary.date_time_actions.date_functions import DateTimeLocal from ApiLayers.ApiLibrary.date_time_actions.date_functions import DateTimeLocal
from ApiLibrary.token.password_module import PasswordModule from ApiLayers.ApiLibrary.token.password_module import PasswordModule
from ErrorHandlers import HTTPExceptionApi from ApiLayers.ErrorHandlers import HTTPExceptionApi
from Schemas.identity.identity import UsersTokens, People from ApiLayers.Schemas.identity.identity import UsersTokens, People
from Services.Redis import RedisActions, AccessToken from ApiLayers.ApiValidations.Custom.token_objects import (
from ApiValidations.Custom.token_objects import (
EmployeeTokenObject, EmployeeTokenObject,
OccupantTokenObject, OccupantTokenObject,
UserType, UserType,
CompanyToken, CompanyToken,
OccupantToken, OccupantToken,
) )
from Schemas import ( from ApiLayers.Schemas import (
Users, Users,
BuildLivingSpace, BuildLivingSpace,
BuildParts, BuildParts,
@ -30,6 +29,8 @@ from Schemas import (
OccupantTypes, OccupantTypes,
) )
from Services.Redis.Models.response import RedisResponse from Services.Redis.Models.response import RedisResponse
from Services.Redis import RedisActions, AccessToken
if TYPE_CHECKING: if TYPE_CHECKING:
from fastapi import Request from fastapi import Request

View File

@ -1,4 +1,4 @@
from ApiServices.Token.token_handler import TokenService from ApiLayers.ApiServices.Token.token_handler import TokenService
__all__ = [ __all__ = [
"TokenService", "TokenService",

View File

@ -1,4 +1,4 @@
from ApiValidations.Request import BaseModelRegular, PydanticBaseModel from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
from typing import Optional from typing import Optional

View File

@ -1,7 +1,7 @@
from typing import Optional from typing import Optional
from ApiValidations.Request import PydanticBaseModel, ListOptions from ApiLayers.ApiValidations.Request import PydanticBaseModel, ListOptions
from ApiValidations.handler import BaseModelRegular from ApiLayers.ApiValidations.handler import BaseModelRegular
class PostCodeValidation: class PostCodeValidation:

View File

@ -1,4 +1,4 @@
from ApiValidations.Request import BaseModelRegular from ApiLayers.ApiValidations.Request import BaseModelRegular
class SingleEnumClassKeyValidation: class SingleEnumClassKeyValidation:

View File

@ -1,5 +1,5 @@
from typing import Optional from typing import Optional
from ApiValidations.Request import BaseModelRegular, PydanticBaseModel from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
class BuildAreaValidation: class BuildAreaValidation:

View File

@ -1,4 +1,4 @@
from ApiValidations.Request import BaseModelRegular from ApiLayers.ApiValidations.Request import BaseModelRegular
from typing import Optional from typing import Optional
from pydantic import BaseModel, ConfigDict, Field from pydantic import BaseModel, ConfigDict, Field

View File

@ -1,5 +1,5 @@
from typing import Optional from typing import Optional
from ApiValidations.handler import BaseModelRegular from ApiLayers.ApiValidations.handler import BaseModelRegular
class ListOptions(BaseModelRegular): class ListOptions(BaseModelRegular):

View File

@ -1,11 +1,11 @@
from typing import Optional from typing import Optional
from ApiValidations.Request import BaseModelRegular from ApiLayers.ApiValidations.Request import BaseModelRegular
# from api_validations.validations_request import ( # from api_validations.validations_request import (
# PydanticBaseModel, # PydanticBaseModel,
# PydanticBaseModelValidation, # PydanticBaseModelValidation,
# ) # )
from ApiValidations.Request import BaseModelRegular, PydanticBaseModel from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
class InsertBuildLivingSpace(BaseModelRegular): class InsertBuildLivingSpace(BaseModelRegular):

View File

@ -1,5 +1,5 @@
from typing import Optional from typing import Optional
from ApiValidations.Request import BaseModelRegular, PydanticBaseModel from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
class InsertBuildTypes(BaseModelRegular): class InsertBuildTypes(BaseModelRegular):

View File

@ -1,6 +1,6 @@
from typing import Optional from typing import Optional
from datetime import datetime from datetime import datetime
from ApiValidations.Request import BaseModelRegular, PydanticBaseModel from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
class InsertBuild(BaseModelRegular): class InsertBuild(BaseModelRegular):

View File

@ -1,5 +1,5 @@
from typing import Optional, List from typing import Optional, List
from ApiValidations.Request import BaseModelRegular, PydanticBaseModel from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
class InsertCompany(BaseModelRegular): class InsertCompany(BaseModelRegular):

View File

@ -1,6 +1,6 @@
from typing import Optional from typing import Optional
from ApiValidations.Request import BaseModelRegular from ApiLayers.ApiValidations.Request import BaseModelRegular
class ListOptionsValidation: class ListOptionsValidation:

View File

@ -1,5 +1,5 @@
from typing import Optional from typing import Optional
from ApiValidations.Request import BaseModelRegular, PydanticBaseModel, ListOptions from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel, ListOptions
class DecisionBookDecisionBookInvitations(BaseModelRegular): class DecisionBookDecisionBookInvitations(BaseModelRegular):

View File

@ -1,7 +1,5 @@
from typing import Optional from typing import Optional
from ApiValidations.Request import ( from ApiLayers.ApiValidations.Request import PydanticBaseModel
PydanticBaseModel,
)
class DepartmentsPydantic(PydanticBaseModel): class DepartmentsPydantic(PydanticBaseModel):

View File

@ -1,5 +1,5 @@
from typing import Optional from typing import Optional
from ApiValidations.Request import BaseModelRegular, PydanticBaseModel from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
class BindEmployees2People(PydanticBaseModel): class BindEmployees2People(PydanticBaseModel):

View File

@ -1,5 +1,5 @@
from typing import Optional from typing import Optional
from ApiValidations.Request import BaseModelRegular from ApiLayers.ApiValidations.Request import BaseModelRegular
class RegisterEvents2EmployeeValidation: class RegisterEvents2EmployeeValidation:

View File

@ -1,4 +1,4 @@
from ApiValidations.Request import BaseModelRegular from ApiLayers.ApiValidations.Request import BaseModelRegular
class RegisterModules2OccupantValidation: class RegisterModules2OccupantValidation:

View File

@ -1,5 +1,5 @@
from typing import Optional from typing import Optional
from ApiValidations.Request import BaseModelRegular, PydanticBaseModel from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
class InsertPerson(BaseModelRegular): class InsertPerson(BaseModelRegular):

View File

@ -1,5 +1,5 @@
from typing import Optional from typing import Optional
from ApiValidations.Request import BaseModelRegular, PydanticBaseModel from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
class InsertBuildDecisionBookProjectItems(BaseModelRegular): class InsertBuildDecisionBookProjectItems(BaseModelRegular):

View File

@ -1,6 +1,6 @@
from typing import Optional, List from typing import Optional, List
from ApiValidations.Request import BaseModelRegular from ApiLayers.ApiValidations.Request import BaseModelRegular
from ApiValidations.Request import BaseModelRegular, PydanticBaseModel from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
class CheckEndpointAccess(BaseModelRegular): class CheckEndpointAccess(BaseModelRegular):

View File

@ -1,4 +1,4 @@
from ApiValidations.Request import BaseModelRegular from ApiLayers.ApiValidations.Request import BaseModelRegular
class RegisterServices2OccupantValidation: class RegisterServices2OccupantValidation:

View File

@ -1,5 +1,5 @@
from typing import Optional from typing import Optional
from ApiValidations.Request import BaseModelRegular, PydanticBaseModel from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
class InsertStaffValidation: class InsertStaffValidation:

View File

@ -1,5 +1,5 @@
from typing import Optional from typing import Optional
from ApiValidations.Request import PydanticBaseModel from ApiLayers.ApiValidations.Request import PydanticBaseModel
class InsertUsersValidation: class InsertUsersValidation:

View File

@ -3,6 +3,7 @@ from typing import Any, Optional
from fastapi import status from fastapi import status
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
class BaseEndpointResponse: class BaseEndpointResponse:
def __init__(self, code: str, lang: str): def __init__(self, code: str, lang: str):
@ -24,8 +25,8 @@ class EndpointSuccessResponse(BaseEndpointResponse):
completed=True, completed=True,
message=self.retrieve_message(), message=self.retrieve_message(),
lang=self.lang, lang=self.lang,
data=data data=data,
) ),
) )
@ -39,15 +40,14 @@ class EndpointCreatedResponse(BaseEndpointResponse):
completed=True, completed=True,
message=self.retrieve_message(), message=self.retrieve_message(),
lang=self.lang, lang=self.lang,
data=data data=data,
) ),
) )
# 3. 202 Accepted # 3. 202 Accepted
class EndpointAcceptedResponse(BaseEndpointResponse): class EndpointAcceptedResponse(BaseEndpointResponse):
def as_dict(self, data: Optional[Dict[str, Any]] = None): def as_dict(self, data: Optional[Dict[str, Any]] = None):
return JSONResponse( return JSONResponse(
status_code=status.HTTP_202_ACCEPTED, status_code=status.HTTP_202_ACCEPTED,
@ -55,8 +55,8 @@ class EndpointAcceptedResponse(BaseEndpointResponse):
completed=True, completed=True,
message=self.retrieve_message(), message=self.retrieve_message(),
lang=self.lang, lang=self.lang,
data=data data=data,
) ),
) )
@ -70,8 +70,8 @@ class EndpointBadRequestResponse(BaseEndpointResponse):
completed=False, completed=False,
message=self.retrieve_message(), message=self.retrieve_message(),
lang=self.lang, lang=self.lang,
data=data data=data,
) ),
) )
@ -82,10 +82,8 @@ class EndpointUnauthorizedResponse(BaseEndpointResponse):
return JSONResponse( return JSONResponse(
status_code=status.HTTP_401_UNAUTHORIZED, status_code=status.HTTP_401_UNAUTHORIZED,
content=dict( content=dict(
completed=False, completed=False, message=self.retrieve_message(), lang=self.lang
message=self.retrieve_message(), ),
lang=self.lang
)
) )
@ -96,10 +94,8 @@ class EndpointNotFoundResponse(BaseEndpointResponse):
return JSONResponse( return JSONResponse(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
content=dict( content=dict(
completed=False, completed=False, message=self.retrieve_message(), lang=self.lang
message=self.retrieve_message(), ),
lang=self.lang
)
) )
@ -110,10 +106,8 @@ class EndpointForbiddenResponse(BaseEndpointResponse):
return JSONResponse( return JSONResponse(
status_code=status.HTTP_403_FORBIDDEN, status_code=status.HTTP_403_FORBIDDEN,
content=dict( content=dict(
completed=False, completed=False, message=self.retrieve_message(), lang=self.lang
message=self.retrieve_message(), ),
lang=self.lang
)
) )
@ -124,12 +118,11 @@ class EndpointConflictResponse(BaseEndpointResponse):
return JSONResponse( return JSONResponse(
status_code=status.HTTP_409_CONFLICT, status_code=status.HTTP_409_CONFLICT,
content=dict( content=dict(
completed=False, completed=False, message=self.retrieve_message(), lang=self.lang
message=self.retrieve_message(), ),
lang=self.lang
)
) )
# 7. 429 Too Many Requests # 7. 429 Too Many Requests
class EndpointTooManyRequestsResponse(BaseEndpointResponse): class EndpointTooManyRequestsResponse(BaseEndpointResponse):
@ -141,10 +134,8 @@ class EndpointTooManyRequestsResponse(BaseEndpointResponse):
status_code=status.HTTP_429_TOO_MANY_REQUESTS, status_code=status.HTTP_429_TOO_MANY_REQUESTS,
headers={"Retry-After": str(self.retry_after)}, headers={"Retry-After": str(self.retry_after)},
content=dict( content=dict(
completed=False, completed=False, message=self.retrieve_message(), lang=self.lang
message=self.retrieve_message(), ),
lang=self.lang
)
) )
@ -155,10 +146,8 @@ class EndpointInternalErrorResponse(BaseEndpointResponse):
return JSONResponse( return JSONResponse(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
content=dict( content=dict(
completed=False, completed=False, message=self.retrieve_message(), lang=self.lang
message=self.retrieve_message(), ),
lang=self.lang
)
) )
@ -168,8 +157,6 @@ class EndpointErrorResponse(BaseEndpointResponse):
return JSONResponse( return JSONResponse(
status_code=status.HTTP_304_NOT_MODIFIED, status_code=status.HTTP_304_NOT_MODIFIED,
content=dict( content=dict(
completed=False, completed=False, message=self.retrieve_message(), lang=self.lang
message=self.retrieve_message(), ),
lang=self.lang
)
) )

View File

@ -1,10 +1,12 @@
from typing import Any, Dict, Union, Awaitable from typing import Any, Union, Awaitable
from fastapi import Request, WebSocket from fastapi import Request, WebSocket
from fastapi.responses import Response from fastapi.responses import Response
from LanguageModels.Errors.merge_all_error_languages import MergedErrorLanguageModels from ApiLayers.LanguageModels.Errors.merge_all_error_languages import (
from ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi MergedErrorLanguageModels,
from ErrorHandlers.bases import BaseErrorModelClass )
from ApiLayers.ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
from ApiLayers.ErrorHandlers.bases import BaseErrorModelClass
class HTTPExceptionApiHandler: class HTTPExceptionApiHandler:
@ -23,7 +25,7 @@ class HTTPExceptionApiHandler:
@staticmethod @staticmethod
def retrieve_error_message(exc: HTTPExceptionApi, error_languages) -> str: 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) return error_languages.get(str(exc.error_code).upper(), DEFAULT_ERROR)

View File

@ -1,9 +1,8 @@
from ErrorHandlers.ErrorHandlers.api_exc_handler import ( from ApiLayers.ErrorHandlers.ErrorHandlers.api_exc_handler import (
HTTPExceptionApiHandler, HTTPExceptionApiHandler,
) )
from ErrorHandlers.Exceptions.api_exc import ( from ApiLayers.ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
HTTPExceptionApi,
)
DEFAULT_ERROR = "UNKNOWN_ERROR" DEFAULT_ERROR = "UNKNOWN_ERROR"

View File

@ -1,5 +1,5 @@
from ErrorHandlers.base import BaseError from ApiLayers.ErrorHandlers.base import BaseError
from ErrorHandlers.statuses import Statuses from ApiLayers.ErrorHandlers.statuses import Statuses
class BaseErrorModelClass: class BaseErrorModelClass:

View File

@ -1,4 +1,4 @@
from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
AccountBooksLanguageModel = dict( AccountBooksLanguageModel = dict(
tr={ tr={

View File

@ -1,4 +1,4 @@
from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
BuildIbansLanguageModel = dict( BuildIbansLanguageModel = dict(
tr={ tr={

View File

@ -1,4 +1,4 @@
from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
DecisionBookBudgetBooksLanguageModel = dict( DecisionBookBudgetBooksLanguageModel = dict(
tr={ tr={

View File

@ -1,4 +1,4 @@
from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
BuildTypesLanguageModel = dict( BuildTypesLanguageModel = dict(
tr={ tr={

View File

@ -1,4 +1,4 @@
from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
BuildDecisionBookLanguageModel = dict( BuildDecisionBookLanguageModel = dict(
tr={ tr={

View File

@ -1,4 +1,4 @@
from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
RelationshipDutyCompanyLanguageModel = dict( RelationshipDutyCompanyLanguageModel = dict(
tr={ tr={

View File

@ -1,4 +1,4 @@
from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
DepartmentsLanguageModel = dict( DepartmentsLanguageModel = dict(
tr={ tr={

View File

@ -1,4 +1,4 @@
from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
StaffLanguageModel = dict( StaffLanguageModel = dict(
tr={ tr={

View File

@ -1,4 +1,4 @@
from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
EventsLanguageModel = dict( EventsLanguageModel = dict(

View File

@ -1,4 +1,4 @@
from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
UsersTokensLanguageModel = dict( UsersTokensLanguageModel = dict(
tr={ tr={

View File

@ -1,4 +1,4 @@
from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
EndpointRestrictionLanguageModel = dict( EndpointRestrictionLanguageModel = dict(
tr={ tr={

View File

@ -1,4 +1,4 @@
from LanguageModels.Errors.base_languages import BaseErrorLanguageModels from ApiLayers.LanguageModels.Errors.base_languages import BaseErrorLanguageModels
class MergedErrorLanguageModels: class MergedErrorLanguageModels:

View File

@ -5,17 +5,19 @@ This module provides authentication decorator for protecting endpoints
and a middleware for request timing measurements. and a middleware for request timing measurements.
""" """
import inspect
from time import perf_counter from time import perf_counter
from typing import Callable, Optional, Dict, Any, Tuple, Union from typing import Callable
from functools import wraps from functools import wraps
from fastapi import Request, Response from fastapi import Request, Response
from starlette.middleware.base import BaseHTTPMiddleware from starlette.middleware.base import BaseHTTPMiddleware
from ApiLibrary.common.line_number import get_line_number_for_error from ApiLayers.ApiLibrary.common.line_number import get_line_number_for_error
from ErrorHandlers.ErrorHandlers.api_exc_handler import HTTPExceptionApi from ApiLayers.ErrorHandlers.ErrorHandlers.api_exc_handler import HTTPExceptionApi
from AllConfigs.Token.config import Auth from ApiLayers.AllConfigs.Token.config import Auth
import inspect from ApiLayers.ApiServices.Token.token_handler import TokenService
class MiddlewareModule: class MiddlewareModule:
@ -39,7 +41,6 @@ class MiddlewareModule:
Raises: Raises:
HTTPExceptionApi: If token is missing, invalid, or user not found 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 # Get token and validate - will raise HTTPExceptionApi if invalid
redis_token = TokenService.get_access_token_from_request(request=request) redis_token = TokenService.get_access_token_from_request(request=request)
@ -86,14 +87,22 @@ class MiddlewareModule:
@wraps(func) @wraps(func)
async def wrapper(request: Request, *args, **kwargs): async def wrapper(request: Request, *args, **kwargs):
# Get and validate token context from request # Get and validate token context from request
# Create auth context and Attach auth context to both wrapper and original function auth_context = {
func.auth = cls.get_user_from_request(request) "is_employee": False,
wrapper.auth = func.auth "is_occupant": False,
"context": {}
}
# Set auth context on the wrapper function itself
setattr(wrapper, 'auth', auth_context)
# Call the original endpoint function # Call the original endpoint function
if inspect.iscoroutinefunction(func): if inspect.iscoroutinefunction(func):
return await func(request, *args, **kwargs) result = await func(request, *args, **kwargs)
return func(request, *args, **kwargs) else:
result = func(request, *args, **kwargs)
return result
return wrapper return wrapper

View File

@ -9,13 +9,12 @@ from typing import Callable, Dict, Any, Optional, Union
from fastapi import Request from fastapi import Request
from pydantic import BaseModel from pydantic import BaseModel
from ApiLibrary.common.line_number import get_line_number_for_error from ApiLayers.ApiLibrary.common.line_number import get_line_number_for_error
from ApiServices.Token.token_handler import TokenService from ApiLayers.ApiServices.Token.token_handler import TokenService
from ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi from ApiLayers.ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
from Schemas.rules.rules import EndpointRestriction from ApiLayers.Schemas import Events, EndpointRestriction
from .auth_middleware import MiddlewareModule from .auth_middleware import MiddlewareModule
from Schemas import Events
class EventFunctions: class EventFunctions:
@ -24,88 +23,7 @@ class EventFunctions:
self.endpoint = endpoint self.endpoint = endpoint
self.request = request 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]]: def retrieve_function_dict(self) -> Optional[Dict[str, Any]]:
""" """
@ -201,9 +119,91 @@ class TokenEventMiddleware:
""" """
@staticmethod @staticmethod
def event_required( def match_endpoint_with_accessible_event(request_from_scope, endpoint_from_scope) -> Optional[Dict[str, Any]]:
func: Callable[..., Dict[str, Any]] """
) -> Callable[..., 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. Decorator for endpoints with token and event requirements.
This decorator: This decorator:
@ -216,31 +216,36 @@ class TokenEventMiddleware:
Returns: Returns:
Callable: The wrapped function with both auth and event handling Callable: The wrapped function with both auth and event handling
""" """
# # First apply authentication # First apply authentication
# authenticated_func = MiddlewareModule.auth_required(func) authenticated_func = MiddlewareModule.auth_required(func)
authenticated_func = func
@wraps(authenticated_func) @wraps(authenticated_func)
async def wrapper(request: Request, *args, **kwargs) -> Dict[str, Any]: async def wrapper(request: Request, *args, **kwargs) -> Dict[str, Any]:
# Get the endpoint URL for matching with events
endpoint_url = str(request.url.path)
# Get function code from the function's metadata # Set func_code first
endpoint_url = getattr(authenticated_func, "url_of_endpoint", {}) func_code = "8aytr-"
if not endpoint_url: setattr(wrapper, 'func_code', func_code)
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 # Get auth context from the authenticated function's wrapper
func.func_code = EventFunctions( auth_context = getattr(authenticated_func, 'auth', None)
endpoint_url, request print('auth_context', auth_context)
).match_endpoint_with_accesiable_event() if auth_context is not None:
# Call the authenticated function setattr(wrapper, 'auth', auth_context)
# Execute the authenticated function and get its result
if inspect.iscoroutinefunction(authenticated_func): if inspect.iscoroutinefunction(authenticated_func):
return await authenticated_func(request, *args, **kwargs) result = await authenticated_func(request, *args, **kwargs)
return 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 return wrapper
@ -261,8 +266,8 @@ class TokenEventMiddleware:
Callable: The wrapped function with both auth and event handling Callable: The wrapped function with both auth and event handling
""" """
# First apply authentication # First apply authentication
authenticated_func = MiddlewareModule.auth_required(func) # authenticated_func = MiddlewareModule.auth_required(func)
authenticated_func = func
@wraps(authenticated_func) @wraps(authenticated_func)
async def wrapper( async def wrapper(
request: Request, *args: Any, **kwargs: Any request: Request, *args: Any, **kwargs: Any
@ -278,9 +283,9 @@ class TokenEventMiddleware:
loc=get_line_number_for_error(), loc=get_line_number_for_error(),
sys_msg="Endpoint not found", sys_msg="Endpoint not found",
) )
wrapper.validation_code = EventFunctions( func.func_code = cls.match_endpoint_with_accessible_event(
endpoint_asked, request endpoint_url, request
).retrieve_function_dict() )
if inspect.iscoroutinefunction(authenticated_func): if inspect.iscoroutinefunction(authenticated_func):
result = await authenticated_func(request, *args, **kwargs) result = await authenticated_func(request, *args, **kwargs)
else: else:
@ -289,9 +294,14 @@ class TokenEventMiddleware:
wrapper.auth = function_auth wrapper.auth = function_auth
func.auth = function_auth func.auth = function_auth
authenticated_func.auth = function_auth authenticated_func.auth = function_auth
# If result is a coroutine, await it if inspect.iscoroutinefunction(authenticated_func):
if inspect.iscoroutine(result): result = await authenticated_func(request, *args, **kwargs)
result = await result 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 result
return wrapper return wrapper

View File

@ -11,7 +11,7 @@ from sqlalchemy import (
) )
from Services.PostgresDb import CrudCollection from Services.PostgresDb import CrudCollection
from LanguageModels.Database.account.account import ( from ApiLayers.LanguageModels.Database.account.account import (
AccountBooksLanguageModel, AccountBooksLanguageModel,
AccountCodesLanguageModel, AccountCodesLanguageModel,
AccountRecordsLanguageModel, AccountRecordsLanguageModel,

View File

@ -15,17 +15,17 @@ from sqlalchemy import (
or_, or_,
) )
from ApiLibrary import system_arrow, SelectActionWithEmployee from ApiLayers.ApiLibrary import system_arrow, SelectActionWithEmployee
from Services.PostgresDb import CrudCollection from Services.PostgresDb import CrudCollection
from ApiValidations.Request import ( from ApiLayers.ApiValidations.Request import (
InsertBuild, InsertBuild,
InsertBuildParts, InsertBuildParts,
InsertBuildLivingSpace, InsertBuildLivingSpace,
UpdateBuild, UpdateBuild,
) )
from ApiValidations.Custom.token_objects import EmployeeTokenObject, OccupantTokenObject from ApiLayers.ApiValidations.Custom.token_objects import EmployeeTokenObject, OccupantTokenObject
from LanguageModels.Database.building.build import ( from ApiLayers.LanguageModels.Database.building.build import (
BuildTypesLanguageModel, BuildTypesLanguageModel,
Part2EmployeeLanguageModel, Part2EmployeeLanguageModel,
BuildPartsLanguageModel, BuildPartsLanguageModel,

View File

@ -4,7 +4,7 @@ from decimal import Decimal
from typing import List from typing import List
from fastapi import HTTPException, status 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 ( from sqlalchemy import (
String, String,
@ -19,14 +19,14 @@ from sqlalchemy import (
) )
from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.orm import Mapped, mapped_column, relationship
from ApiValidations.Request import ( from ApiLayers.ApiValidations.Request import (
InsertDecisionBook, InsertDecisionBook,
InsertBuildDecisionBookItems, InsertBuildDecisionBookItems,
InsertBuildDecisionBookItemDebits, InsertBuildDecisionBookItemDebits,
InsertBuildDecisionBookProjects, InsertBuildDecisionBookProjects,
) )
from Services.PostgresDb import CrudCollection from Services.PostgresDb import CrudCollection
from LanguageModels.Database.building.decision_book import ( from ApiLayers.LanguageModels.Database.building.decision_book import (
BuildDecisionBookLanguageModel, BuildDecisionBookLanguageModel,
BuildDecisionBookInvitationsLanguageModel, BuildDecisionBookInvitationsLanguageModel,
BuildDecisionBookPersonLanguageModel, BuildDecisionBookPersonLanguageModel,

View File

@ -11,14 +11,14 @@ from sqlalchemy import (
) )
from sqlalchemy.orm import mapped_column, relationship, Mapped from sqlalchemy.orm import mapped_column, relationship, Mapped
from ApiLibrary.extensions.select import SelectAction from ApiLayers.ApiLibrary.extensions.select import SelectAction
from ApiValidations.Custom.token_objects import EmployeeTokenObject from ApiLayers.ApiValidations.Custom.token_objects import EmployeeTokenObject
from ApiValidations.Request import ( from ApiLayers.ApiValidations.Request import (
InsertCompany, InsertCompany,
UpdateCompany, UpdateCompany,
MatchCompany2Company, MatchCompany2Company,
) )
from LanguageModels.Database.company.company import ( from ApiLayers.LanguageModels.Database.company.company import (
RelationshipDutyCompanyLanguageModel, RelationshipDutyCompanyLanguageModel,
CompaniesLanguageModel, CompaniesLanguageModel,
# CompanyDutiesLanguageModel, # CompanyDutiesLanguageModel,

View File

@ -6,7 +6,7 @@ from sqlalchemy import (
) )
from sqlalchemy.orm import mapped_column, Mapped from sqlalchemy.orm import mapped_column, Mapped
from LanguageModels.Database.company.employee import ( from ApiLayers.LanguageModels.Database.company.employee import (
StaffLanguageModel, StaffLanguageModel,
EmployeesLanguageModel, EmployeesLanguageModel,
EmployeeHistoryLanguageModel, EmployeeHistoryLanguageModel,
@ -14,7 +14,7 @@ from LanguageModels.Database.company.employee import (
) )
from Services.PostgresDb import CrudCollection from Services.PostgresDb import CrudCollection
from ApiValidations.Request import InsertCompanyEmployees from ApiLayers.ApiValidations.Request import InsertCompanyEmployees
class Staff(CrudCollection): class Staff(CrudCollection):

View File

@ -1,5 +1,5 @@
from Services.PostgresDb import CrudCollection from Services.PostgresDb import CrudCollection
from LanguageModels.Database.event.event import ( from ApiLayers.LanguageModels.Database.event.event import (
EventsLanguageModel, EventsLanguageModel,
ModulesLanguageModel, ModulesLanguageModel,
ServicesLanguageModel, ServicesLanguageModel,

View File

@ -8,24 +8,23 @@ from sqlalchemy import (
ForeignKey, ForeignKey,
Index, Index,
TIMESTAMP, TIMESTAMP,
func,
Text, Text,
BigInteger, BigInteger,
Numeric, Numeric,
func,
or_, or_,
) )
from sqlalchemy.orm import mapped_column, relationship, Mapped from sqlalchemy.orm import mapped_column, relationship, Mapped
from ApiLibrary.date_time_actions.date_functions import system_arrow from ApiLayers.ApiLibrary.date_time_actions.date_functions import system_arrow
from AllConfigs.Token.config import Auth, ApiStatic from ApiLayers.ApiLibrary.extensions.select import SelectAction, SelectActionWithEmployee
from ApiLibrary.extensions.select import SelectAction, SelectActionWithEmployee
from ApiLayers.AllConfigs.Token.config import Auth
from Services.PostgresDb import CrudCollection from Services.PostgresDb import CrudCollection
from config import ApiStatic
# from databases.extensions import SelectAction, SelectActionWithEmployee from ApiLayers.ApiValidations.Request import InsertUsers, InsertPerson
# from databases.extensions.auth import UserLoginModule from ApiLayers.LanguageModels.Database.identity.identity import (
from ApiValidations.Request import InsertUsers, InsertPerson
from LanguageModels.Database.identity.identity import (
UsersTokensLanguageModel, UsersTokensLanguageModel,
UsersLanguageModel, UsersLanguageModel,
PeopleLanguageModel, PeopleLanguageModel,

View File

@ -1,7 +1,7 @@
from sqlalchemy import String from sqlalchemy import String
from sqlalchemy.orm import mapped_column, Mapped 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 from Services.PostgresDb import CrudCollection

View File

@ -19,15 +19,18 @@ RUN poetry config virtualenvs.create false \
&& rm -rf ~/.cache/pypoetry && rm -rf ~/.cache/pypoetry
# Copy application code # Copy application code
COPY DockerApiServices/AllApiNeeds /app COPY DockerApiServices/AuthServiceApi /app
# Copy application code # Copy application code
COPY ApiLayers /app/ApiLayers COPY ApiLayers /app/ApiLayers
COPY Services /app/Services
# Events # 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/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 # Set Python path to include app directory
ENV PYTHONPATH=/app \ ENV PYTHONPATH=/app \

View File

@ -10,9 +10,11 @@ This module initializes and configures the FastAPI application with:
""" """
import uvicorn import uvicorn
from prometheus_fastapi_instrumentator import Instrumentator 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 create_file import create_app
from config import ApiConfig
app = create_app() # Initialize FastAPI application app = create_app() # Initialize FastAPI application
@ -21,5 +23,5 @@ setup_middleware(app) # Configure middleware and exception handlers
if __name__ == "__main__": if __name__ == "__main__":
uvicorn_config = get_uvicorn_config() # Run the application with Uvicorn # Run the application with Uvicorn
uvicorn.Server(uvicorn.Config(**uvicorn_config)).run() uvicorn.Server(uvicorn.Config(**ApiConfig.as_dict())).run()

View File

@ -7,13 +7,12 @@ This module contains all the handler functions for configuring and setting up th
- Uvicorn server configuration - Uvicorn server configuration
""" """
from typing import Dict, Any from fastapi import FastAPI, Request, status
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from fastapi import FastAPI, Request, HTTPException, status
from fastapi.responses import JSONResponse 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: def setup_cors_middleware(app: FastAPI) -> None:
@ -56,7 +55,7 @@ def setup_exception_handlers(app: FastAPI) -> None:
Args: Args:
app: FastAPI application instance 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) custom_exception_handler = HTTPExceptionApiHandler(response_model=JSONResponse)
app.add_exception_handler( app.add_exception_handler(
@ -76,19 +75,3 @@ def setup_middleware(app: FastAPI) -> None:
app.add_middleware(RequestTimingMiddleware) app.add_middleware(RequestTimingMiddleware)
app.add_middleware(LoggerTimingMiddleware) app.add_middleware(LoggerTimingMiddleware)
setup_exception_handlers(app) 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,
}

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,3 @@
import Events.AllEvents.authentication as auths_events
events_list = (auths_events,)

View File

@ -9,14 +9,13 @@ This module provides functionality to create and customize OpenAPI documentation
- Custom documentation extensions - Custom documentation extensions
""" """
from typing import Any, Dict, List, Optional, Set from typing import Any, Dict
from fastapi import FastAPI, APIRouter from fastapi import FastAPI
from fastapi.routing import APIRoute from fastapi.routing import APIRoute
from fastapi.openapi.utils import get_openapi 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 create_routes import get_all_routers
from config import ApiConfig
class OpenAPISchemaCreator: class OpenAPISchemaCreator:
@ -32,28 +31,8 @@ class OpenAPISchemaCreator:
app: FastAPI application instance app: FastAPI application instance
""" """
self.app = app self.app = app
_, self.protected_routes = get_all_routers() self.cluster = get_all_routers()
# self.tags_metadata = self._create_tags_metadata() self.safe_endpoint_list = self.cluster.safe_endpoints if hasattr(self.cluster, 'safe_endpoints') else []
@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
]
def _create_security_schemes(self) -> Dict[str, Any]: def _create_security_schemes(self) -> Dict[str, Any]:
""" """
@ -62,8 +41,9 @@ class OpenAPISchemaCreator:
Returns: Returns:
Dict[str, Any]: Security scheme configurations Dict[str, Any]: Security scheme configurations
""" """
from ApiLayers.AllConfigs.Token.config import Auth
return { return {
"Bearer Auth": { "BearerAuth": {
"type": "apiKey", "type": "apiKey",
"in": "header", "in": "header",
"name": Auth.ACCESS_TOKEN_TAG, "name": Auth.ACCESS_TOKEN_TAG,
@ -206,19 +186,17 @@ class OpenAPISchemaCreator:
method: HTTP method method: HTTP method
schema: OpenAPI schema to modify schema: OpenAPI schema to modify
""" """
# Check if route is protected based on dynamic routing info if not schema.get("paths", {}).get(path, {}).get(method):
if path in self.protected_routes and method in self.protected_routes[path]: return
schema["paths"][path][method]["security"] = [
{"Bearer Auth": []},
]
schema["paths"][path][method]["responses"].update(
self._create_common_responses()
)
# Process request body examples # Check if endpoint is in safe list
self._process_request_body(path, method, schema) endpoint_path = f"{path}:{method}"
# Process response examples if endpoint_path not in [f"{e.URL}:{e.METHOD.lower()}" for e in self.safe_endpoint_list]:
self._process_response_examples(path, method, schema) 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]: def create_schema(self) -> Dict[str, Any]:
""" """
@ -228,8 +206,8 @@ class OpenAPISchemaCreator:
Dict[str, Any]: Complete OpenAPI schema Dict[str, Any]: Complete OpenAPI schema
""" """
openapi_schema = get_openapi( openapi_schema = get_openapi(
title=Config.TITLE, title=ApiConfig.TITLE,
description=Config.DESCRIPTION, description=ApiConfig.DESCRIPTION,
version="1.1.1", version="1.1.1",
routes=self.app.routes, routes=self.app.routes,
) )
@ -238,9 +216,8 @@ class OpenAPISchemaCreator:
if "components" not in openapi_schema: if "components" not in openapi_schema:
openapi_schema["components"] = {} openapi_schema["components"] = {}
openapi_schema["components"][ openapi_schema["components"]["securitySchemes"] = self._create_security_schemes()
"securitySchemes"
] = self._create_security_schemes()
# Configure route security and responses # Configure route security and responses
for route in self.app.routes: for route in self.app.routes:
if isinstance(route, APIRoute) and route.include_in_schema: if isinstance(route, APIRoute) and route.include_in_schema:
@ -249,13 +226,12 @@ class OpenAPISchemaCreator:
for method in methods: for method in methods:
self.configure_route_security(path, method, openapi_schema) self.configure_route_security(path, method, openapi_schema)
# # Add custom documentation extensions # Add custom documentation extensions
openapi_schema["x-documentation"] = { openapi_schema["x-documentation"] = {
"postman_collection": "/docs/postman", "postman_collection": "/docs/postman",
"swagger_ui": "/docs", "swagger_ui": "/docs",
"redoc": "/redoc", "redoc": "/redoc",
} }
return openapi_schema return openapi_schema

View File

@ -19,22 +19,18 @@ RUN poetry config virtualenvs.create false \
&& rm -rf ~/.cache/pypoetry && rm -rf ~/.cache/pypoetry
# Copy application code # Copy application code
COPY DockerApiServices/AllApiNeeds /app COPY DockerApiServices/EventServiceApi /app
COPY ErrorHandlers /app/ErrorHandlers
COPY LanguageModels /app/LanguageModels # Copy application code
COPY ApiLibrary /app/ApiLibrary COPY ApiLayers /app/ApiLayers
COPY ApiValidations /app/ApiValidations
COPY AllConfigs /app/AllConfigs
COPY ErrorHandlers /app/ErrorHandlers
COPY Schemas /app/Schemas
COPY Services /app/Services 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 # Set Python path to include app directory
ENV PYTHONPATH=/app \ ENV PYTHONPATH=/app \

View File

@ -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()

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,3 @@
import Events.AllEvents.events as events_events
events_list = (events_events,)

View File

@ -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 &lt;JWT&gt;'**, 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()

View File

@ -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"]

View File

@ -19,23 +19,17 @@ RUN poetry config virtualenvs.create false \
&& rm -rf ~/.cache/pypoetry && rm -rf ~/.cache/pypoetry
# Copy application code # Copy application code
COPY DockerApiServices/AllApiNeeds /app COPY DockerApiServices/ValidationServiceApi /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 Events structure with consistent naming # Copy application code
COPY ApiEvents/ValidationServiceApi /app/ApiEvents COPY ApiLayers /app/ApiLayers
ADD ApiEvents/AuthServiceApi/events /app/ApiEvents/events COPY Services /app/Services
ADD ApiEvents/EventServiceApi/events /app/ApiEvents/events
COPY ApiEvents/abstract_class.py /app/ApiEvents/abstract_class.py # Events
COPY ApiEvents/base_request_model.py /app/ApiEvents/base_request_model.py # 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 # Set Python path to include app directory
ENV PYTHONPATH=/app \ ENV PYTHONPATH=/app \

View File

@ -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()

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,3 @@
import Events.AllEvents.validations as validations_events
events_list = (validations_events,)

View File

@ -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 &lt;JWT&gt;'**, 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()

View File

@ -2,8 +2,8 @@
Authentication package initialization. Authentication package initialization.
""" """
from .auth import AUTH_CONFIG from .auth.cluster import AuthCluster
__all__ = [ __all__ = [
"AUTH_CONFIG", "AuthCluster",
] ]

View File

@ -1,4 +1,3 @@
from uuid import UUID
from Events.Engine.abstract_class import Event from Events.Engine.abstract_class import Event
from .models import ( from .models import (
@ -14,8 +13,6 @@ from .models import (
from .function_handlers import ( from .function_handlers import (
authentication_login_with_domain_and_creds, authentication_login_with_domain_and_creds,
authentication_select_company_or_occupant_type, authentication_select_company_or_occupant_type,
handle_employee_selection,
handle_occupant_selection,
authentication_check_token_is_valid, authentication_check_token_is_valid,
authentication_refresh_user_info, authentication_refresh_user_info,
authentication_change_password, authentication_change_password,
@ -31,124 +28,126 @@ from .function_handlers import (
# Auth Login # Auth Login
authentication_login_super_user_event = Event( 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, request_validator=LoginSuperUserRequestModel,
response_validator=LoginSuperUserResponseModel, # response_validator=LoginSuperUserResponseModel,
description="Login super user", 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 # Auth Select Company or Occupant Type
authentication_select_company_or_occupant_type_super_user_event = Event( 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, request_validator=SelectCompanyOrOccupantTypeSuperUserRequestModel,
response_validator=SelectCompanyOrOccupantTypeSuperUserResponseModel, # response_validator=SelectCompanyOrOccupantTypeSuperUserResponseModel,
description="Select company or occupant type super user", 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_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_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 # Check Token Validity
authentication_check_token_event = Event( 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 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", description="Check if token is valid",
) )
authentication_check_token_event.endpoint_callable = authentication_check_token_is_valid authentication_check_token_event.endpoint_callable = authentication_check_token_is_valid
# Refresh User Info # Refresh User Info
authentication_refresh_user_info_event = Event( 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 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", 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 # Change Password
authentication_change_password_event = Event( 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 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", description="Change user password",
) )
authentication_change_password_event.endpoint_callable = authentication_change_password authentication_change_password_event.endpoint_callable = authentication_change_password
# Create Password # Create Password
authentication_create_password_event = Event( 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 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", description="Create new password",
) )
authentication_create_password_event.endpoint_callable = authentication_create_password authentication_create_password_event.endpoint_callable = authentication_create_password
# Disconnect User # Disconnect User
authentication_disconnect_user_event = Event( 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 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", description="Disconnect all user sessions",
) )
authentication_disconnect_user_event.endpoint_callable = authentication_disconnect_user authentication_disconnect_user_event.endpoint_callable = authentication_disconnect_user
# Logout User # Logout User
authentication_logout_user_event = Event( 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 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", description="Logout user session",
) )
authentication_logout_user_event.endpoint_callable = authentication_logout_user authentication_logout_user_event.endpoint_callable = authentication_logout_user
# Refresh Token # Refresh Token
authentication_refresher_token_event = Event( 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 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", description="Refresh authentication token",
) )
authentication_refresher_token_event.endpoint_callable = authentication_refresher_token authentication_refresher_token_event.endpoint_callable = authentication_refresher_token
# Forgot Password # Forgot Password
authentication_forgot_password_event = Event( 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 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", description="Request password reset",
) )
authentication_forgot_password_event.endpoint_callable = authentication_forgot_password authentication_forgot_password_event.endpoint_callable = authentication_forgot_password
# Reset Password # Reset Password
authentication_reset_password_event = Event( 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 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", description="Reset user password",
) )
authentication_reset_password_event.endpoint_callable = authentication_reset_password authentication_reset_password_event.endpoint_callable = authentication_reset_password
# Download Avatar # Download Avatar
authentication_download_avatar_event = Event( 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 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", description="Download user avatar and profile info",
) )
authentication_download_avatar_event.endpoint_callable = authentication_download_avatar 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