diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..4129666
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..0653e14
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/wag-managment-api-service-version-5.iml b/.idea/wag-managment-api-service-version-5.iml
new file mode 100644
index 0000000..5fdd65b
--- /dev/null
+++ b/.idea/wag-managment-api-service-version-5.iml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..48fba99
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,185 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1737819471396
+
+
+ 1737819471396
+
+
+
+
\ No newline at end of file
diff --git a/ApiLayers/AllApiNeeds/application/__init__.py b/ApiLayers/AllApiNeeds/application/__init__.py
deleted file mode 100644
index 8b13789..0000000
--- a/ApiLayers/AllApiNeeds/application/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/ApiLayers/AllApiNeeds/application/app.py b/ApiLayers/AllApiNeeds/application/app.py
deleted file mode 100644
index 257add1..0000000
--- a/ApiLayers/AllApiNeeds/application/app.py
+++ /dev/null
@@ -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
diff --git a/ApiLayers/AllApiNeeds/create_file.py b/ApiLayers/AllApiNeeds/create_file.py
deleted file mode 100644
index 8ce7074..0000000
--- a/ApiLayers/AllApiNeeds/create_file.py
+++ /dev/null
@@ -1,94 +0,0 @@
-"""
-FastAPI Application Factory Module
-
-This module provides functionality to create and configure a FastAPI application with:
-- Custom OpenAPI schema configuration
-- Security scheme configuration for Bearer authentication
-- Automatic router registration
-- Response class configuration
-- Security requirements for protected endpoints
-"""
-
-from typing import Any, Dict, List, Tuple
-from fastapi import FastAPI, APIRouter
-from fastapi.responses import JSONResponse, RedirectResponse
-from fastapi.openapi.utils import get_openapi
-
-from AllConfigs.Token.config import Auth
-from AllConfigs.main import MainConfig as Config
-
-from create_routes import get_all_routers
-
-
-def setup_security_schema() -> Dict[str, Any]:
- """
- Configure security schema for the OpenAPI documentation.
-
- Returns:
- Dict[str, Any]: Security schema configuration
- """
- return {
- "components": {
- "securitySchemes": {
- "Bearer Auth": {
- "type": "apiKey",
- "in": "header",
- "name": Auth.ACCESS_TOKEN_TAG,
- "description": "Enter: **'Bearer <JWT>'**, where JWT is the access token",
- }
- }
- }
- }
-
-
-def configure_route_security(
- path: str, method: str, schema: Dict[str, Any], protected_paths: List[str]
-) -> None:
- """
- Configure security requirements for a specific route.
-
- Args:
- path: Route path
- method: HTTP method
- schema: OpenAPI schema to modify
- protected_paths: List of paths that require authentication
- """
- if path in protected_paths:
- if "paths" in schema and path in schema["paths"]:
- if method.lower() in schema["paths"][path]:
- schema["paths"][path][method.lower()]["security"] = [{"Bearer": []}]
-
-
-def create_app() -> FastAPI:
- """
- Create and configure a FastAPI application with dynamic route creation.
-
- Returns:
- FastAPI: Configured FastAPI application instance
- """
-
- from open_api_creator import create_openapi_schema
-
- # Get all routers and protected routes using the dynamic route creation
-
- app = FastAPI(
- title=Config.TITLE,
- description=Config.DESCRIPTION,
- default_response_class=JSONResponse,
- ) # Initialize FastAPI app
-
- @app.get("/", include_in_schema=False, summary=str(Config.DESCRIPTION))
- async def home() -> RedirectResponse:
- """Redirect root path to API documentation."""
- return RedirectResponse(url="/docs")
-
- # Get all routers and protected routes using the dynamic route creation
- routers, protected_routes = get_all_routers()
-
- # Include all routers
- for router in routers:
- app.include_router(router)
-
- app.openapi = lambda app=app: create_openapi_schema(app)
-
- return app
diff --git a/ApiLayers/AllApiNeeds/create_routes.py b/ApiLayers/AllApiNeeds/create_routes.py
deleted file mode 100644
index b969985..0000000
--- a/ApiLayers/AllApiNeeds/create_routes.py
+++ /dev/null
@@ -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
diff --git a/ApiLayers/AllConfigs/Email/configs.py b/ApiLayers/AllConfigs/Email/configs.py
index 2cd61c9..ce92382 100644
--- a/ApiLayers/AllConfigs/Email/configs.py
+++ b/ApiLayers/AllConfigs/Email/configs.py
@@ -1,4 +1,4 @@
-from AllConfigs import HostConfig
+from ApiLayers.AllConfigs import HostConfig
class EmailConfig:
diff --git a/ApiLayers/AllConfigs/NoSqlDatabase/configs.py b/ApiLayers/AllConfigs/NoSqlDatabase/configs.py
index 8dcc208..813b12f 100644
--- a/ApiLayers/AllConfigs/NoSqlDatabase/configs.py
+++ b/ApiLayers/AllConfigs/NoSqlDatabase/configs.py
@@ -1,4 +1,4 @@
-from AllConfigs import HostConfig
+from ApiLayers.AllConfigs import HostConfig
class MongoConfig:
diff --git a/ApiLayers/AllConfigs/Redis/configs.py b/ApiLayers/AllConfigs/Redis/configs.py
index cebf5cf..1303782 100644
--- a/ApiLayers/AllConfigs/Redis/configs.py
+++ b/ApiLayers/AllConfigs/Redis/configs.py
@@ -1,4 +1,4 @@
-from AllConfigs import HostConfig
+from ApiLayers.AllConfigs import HostConfig
class WagRedis:
@@ -16,14 +16,18 @@ class WagRedis:
db=WagRedis.REDIS_DB,
)
+
class RedisCategoryKeys:
+ REBUILD: str = "REBUILD"
+ ENDPOINT2CLASS: str = "ENDPOINT2CLASS"
LANGUAGE_MODELS: str = "LANGUAGE_MODELS"
VALIDATION_USER: str = "VALIDATION_USER"
+ CLUSTER_INDEX: str = "CLUSTER_INDEX"
CLUSTER_FUNCTION_CODES: str = "CLUSTER_FUNCTION_CODES"
METHOD_FUNCTION_CODES: str = "METHOD_FUNCTION_CODES"
MENU_FIRST_LAYER: str = "MENU_FIRST_LAYER"
PAGE_MAPPER: str = "PAGE_MAPPER"
MENU_MAPPER: str = "MENU_MAPPER"
AUTH: str = "AUTH"
- OCC: str = "Occupant"
- EMP: str = "Employee"
+ OCCUPANT: str = "OCCUPANT"
+ EMPLOYEE: str = "EMPLOYEE"
\ No newline at end of file
diff --git a/ApiLayers/AllConfigs/SqlDatabase/configs.py b/ApiLayers/AllConfigs/SqlDatabase/configs.py
index f33684b..c36f662 100644
--- a/ApiLayers/AllConfigs/SqlDatabase/configs.py
+++ b/ApiLayers/AllConfigs/SqlDatabase/configs.py
@@ -1,4 +1,4 @@
-from AllConfigs import HostConfig
+from ApiLayers.AllConfigs import HostConfig
class WagDatabase:
diff --git a/ApiLayers/AllConfigs/Token/config.py b/ApiLayers/AllConfigs/Token/config.py
index e95c300..9793055 100644
--- a/ApiLayers/AllConfigs/Token/config.py
+++ b/ApiLayers/AllConfigs/Token/config.py
@@ -1,21 +1,6 @@
import datetime
-class ApiStatic:
- PLACEHOLDER = "https://s.tmimgcdn.com/scr/800x500/276800/building-home-nature-logo-vector-template-3_276851-original.jpg"
- FORGOT_LINK = "https://www.evyos.com.tr/password/create?tokenUrl="
- BLACKLIST_LINK = "https://www.evyos.com.tr/support/unknown-login-notice/"
- APP_DIR = "/home/berkay/git-evyos/api-managment-backend/"
-
- @classmethod
- def forgot_link(cls, forgot_key):
- return cls.FORGOT_LINK + forgot_key
-
- @classmethod
- def blacklist_login(cls, record_id):
- return cls.BLACKLIST_LINK + record_id
-
-
class Auth:
ACCESS_EMAIL_EXT = "evyos.com.tr"
ACCESS_TOKEN_TAG = "evyos-session-key"
@@ -40,32 +25,3 @@ class Auth:
TOKEN_EXPIRE_DAY_5 = datetime.timedelta(days=5)
TOKEN_EXPIRE_DAY_15 = datetime.timedelta(days=15)
TOKEN_EXPIRE_DAY_30 = datetime.timedelta(days=30)
-
-
-class Routers:
- NO_TOKEN_REQUIRES = [
- "/",
- "/metrics",
- "/openapi.json",
- "/docs",
- "/redoc",
- "/auth/login",
- "/favicon.ico",
- "/docs/oauth2-redirect",
- "/authentication/select",
- "/authentication/login",
- "/authentication/logout",
- "/authentication/refresher",
- "/authentication/refresh",
- "/authentication/disconnect",
- "/authentication/create_password",
- "/authentication/reset_password",
- "/authentication/forgot",
- "/authentication/valid",
- ]
- NO_EVENT_REQUIRES = [
- "/access/endpoints/available",
- "/access/endpoint/available",
- "/validations/endpoint",
- "/authentication/avatar",
- ]
diff --git a/ApiLayers/ApiLibrary/__init__.py b/ApiLayers/ApiLibrary/__init__.py
index 9da6e7d..b64093b 100644
--- a/ApiLayers/ApiLibrary/__init__.py
+++ b/ApiLayers/ApiLibrary/__init__.py
@@ -1,10 +1,13 @@
-from ApiLibrary.date_time_actions.date_functions import (
+from ApiLayers.ApiLibrary.date_time_actions.date_functions import (
DateTimeLocal,
system_arrow,
client_arrow,
)
-from ApiLibrary.extensions.select import SelectActionWithEmployee, SelectAction
-from ApiLibrary.common.line_number import get_line_number_for_error
+from ApiLayers.ApiLibrary.extensions.select import (
+ SelectActionWithEmployee,
+ SelectAction,
+)
+from ApiLayers.ApiLibrary.common.line_number import get_line_number_for_error
__all__ = [
"DateTimeLocal",
diff --git a/ApiLayers/ApiLibrary/date_time_actions/date_functions.py b/ApiLayers/ApiLibrary/date_time_actions/date_functions.py
index 533cf08..3071d23 100644
--- a/ApiLayers/ApiLibrary/date_time_actions/date_functions.py
+++ b/ApiLayers/ApiLibrary/date_time_actions/date_functions.py
@@ -1,6 +1,7 @@
import arrow
import calendar
-from AllConfigs.main import MainConfig as Config
+
+from ApiLayers.AllConfigs.main import MainConfig as Config
class DateTimeLocal:
diff --git a/ApiLayers/ApiLibrary/token/password_module.py b/ApiLayers/ApiLibrary/token/password_module.py
index d2ebbf0..8032f93 100644
--- a/ApiLayers/ApiLibrary/token/password_module.py
+++ b/ApiLayers/ApiLibrary/token/password_module.py
@@ -3,7 +3,7 @@ import uuid
import secrets
import random
-from AllConfigs.Token.config import Auth
+from ApiLayers.AllConfigs.Token.config import Auth
class PasswordModule:
diff --git a/ApiLayers/ApiServices/Cluster/create_router.py b/ApiLayers/ApiServices/Cluster/create_router.py
new file mode 100644
index 0000000..f59dd5f
--- /dev/null
+++ b/ApiLayers/ApiServices/Cluster/create_router.py
@@ -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)
diff --git a/ApiLayers/ApiServices/Cluster/handle_cluster.py b/ApiLayers/ApiServices/Cluster/handle_cluster.py
new file mode 100644
index 0000000..b7f1884
--- /dev/null
+++ b/ApiLayers/ApiServices/Cluster/handle_cluster.py
@@ -0,0 +1,5 @@
+from Services.Redis import RedisActions, AccessToken
+from Services.Redis.Models.cluster import RedisList
+
+redis_list = RedisList(redis_key="test")
+
diff --git a/ApiLayers/ApiServices/Login/user_login_handler.py b/ApiLayers/ApiServices/Login/user_login_handler.py
index ec416c7..4ca7889 100644
--- a/ApiLayers/ApiServices/Login/user_login_handler.py
+++ b/ApiLayers/ApiServices/Login/user_login_handler.py
@@ -1,11 +1,12 @@
from typing import Any, ClassVar, Dict
from sqlalchemy import or_
-from ApiLibrary.common.line_number import get_line_number_for_error
-from Schemas import Users
-from ErrorHandlers import HTTPExceptionApi
-from ApiValidations.Request.authentication import Login
-from ApiLibrary.token.password_module import PasswordModule
-from ApiServices.Token.token_handler import TokenService
+
+from ApiLayers.ApiLibrary.common.line_number import get_line_number_for_error
+from ApiLayers.ErrorHandlers import HTTPExceptionApi
+from ApiLayers.ApiValidations.Request.authentication import Login
+from ApiLayers.ApiLibrary.token.password_module import PasswordModule
+from ApiLayers.ApiServices.Token.token_handler import TokenService
+from ApiLayers.Schemas import Users
class UserLoginModule:
diff --git a/ApiLayers/ApiServices/Token/token_handler.py b/ApiLayers/ApiServices/Token/token_handler.py
index 871fa63..7f8538f 100644
--- a/ApiLayers/ApiServices/Token/token_handler.py
+++ b/ApiLayers/ApiServices/Token/token_handler.py
@@ -2,21 +2,20 @@
from typing import List, Union, TypeVar, Dict, Any, Optional, TYPE_CHECKING
-from AllConfigs.Token.config import Auth
-from ApiLibrary.common.line_number import get_line_number_for_error
-from ApiLibrary.date_time_actions.date_functions import DateTimeLocal
-from ApiLibrary.token.password_module import PasswordModule
-from ErrorHandlers import HTTPExceptionApi
-from Schemas.identity.identity import UsersTokens, People
-from Services.Redis import RedisActions, AccessToken
-from ApiValidations.Custom.token_objects import (
+from ApiLayers.AllConfigs.Token.config import Auth
+from ApiLayers.ApiLibrary.common.line_number import get_line_number_for_error
+from ApiLayers.ApiLibrary.date_time_actions.date_functions import DateTimeLocal
+from ApiLayers.ApiLibrary.token.password_module import PasswordModule
+from ApiLayers.ErrorHandlers import HTTPExceptionApi
+from ApiLayers.Schemas.identity.identity import UsersTokens, People
+from ApiLayers.ApiValidations.Custom.token_objects import (
EmployeeTokenObject,
OccupantTokenObject,
UserType,
CompanyToken,
OccupantToken,
)
-from Schemas import (
+from ApiLayers.Schemas import (
Users,
BuildLivingSpace,
BuildParts,
@@ -30,6 +29,8 @@ from Schemas import (
OccupantTypes,
)
from Services.Redis.Models.response import RedisResponse
+from Services.Redis import RedisActions, AccessToken
+
if TYPE_CHECKING:
from fastapi import Request
diff --git a/ApiLayers/ApiServices/__init__.py b/ApiLayers/ApiServices/__init__.py
index be0bc54..7dec7ae 100644
--- a/ApiLayers/ApiServices/__init__.py
+++ b/ApiLayers/ApiServices/__init__.py
@@ -1,4 +1,4 @@
-from ApiServices.Token.token_handler import TokenService
+from ApiLayers.ApiServices.Token.token_handler import TokenService
__all__ = [
"TokenService",
diff --git a/ApiLayers/ApiValidations/Request/account_records.py b/ApiLayers/ApiValidations/Request/account_records.py
index 5dca43c..cdbf515 100644
--- a/ApiLayers/ApiValidations/Request/account_records.py
+++ b/ApiLayers/ApiValidations/Request/account_records.py
@@ -1,4 +1,4 @@
-from ApiValidations.Request import BaseModelRegular, PydanticBaseModel
+from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
from typing import Optional
diff --git a/ApiLayers/ApiValidations/Request/address.py b/ApiLayers/ApiValidations/Request/address.py
index 8939943..5482b5e 100644
--- a/ApiLayers/ApiValidations/Request/address.py
+++ b/ApiLayers/ApiValidations/Request/address.py
@@ -1,7 +1,7 @@
from typing import Optional
-from ApiValidations.Request import PydanticBaseModel, ListOptions
-from ApiValidations.handler import BaseModelRegular
+from ApiLayers.ApiValidations.Request import PydanticBaseModel, ListOptions
+from ApiLayers.ApiValidations.handler import BaseModelRegular
class PostCodeValidation:
diff --git a/ApiLayers/ApiValidations/Request/application.py b/ApiLayers/ApiValidations/Request/application.py
index 3a1147b..f9e4739 100644
--- a/ApiLayers/ApiValidations/Request/application.py
+++ b/ApiLayers/ApiValidations/Request/application.py
@@ -1,4 +1,4 @@
-from ApiValidations.Request import BaseModelRegular
+from ApiLayers.ApiValidations.Request import BaseModelRegular
class SingleEnumClassKeyValidation:
diff --git a/ApiLayers/ApiValidations/Request/area.py b/ApiLayers/ApiValidations/Request/area.py
index 635adbf..1cc63aa 100644
--- a/ApiLayers/ApiValidations/Request/area.py
+++ b/ApiLayers/ApiValidations/Request/area.py
@@ -1,5 +1,5 @@
from typing import Optional
-from ApiValidations.Request import BaseModelRegular, PydanticBaseModel
+from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
class BuildAreaValidation:
diff --git a/ApiLayers/ApiValidations/Request/authentication.py b/ApiLayers/ApiValidations/Request/authentication.py
index 8f3b7ad..abbb249 100644
--- a/ApiLayers/ApiValidations/Request/authentication.py
+++ b/ApiLayers/ApiValidations/Request/authentication.py
@@ -1,4 +1,4 @@
-from ApiValidations.Request import BaseModelRegular
+from ApiLayers.ApiValidations.Request import BaseModelRegular
from typing import Optional
from pydantic import BaseModel, ConfigDict, Field
diff --git a/ApiLayers/ApiValidations/Request/base_validations.py b/ApiLayers/ApiValidations/Request/base_validations.py
index 27eb461..832193f 100644
--- a/ApiLayers/ApiValidations/Request/base_validations.py
+++ b/ApiLayers/ApiValidations/Request/base_validations.py
@@ -1,5 +1,5 @@
from typing import Optional
-from ApiValidations.handler import BaseModelRegular
+from ApiLayers.ApiValidations.handler import BaseModelRegular
class ListOptions(BaseModelRegular):
diff --git a/ApiLayers/ApiValidations/Request/build_living_space.py b/ApiLayers/ApiValidations/Request/build_living_space.py
index d39dd2a..b13e503 100644
--- a/ApiLayers/ApiValidations/Request/build_living_space.py
+++ b/ApiLayers/ApiValidations/Request/build_living_space.py
@@ -1,11 +1,11 @@
from typing import Optional
-from ApiValidations.Request import BaseModelRegular
+from ApiLayers.ApiValidations.Request import BaseModelRegular
# from api_validations.validations_request import (
# PydanticBaseModel,
# PydanticBaseModelValidation,
# )
-from ApiValidations.Request import BaseModelRegular, PydanticBaseModel
+from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
class InsertBuildLivingSpace(BaseModelRegular):
diff --git a/ApiLayers/ApiValidations/Request/build_part.py b/ApiLayers/ApiValidations/Request/build_part.py
index ae6d104..9d9d2bb 100644
--- a/ApiLayers/ApiValidations/Request/build_part.py
+++ b/ApiLayers/ApiValidations/Request/build_part.py
@@ -1,5 +1,5 @@
from typing import Optional
-from ApiValidations.Request import BaseModelRegular, PydanticBaseModel
+from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
class InsertBuildTypes(BaseModelRegular):
diff --git a/ApiLayers/ApiValidations/Request/building.py b/ApiLayers/ApiValidations/Request/building.py
index 7d81bdc..042b62e 100644
--- a/ApiLayers/ApiValidations/Request/building.py
+++ b/ApiLayers/ApiValidations/Request/building.py
@@ -1,6 +1,6 @@
from typing import Optional
from datetime import datetime
-from ApiValidations.Request import BaseModelRegular, PydanticBaseModel
+from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
class InsertBuild(BaseModelRegular):
diff --git a/ApiLayers/ApiValidations/Request/company.py b/ApiLayers/ApiValidations/Request/company.py
index 59cf061..50b394a 100644
--- a/ApiLayers/ApiValidations/Request/company.py
+++ b/ApiLayers/ApiValidations/Request/company.py
@@ -1,5 +1,5 @@
from typing import Optional, List
-from ApiValidations.Request import BaseModelRegular, PydanticBaseModel
+from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
class InsertCompany(BaseModelRegular):
diff --git a/ApiLayers/ApiValidations/Request/core_request_validations.py b/ApiLayers/ApiValidations/Request/core_request_validations.py
index 0c303a9..aa08831 100644
--- a/ApiLayers/ApiValidations/Request/core_request_validations.py
+++ b/ApiLayers/ApiValidations/Request/core_request_validations.py
@@ -1,6 +1,6 @@
from typing import Optional
-from ApiValidations.Request import BaseModelRegular
+from ApiLayers.ApiValidations.Request import BaseModelRegular
class ListOptionsValidation:
diff --git a/ApiLayers/ApiValidations/Request/decision_book.py b/ApiLayers/ApiValidations/Request/decision_book.py
index 61fc3a4..e3d14fa 100644
--- a/ApiLayers/ApiValidations/Request/decision_book.py
+++ b/ApiLayers/ApiValidations/Request/decision_book.py
@@ -1,5 +1,5 @@
from typing import Optional
-from ApiValidations.Request import BaseModelRegular, PydanticBaseModel, ListOptions
+from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel, ListOptions
class DecisionBookDecisionBookInvitations(BaseModelRegular):
diff --git a/ApiLayers/ApiValidations/Request/departments.py b/ApiLayers/ApiValidations/Request/departments.py
index 377b119..dbdaa01 100644
--- a/ApiLayers/ApiValidations/Request/departments.py
+++ b/ApiLayers/ApiValidations/Request/departments.py
@@ -1,7 +1,5 @@
from typing import Optional
-from ApiValidations.Request import (
- PydanticBaseModel,
-)
+from ApiLayers.ApiValidations.Request import PydanticBaseModel
class DepartmentsPydantic(PydanticBaseModel):
diff --git a/ApiLayers/ApiValidations/Request/employee.py b/ApiLayers/ApiValidations/Request/employee.py
index a1d5c24..9a68b46 100644
--- a/ApiLayers/ApiValidations/Request/employee.py
+++ b/ApiLayers/ApiValidations/Request/employee.py
@@ -1,5 +1,5 @@
from typing import Optional
-from ApiValidations.Request import BaseModelRegular, PydanticBaseModel
+from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
class BindEmployees2People(PydanticBaseModel):
diff --git a/ApiLayers/ApiValidations/Request/events.py b/ApiLayers/ApiValidations/Request/events.py
index 98f4db9..83a5ba6 100644
--- a/ApiLayers/ApiValidations/Request/events.py
+++ b/ApiLayers/ApiValidations/Request/events.py
@@ -1,5 +1,5 @@
from typing import Optional
-from ApiValidations.Request import BaseModelRegular
+from ApiLayers.ApiValidations.Request import BaseModelRegular
class RegisterEvents2EmployeeValidation:
diff --git a/ApiLayers/ApiValidations/Request/modules.py b/ApiLayers/ApiValidations/Request/modules.py
index e6fcc67..26658ca 100644
--- a/ApiLayers/ApiValidations/Request/modules.py
+++ b/ApiLayers/ApiValidations/Request/modules.py
@@ -1,4 +1,4 @@
-from ApiValidations.Request import BaseModelRegular
+from ApiLayers.ApiValidations.Request import BaseModelRegular
class RegisterModules2OccupantValidation:
diff --git a/ApiLayers/ApiValidations/Request/people.py b/ApiLayers/ApiValidations/Request/people.py
index 281f355..b898ab1 100644
--- a/ApiLayers/ApiValidations/Request/people.py
+++ b/ApiLayers/ApiValidations/Request/people.py
@@ -1,5 +1,5 @@
from typing import Optional
-from ApiValidations.Request import BaseModelRegular, PydanticBaseModel
+from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
class InsertPerson(BaseModelRegular):
diff --git a/ApiLayers/ApiValidations/Request/project_decision_book.py b/ApiLayers/ApiValidations/Request/project_decision_book.py
index 709852a..1bd4c2b 100644
--- a/ApiLayers/ApiValidations/Request/project_decision_book.py
+++ b/ApiLayers/ApiValidations/Request/project_decision_book.py
@@ -1,5 +1,5 @@
from typing import Optional
-from ApiValidations.Request import BaseModelRegular, PydanticBaseModel
+from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
class InsertBuildDecisionBookProjectItems(BaseModelRegular):
diff --git a/ApiLayers/ApiValidations/Request/rules.py b/ApiLayers/ApiValidations/Request/rules.py
index c9f9845..cc8ef6f 100644
--- a/ApiLayers/ApiValidations/Request/rules.py
+++ b/ApiLayers/ApiValidations/Request/rules.py
@@ -1,6 +1,6 @@
from typing import Optional, List
-from ApiValidations.Request import BaseModelRegular
-from ApiValidations.Request import BaseModelRegular, PydanticBaseModel
+from ApiLayers.ApiValidations.Request import BaseModelRegular
+from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
class CheckEndpointAccess(BaseModelRegular):
diff --git a/ApiLayers/ApiValidations/Request/services.py b/ApiLayers/ApiValidations/Request/services.py
index 54712c9..c5d71ef 100644
--- a/ApiLayers/ApiValidations/Request/services.py
+++ b/ApiLayers/ApiValidations/Request/services.py
@@ -1,4 +1,4 @@
-from ApiValidations.Request import BaseModelRegular
+from ApiLayers.ApiValidations.Request import BaseModelRegular
class RegisterServices2OccupantValidation:
diff --git a/ApiLayers/ApiValidations/Request/staff.py b/ApiLayers/ApiValidations/Request/staff.py
index 03cdadb..a98af03 100644
--- a/ApiLayers/ApiValidations/Request/staff.py
+++ b/ApiLayers/ApiValidations/Request/staff.py
@@ -1,5 +1,5 @@
from typing import Optional
-from ApiValidations.Request import BaseModelRegular, PydanticBaseModel
+from ApiLayers.ApiValidations.Request import BaseModelRegular, PydanticBaseModel
class InsertStaffValidation:
diff --git a/ApiLayers/ApiValidations/Request/user.py b/ApiLayers/ApiValidations/Request/user.py
index 7583a1b..c527684 100644
--- a/ApiLayers/ApiValidations/Request/user.py
+++ b/ApiLayers/ApiValidations/Request/user.py
@@ -1,5 +1,5 @@
from typing import Optional
-from ApiValidations.Request import PydanticBaseModel
+from ApiLayers.ApiValidations.Request import PydanticBaseModel
class InsertUsersValidation:
diff --git a/ApiLayers/ApiValidations/Response/default_response.py b/ApiLayers/ApiValidations/Response/default_response.py
index 117ff2c..ab32299 100644
--- a/ApiLayers/ApiValidations/Response/default_response.py
+++ b/ApiLayers/ApiValidations/Response/default_response.py
@@ -3,6 +3,7 @@ from typing import Any, Optional
from fastapi import status
from fastapi.responses import JSONResponse
+
class BaseEndpointResponse:
def __init__(self, code: str, lang: str):
@@ -12,7 +13,7 @@ class BaseEndpointResponse:
def retrieve_message(self):
messages = {}
return messages[self.code][self.lang]
-
+
# 1. 200 OK
class EndpointSuccessResponse(BaseEndpointResponse):
@@ -24,8 +25,8 @@ class EndpointSuccessResponse(BaseEndpointResponse):
completed=True,
message=self.retrieve_message(),
lang=self.lang,
- data=data
- )
+ data=data,
+ ),
)
@@ -39,15 +40,14 @@ class EndpointCreatedResponse(BaseEndpointResponse):
completed=True,
message=self.retrieve_message(),
lang=self.lang,
- data=data
- )
+ data=data,
+ ),
)
# 3. 202 Accepted
class EndpointAcceptedResponse(BaseEndpointResponse):
-
def as_dict(self, data: Optional[Dict[str, Any]] = None):
return JSONResponse(
status_code=status.HTTP_202_ACCEPTED,
@@ -55,8 +55,8 @@ class EndpointAcceptedResponse(BaseEndpointResponse):
completed=True,
message=self.retrieve_message(),
lang=self.lang,
- data=data
- )
+ data=data,
+ ),
)
@@ -70,8 +70,8 @@ class EndpointBadRequestResponse(BaseEndpointResponse):
completed=False,
message=self.retrieve_message(),
lang=self.lang,
- data=data
- )
+ data=data,
+ ),
)
@@ -82,10 +82,8 @@ class EndpointUnauthorizedResponse(BaseEndpointResponse):
return JSONResponse(
status_code=status.HTTP_401_UNAUTHORIZED,
content=dict(
- completed=False,
- message=self.retrieve_message(),
- lang=self.lang
- )
+ completed=False, message=self.retrieve_message(), lang=self.lang
+ ),
)
@@ -96,10 +94,8 @@ class EndpointNotFoundResponse(BaseEndpointResponse):
return JSONResponse(
status_code=status.HTTP_404_NOT_FOUND,
content=dict(
- completed=False,
- message=self.retrieve_message(),
- lang=self.lang
- )
+ completed=False, message=self.retrieve_message(), lang=self.lang
+ ),
)
@@ -110,10 +106,8 @@ class EndpointForbiddenResponse(BaseEndpointResponse):
return JSONResponse(
status_code=status.HTTP_403_FORBIDDEN,
content=dict(
- completed=False,
- message=self.retrieve_message(),
- lang=self.lang
- )
+ completed=False, message=self.retrieve_message(), lang=self.lang
+ ),
)
@@ -124,15 +118,14 @@ class EndpointConflictResponse(BaseEndpointResponse):
return JSONResponse(
status_code=status.HTTP_409_CONFLICT,
content=dict(
- completed=False,
- message=self.retrieve_message(),
- lang=self.lang
- )
+ completed=False, message=self.retrieve_message(), lang=self.lang
+ ),
)
+
# 7. 429 Too Many Requests
class EndpointTooManyRequestsResponse(BaseEndpointResponse):
-
+
def __init__(self, retry_after: int):
self.retry_after = retry_after
@@ -141,10 +134,8 @@ class EndpointTooManyRequestsResponse(BaseEndpointResponse):
status_code=status.HTTP_429_TOO_MANY_REQUESTS,
headers={"Retry-After": str(self.retry_after)},
content=dict(
- completed=False,
- message=self.retrieve_message(),
- lang=self.lang
- )
+ completed=False, message=self.retrieve_message(), lang=self.lang
+ ),
)
@@ -155,10 +146,8 @@ class EndpointInternalErrorResponse(BaseEndpointResponse):
return JSONResponse(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
content=dict(
- completed=False,
- message=self.retrieve_message(),
- lang=self.lang
- )
+ completed=False, message=self.retrieve_message(), lang=self.lang
+ ),
)
@@ -168,8 +157,6 @@ class EndpointErrorResponse(BaseEndpointResponse):
return JSONResponse(
status_code=status.HTTP_304_NOT_MODIFIED,
content=dict(
- completed=False,
- message=self.retrieve_message(),
- lang=self.lang
- )
+ completed=False, message=self.retrieve_message(), lang=self.lang
+ ),
)
diff --git a/ApiLayers/ErrorHandlers/ErrorHandlers/api_exc_handler.py b/ApiLayers/ErrorHandlers/ErrorHandlers/api_exc_handler.py
index 96d8f5f..6745534 100644
--- a/ApiLayers/ErrorHandlers/ErrorHandlers/api_exc_handler.py
+++ b/ApiLayers/ErrorHandlers/ErrorHandlers/api_exc_handler.py
@@ -1,10 +1,12 @@
-from typing import Any, Dict, Union, Awaitable
+from typing import Any, Union, Awaitable
from fastapi import Request, WebSocket
from fastapi.responses import Response
-from LanguageModels.Errors.merge_all_error_languages import MergedErrorLanguageModels
-from ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
-from ErrorHandlers.bases import BaseErrorModelClass
+from ApiLayers.LanguageModels.Errors.merge_all_error_languages import (
+ MergedErrorLanguageModels,
+)
+from ApiLayers.ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
+from ApiLayers.ErrorHandlers.bases import BaseErrorModelClass
class HTTPExceptionApiHandler:
@@ -23,7 +25,7 @@ class HTTPExceptionApiHandler:
@staticmethod
def retrieve_error_message(exc: HTTPExceptionApi, error_languages) -> str:
- from ErrorHandlers import DEFAULT_ERROR
+ from ApiLayers.ErrorHandlers import DEFAULT_ERROR
return error_languages.get(str(exc.error_code).upper(), DEFAULT_ERROR)
diff --git a/ApiLayers/ErrorHandlers/__init__.py b/ApiLayers/ErrorHandlers/__init__.py
index fae403a..c83ecf8 100644
--- a/ApiLayers/ErrorHandlers/__init__.py
+++ b/ApiLayers/ErrorHandlers/__init__.py
@@ -1,9 +1,8 @@
-from ErrorHandlers.ErrorHandlers.api_exc_handler import (
+from ApiLayers.ErrorHandlers.ErrorHandlers.api_exc_handler import (
HTTPExceptionApiHandler,
)
-from ErrorHandlers.Exceptions.api_exc import (
- HTTPExceptionApi,
-)
+from ApiLayers.ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
+
DEFAULT_ERROR = "UNKNOWN_ERROR"
diff --git a/ApiLayers/ErrorHandlers/bases.py b/ApiLayers/ErrorHandlers/bases.py
index e7ee6a3..c045b80 100644
--- a/ApiLayers/ErrorHandlers/bases.py
+++ b/ApiLayers/ErrorHandlers/bases.py
@@ -1,5 +1,5 @@
-from ErrorHandlers.base import BaseError
-from ErrorHandlers.statuses import Statuses
+from ApiLayers.ErrorHandlers.base import BaseError
+from ApiLayers.ErrorHandlers.statuses import Statuses
class BaseErrorModelClass:
diff --git a/ApiLayers/LanguageModels/Database/account/account.py b/ApiLayers/LanguageModels/Database/account/account.py
index 8bb0857..57924b3 100644
--- a/ApiLayers/LanguageModels/Database/account/account.py
+++ b/ApiLayers/LanguageModels/Database/account/account.py
@@ -1,4 +1,4 @@
-from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
+from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
AccountBooksLanguageModel = dict(
tr={
diff --git a/ApiLayers/LanguageModels/Database/account/iban.py b/ApiLayers/LanguageModels/Database/account/iban.py
index ccc1b49..8adc724 100644
--- a/ApiLayers/LanguageModels/Database/account/iban.py
+++ b/ApiLayers/LanguageModels/Database/account/iban.py
@@ -1,4 +1,4 @@
-from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
+from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
BuildIbansLanguageModel = dict(
tr={
diff --git a/ApiLayers/LanguageModels/Database/building/budget.py b/ApiLayers/LanguageModels/Database/building/budget.py
index 515d6d5..b1b9890 100644
--- a/ApiLayers/LanguageModels/Database/building/budget.py
+++ b/ApiLayers/LanguageModels/Database/building/budget.py
@@ -1,4 +1,4 @@
-from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
+from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
DecisionBookBudgetBooksLanguageModel = dict(
tr={
diff --git a/ApiLayers/LanguageModels/Database/building/build.py b/ApiLayers/LanguageModels/Database/building/build.py
index 06aaa7e..e71c9d0 100644
--- a/ApiLayers/LanguageModels/Database/building/build.py
+++ b/ApiLayers/LanguageModels/Database/building/build.py
@@ -1,4 +1,4 @@
-from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
+from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
BuildTypesLanguageModel = dict(
tr={
diff --git a/ApiLayers/LanguageModels/Database/building/decision_book.py b/ApiLayers/LanguageModels/Database/building/decision_book.py
index fb2f6f5..8209b91 100644
--- a/ApiLayers/LanguageModels/Database/building/decision_book.py
+++ b/ApiLayers/LanguageModels/Database/building/decision_book.py
@@ -1,4 +1,4 @@
-from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
+from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
BuildDecisionBookLanguageModel = dict(
tr={
diff --git a/ApiLayers/LanguageModels/Database/company/company.py b/ApiLayers/LanguageModels/Database/company/company.py
index 94bdb14..be9047b 100644
--- a/ApiLayers/LanguageModels/Database/company/company.py
+++ b/ApiLayers/LanguageModels/Database/company/company.py
@@ -1,4 +1,4 @@
-from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
+from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
RelationshipDutyCompanyLanguageModel = dict(
tr={
diff --git a/ApiLayers/LanguageModels/Database/company/department.py b/ApiLayers/LanguageModels/Database/company/department.py
index 77b79f1..1ce4c33 100644
--- a/ApiLayers/LanguageModels/Database/company/department.py
+++ b/ApiLayers/LanguageModels/Database/company/department.py
@@ -1,4 +1,4 @@
-from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
+from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
DepartmentsLanguageModel = dict(
tr={
diff --git a/ApiLayers/LanguageModels/Database/company/employee.py b/ApiLayers/LanguageModels/Database/company/employee.py
index 391d1f2..ca96af7 100644
--- a/ApiLayers/LanguageModels/Database/company/employee.py
+++ b/ApiLayers/LanguageModels/Database/company/employee.py
@@ -1,4 +1,4 @@
-from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
+from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
StaffLanguageModel = dict(
tr={
diff --git a/ApiLayers/LanguageModels/Database/event/event.py b/ApiLayers/LanguageModels/Database/event/event.py
index 184608e..f30fd85 100644
--- a/ApiLayers/LanguageModels/Database/event/event.py
+++ b/ApiLayers/LanguageModels/Database/event/event.py
@@ -1,4 +1,4 @@
-from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
+from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
EventsLanguageModel = dict(
diff --git a/ApiLayers/LanguageModels/Database/identity/identity.py b/ApiLayers/LanguageModels/Database/identity/identity.py
index aeb7869..3b3c685 100644
--- a/ApiLayers/LanguageModels/Database/identity/identity.py
+++ b/ApiLayers/LanguageModels/Database/identity/identity.py
@@ -1,4 +1,4 @@
-from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
+from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
UsersTokensLanguageModel = dict(
tr={
diff --git a/ApiLayers/LanguageModels/Database/rules/rules.py b/ApiLayers/LanguageModels/Database/rules/rules.py
index 4d3f52e..bb79123 100644
--- a/ApiLayers/LanguageModels/Database/rules/rules.py
+++ b/ApiLayers/LanguageModels/Database/rules/rules.py
@@ -1,4 +1,4 @@
-from LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
+from ApiLayers.LanguageModels.Database.Mixins.crud_mixin import CrudCollectionLanguageModel
EndpointRestrictionLanguageModel = dict(
tr={
diff --git a/ApiLayers/LanguageModels/Errors/merge_all_error_languages.py b/ApiLayers/LanguageModels/Errors/merge_all_error_languages.py
index 5f83f27..17c6c2d 100644
--- a/ApiLayers/LanguageModels/Errors/merge_all_error_languages.py
+++ b/ApiLayers/LanguageModels/Errors/merge_all_error_languages.py
@@ -1,4 +1,4 @@
-from LanguageModels.Errors.base_languages import BaseErrorLanguageModels
+from ApiLayers.LanguageModels.Errors.base_languages import BaseErrorLanguageModels
class MergedErrorLanguageModels:
diff --git a/ApiLayers/AllApiNeeds/middleware/__init__.py b/ApiLayers/Middleware/__init__.py
similarity index 100%
rename from ApiLayers/AllApiNeeds/middleware/__init__.py
rename to ApiLayers/Middleware/__init__.py
diff --git a/ApiLayers/AllApiNeeds/middleware/auth_middleware.py b/ApiLayers/Middleware/auth_middleware.py
similarity index 86%
rename from ApiLayers/AllApiNeeds/middleware/auth_middleware.py
rename to ApiLayers/Middleware/auth_middleware.py
index c23d3d3..51b62a0 100644
--- a/ApiLayers/AllApiNeeds/middleware/auth_middleware.py
+++ b/ApiLayers/Middleware/auth_middleware.py
@@ -5,17 +5,19 @@ This module provides authentication decorator for protecting endpoints
and a middleware for request timing measurements.
"""
+import inspect
+
from time import perf_counter
-from typing import Callable, Optional, Dict, Any, Tuple, Union
+from typing import Callable
from functools import wraps
from fastapi import Request, Response
from starlette.middleware.base import BaseHTTPMiddleware
-from ApiLibrary.common.line_number import get_line_number_for_error
-from ErrorHandlers.ErrorHandlers.api_exc_handler import HTTPExceptionApi
-from AllConfigs.Token.config import Auth
-import inspect
+from ApiLayers.ApiLibrary.common.line_number import get_line_number_for_error
+from ApiLayers.ErrorHandlers.ErrorHandlers.api_exc_handler import HTTPExceptionApi
+from ApiLayers.AllConfigs.Token.config import Auth
+from ApiLayers.ApiServices.Token.token_handler import TokenService
class MiddlewareModule:
@@ -39,7 +41,6 @@ class MiddlewareModule:
Raises:
HTTPExceptionApi: If token is missing, invalid, or user not found
"""
- from ApiServices.Token.token_handler import TokenService
# Get token and validate - will raise HTTPExceptionApi if invalid
redis_token = TokenService.get_access_token_from_request(request=request)
@@ -86,14 +87,22 @@ class MiddlewareModule:
@wraps(func)
async def wrapper(request: Request, *args, **kwargs):
# Get and validate token context from request
- # Create auth context and Attach auth context to both wrapper and original function
- func.auth = cls.get_user_from_request(request)
- wrapper.auth = func.auth
+ auth_context = {
+ "is_employee": False,
+ "is_occupant": False,
+ "context": {}
+ }
+
+ # Set auth context on the wrapper function itself
+ setattr(wrapper, 'auth', auth_context)
+
# Call the original endpoint function
if inspect.iscoroutinefunction(func):
- return await func(request, *args, **kwargs)
- return func(request, *args, **kwargs)
-
+ result = await func(request, *args, **kwargs)
+ else:
+ result = func(request, *args, **kwargs)
+
+ return result
return wrapper
diff --git a/ApiLayers/AllApiNeeds/middleware/function_wrappers.py b/ApiLayers/Middleware/function_wrappers.py
similarity index 100%
rename from ApiLayers/AllApiNeeds/middleware/function_wrappers.py
rename to ApiLayers/Middleware/function_wrappers.py
diff --git a/ApiLayers/AllApiNeeds/middleware/token_event_middleware.py b/ApiLayers/Middleware/token_event_middleware.py
similarity index 79%
rename from ApiLayers/AllApiNeeds/middleware/token_event_middleware.py
rename to ApiLayers/Middleware/token_event_middleware.py
index 3db8774..1129762 100644
--- a/ApiLayers/AllApiNeeds/middleware/token_event_middleware.py
+++ b/ApiLayers/Middleware/token_event_middleware.py
@@ -9,13 +9,12 @@ from typing import Callable, Dict, Any, Optional, Union
from fastapi import Request
from pydantic import BaseModel
-from ApiLibrary.common.line_number import get_line_number_for_error
-from ApiServices.Token.token_handler import TokenService
-from ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
-from Schemas.rules.rules import EndpointRestriction
+from ApiLayers.ApiLibrary.common.line_number import get_line_number_for_error
+from ApiLayers.ApiServices.Token.token_handler import TokenService
+from ApiLayers.ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
+from ApiLayers.Schemas import Events, EndpointRestriction
from .auth_middleware import MiddlewareModule
-from Schemas import Events
class EventFunctions:
@@ -24,88 +23,7 @@ class EventFunctions:
self.endpoint = endpoint
self.request = request
- def match_endpoint_with_accesiable_event(self) -> Optional[Dict[str, Any]]:
- """
- Match an endpoint with accessible events.
- Args:
- endpoint: The endpoint to match
-
- Returns:
- Dict containing the endpoint registration data
- None if endpoint is not found in database
- """
- access_token = TokenService.get_access_token_from_request(self.request)
- token_context = TokenService.get_object_via_access_key(
- access_token=access_token
- )
- if token_context.is_employee:
- reachable_event_codes: list[str] = (
- token_context.selected_company.reachable_event_codes
- )
- elif token_context.is_occupant:
- reachable_event_codes: list[str] = (
- token_context.selected_occupant.reachable_event_codes
- )
- else:
- raise HTTPExceptionApi(
- error_code="",
- lang="en",
- loc=get_line_number_for_error(),
- sys_msg="Token not found",
- )
-
- if not access_token:
- raise HTTPExceptionApi(
- error_code="",
- lang="en",
- loc=get_line_number_for_error(),
- sys_msg="Token not found",
- )
-
- db = EndpointRestriction.new_session()
- restriction = EndpointRestriction.filter_one(
- EndpointRestriction.endpoint_name == self.endpoint,
- db=db,
- ).data
- if not restriction:
- raise HTTPExceptionApi(
- error_code="",
- lang="en",
- loc=get_line_number_for_error(),
- sys_msg="Function code not found",
- )
-
- event_related = Events.filter_all(
- Events.endpoint_id == restriction.id,
- db=db,
- ).data
- if not event_related:
- raise HTTPExceptionApi(
- error_code="",
- lang="en",
- loc=get_line_number_for_error(),
- sys_msg="No event is registered for this user.",
- )
- an_event = event_related[0]
- event_related_codes: list[str] = [
- event.function_code for event in event_related
- ]
- intersected_code: set = set(reachable_event_codes).intersection(
- set(event_related_codes)
- )
- if not len(list(intersected_code)) == 1:
- raise HTTPExceptionApi(
- error_code="",
- lang="en",
- loc=get_line_number_for_error(),
- sys_msg="No event is registered for this user.",
- )
- return {
- "endpoint_url": self.endpoint,
- "reachable_event_code": list(intersected_code)[0],
- "class": an_event.function_class,
- }
def retrieve_function_dict(self) -> Optional[Dict[str, Any]]:
"""
@@ -201,9 +119,91 @@ class TokenEventMiddleware:
"""
@staticmethod
- def event_required(
- func: Callable[..., Dict[str, Any]]
- ) -> Callable[..., Dict[str, Any]]:
+ def match_endpoint_with_accessible_event(request_from_scope, endpoint_from_scope) -> Optional[Dict[str, Any]]:
+ """
+ Match an endpoint with accessible events.
+
+ Args:
+ request_from_scope: The endpoint to match
+
+ Returns:
+ Dict containing the endpoint registration data
+ None if endpoint is not found in database
+ """
+ access_token = TokenService.get_access_token_from_request(request_from_scope)
+ token_context = TokenService.get_object_via_access_key(
+ access_token=access_token
+ )
+ if token_context.is_employee:
+ reachable_event_codes: list[str] = (
+ token_context.selected_company.reachable_event_codes
+ )
+ elif token_context.is_occupant:
+ reachable_event_codes: list[str] = (
+ token_context.selected_occupant.reachable_event_codes
+ )
+ else:
+ raise HTTPExceptionApi(
+ error_code="",
+ lang="en",
+ loc=get_line_number_for_error(),
+ sys_msg="Token not found",
+ )
+
+ if not access_token:
+ raise HTTPExceptionApi(
+ error_code="",
+ lang="en",
+ loc=get_line_number_for_error(),
+ sys_msg="Token not found",
+ )
+
+ db = EndpointRestriction.new_session()
+ restriction = EndpointRestriction.filter_one(
+ EndpointRestriction.endpoint_name == endpoint_from_scope,
+ db=db,
+ ).data
+ if not restriction:
+ raise HTTPExceptionApi(
+ error_code="",
+ lang="en",
+ loc=get_line_number_for_error(),
+ sys_msg="Function code not found",
+ )
+
+ event_related = Events.filter_all(
+ Events.endpoint_id == restriction.id,
+ db=db,
+ ).data
+ if not event_related:
+ raise HTTPExceptionApi(
+ error_code="",
+ lang="en",
+ loc=get_line_number_for_error(),
+ sys_msg="No event is registered for this user.",
+ )
+ an_event = event_related[0]
+ event_related_codes: list[str] = [
+ event.function_code for event in event_related
+ ]
+ intersected_code: set = set(reachable_event_codes).intersection(
+ set(event_related_codes)
+ )
+ if not len(list(intersected_code)) == 1:
+ raise HTTPExceptionApi(
+ error_code="",
+ lang="en",
+ loc=get_line_number_for_error(),
+ sys_msg="No event is registered for this user.",
+ )
+ return {
+ "endpoint_url": endpoint_from_scope,
+ "reachable_event_code": list(intersected_code)[0],
+ "class": an_event.function_class,
+ }
+
+ @classmethod
+ def event_required(cls, func: Callable) -> Callable:
"""
Decorator for endpoints with token and event requirements.
This decorator:
@@ -216,31 +216,36 @@ class TokenEventMiddleware:
Returns:
Callable: The wrapped function with both auth and event handling
"""
- # # First apply authentication
- # authenticated_func = MiddlewareModule.auth_required(func)
- authenticated_func = func
+ # First apply authentication
+ authenticated_func = MiddlewareModule.auth_required(func)
@wraps(authenticated_func)
async def wrapper(request: Request, *args, **kwargs) -> Dict[str, Any]:
-
- # Get function code from the function's metadata
- endpoint_url = getattr(authenticated_func, "url_of_endpoint", {})
- if not endpoint_url:
- raise HTTPExceptionApi(
- error_code="",
- lang="en",
- loc=get_line_number_for_error(),
- sys_msg="Function code not found",
- )
-
- # Make handler available to all functions in the chain
- func.func_code = EventFunctions(
- endpoint_url, request
- ).match_endpoint_with_accesiable_event()
- # Call the authenticated function
+ # Get the endpoint URL for matching with events
+ endpoint_url = str(request.url.path)
+
+ # Set func_code first
+ func_code = "8aytr-"
+ setattr(wrapper, 'func_code', func_code)
+
+ # Get auth context from the authenticated function's wrapper
+ auth_context = getattr(authenticated_func, 'auth', None)
+ print('auth_context', auth_context)
+ if auth_context is not None:
+ setattr(wrapper, 'auth', auth_context)
+
+ # Execute the authenticated function and get its result
if inspect.iscoroutinefunction(authenticated_func):
- return await authenticated_func(request, *args, **kwargs)
- return authenticated_func(request, *args, **kwargs)
+ result = await authenticated_func(request, *args, **kwargs)
+ else:
+ result = authenticated_func(request, *args, **kwargs)
+
+ return result
+
+ # Copy any existing attributes from the authenticated function
+ for attr in dir(authenticated_func):
+ if not attr.startswith('__'):
+ setattr(wrapper, attr, getattr(authenticated_func, attr))
return wrapper
@@ -261,8 +266,8 @@ class TokenEventMiddleware:
Callable: The wrapped function with both auth and event handling
"""
# First apply authentication
- authenticated_func = MiddlewareModule.auth_required(func)
-
+ # authenticated_func = MiddlewareModule.auth_required(func)
+ authenticated_func = func
@wraps(authenticated_func)
async def wrapper(
request: Request, *args: Any, **kwargs: Any
@@ -278,9 +283,9 @@ class TokenEventMiddleware:
loc=get_line_number_for_error(),
sys_msg="Endpoint not found",
)
- wrapper.validation_code = EventFunctions(
- endpoint_asked, request
- ).retrieve_function_dict()
+ func.func_code = cls.match_endpoint_with_accessible_event(
+ endpoint_url, request
+ )
if inspect.iscoroutinefunction(authenticated_func):
result = await authenticated_func(request, *args, **kwargs)
else:
@@ -289,9 +294,14 @@ class TokenEventMiddleware:
wrapper.auth = function_auth
func.auth = function_auth
authenticated_func.auth = function_auth
- # If result is a coroutine, await it
- if inspect.iscoroutine(result):
- result = await result
+ if inspect.iscoroutinefunction(authenticated_func):
+ result = await authenticated_func(request, *args, **kwargs)
+ else:
+ result = authenticated_func(request, *args, **kwargs)
+ if inspect.iscoroutinefunction(func):
+ result = await func(request, *args, **kwargs)
+ else:
+ result = func(request, *args, **kwargs)
return result
return wrapper
diff --git a/ApiLayers/Schemas/account/account.py b/ApiLayers/Schemas/account/account.py
index 707a233..2a30db6 100644
--- a/ApiLayers/Schemas/account/account.py
+++ b/ApiLayers/Schemas/account/account.py
@@ -11,7 +11,7 @@ from sqlalchemy import (
)
from Services.PostgresDb import CrudCollection
-from LanguageModels.Database.account.account import (
+from ApiLayers.LanguageModels.Database.account.account import (
AccountBooksLanguageModel,
AccountCodesLanguageModel,
AccountRecordsLanguageModel,
diff --git a/ApiLayers/Schemas/building/build.py b/ApiLayers/Schemas/building/build.py
index 0efcdee..3366451 100644
--- a/ApiLayers/Schemas/building/build.py
+++ b/ApiLayers/Schemas/building/build.py
@@ -15,17 +15,17 @@ from sqlalchemy import (
or_,
)
-from ApiLibrary import system_arrow, SelectActionWithEmployee
+from ApiLayers.ApiLibrary import system_arrow, SelectActionWithEmployee
from Services.PostgresDb import CrudCollection
-from ApiValidations.Request import (
+from ApiLayers.ApiValidations.Request import (
InsertBuild,
InsertBuildParts,
InsertBuildLivingSpace,
UpdateBuild,
)
-from ApiValidations.Custom.token_objects import EmployeeTokenObject, OccupantTokenObject
-from LanguageModels.Database.building.build import (
+from ApiLayers.ApiValidations.Custom.token_objects import EmployeeTokenObject, OccupantTokenObject
+from ApiLayers.LanguageModels.Database.building.build import (
BuildTypesLanguageModel,
Part2EmployeeLanguageModel,
BuildPartsLanguageModel,
diff --git a/ApiLayers/Schemas/building/decision_book.py b/ApiLayers/Schemas/building/decision_book.py
index 12cd710..de8e53c 100644
--- a/ApiLayers/Schemas/building/decision_book.py
+++ b/ApiLayers/Schemas/building/decision_book.py
@@ -4,7 +4,7 @@ from decimal import Decimal
from typing import List
from fastapi import HTTPException, status
-from ApiLibrary.date_time_actions.date_functions import system_arrow
+from ApiLayers.ApiLibrary.date_time_actions.date_functions import system_arrow
from sqlalchemy import (
String,
@@ -19,14 +19,14 @@ from sqlalchemy import (
)
from sqlalchemy.orm import Mapped, mapped_column, relationship
-from ApiValidations.Request import (
+from ApiLayers.ApiValidations.Request import (
InsertDecisionBook,
InsertBuildDecisionBookItems,
InsertBuildDecisionBookItemDebits,
InsertBuildDecisionBookProjects,
)
from Services.PostgresDb import CrudCollection
-from LanguageModels.Database.building.decision_book import (
+from ApiLayers.LanguageModels.Database.building.decision_book import (
BuildDecisionBookLanguageModel,
BuildDecisionBookInvitationsLanguageModel,
BuildDecisionBookPersonLanguageModel,
diff --git a/ApiLayers/Schemas/company/company.py b/ApiLayers/Schemas/company/company.py
index dea49af..73752a2 100644
--- a/ApiLayers/Schemas/company/company.py
+++ b/ApiLayers/Schemas/company/company.py
@@ -11,14 +11,14 @@ from sqlalchemy import (
)
from sqlalchemy.orm import mapped_column, relationship, Mapped
-from ApiLibrary.extensions.select import SelectAction
-from ApiValidations.Custom.token_objects import EmployeeTokenObject
-from ApiValidations.Request import (
+from ApiLayers.ApiLibrary.extensions.select import SelectAction
+from ApiLayers.ApiValidations.Custom.token_objects import EmployeeTokenObject
+from ApiLayers.ApiValidations.Request import (
InsertCompany,
UpdateCompany,
MatchCompany2Company,
)
-from LanguageModels.Database.company.company import (
+from ApiLayers.LanguageModels.Database.company.company import (
RelationshipDutyCompanyLanguageModel,
CompaniesLanguageModel,
# CompanyDutiesLanguageModel,
diff --git a/ApiLayers/Schemas/company/employee.py b/ApiLayers/Schemas/company/employee.py
index dd892ca..748fc93 100644
--- a/ApiLayers/Schemas/company/employee.py
+++ b/ApiLayers/Schemas/company/employee.py
@@ -6,7 +6,7 @@ from sqlalchemy import (
)
from sqlalchemy.orm import mapped_column, Mapped
-from LanguageModels.Database.company.employee import (
+from ApiLayers.LanguageModels.Database.company.employee import (
StaffLanguageModel,
EmployeesLanguageModel,
EmployeeHistoryLanguageModel,
@@ -14,7 +14,7 @@ from LanguageModels.Database.company.employee import (
)
from Services.PostgresDb import CrudCollection
-from ApiValidations.Request import InsertCompanyEmployees
+from ApiLayers.ApiValidations.Request import InsertCompanyEmployees
class Staff(CrudCollection):
diff --git a/ApiLayers/Schemas/event/event.py b/ApiLayers/Schemas/event/event.py
index d30b6ce..3f6cf9e 100644
--- a/ApiLayers/Schemas/event/event.py
+++ b/ApiLayers/Schemas/event/event.py
@@ -1,5 +1,5 @@
from Services.PostgresDb import CrudCollection
-from LanguageModels.Database.event.event import (
+from ApiLayers.LanguageModels.Database.event.event import (
EventsLanguageModel,
ModulesLanguageModel,
ServicesLanguageModel,
diff --git a/ApiLayers/Schemas/identity/identity.py b/ApiLayers/Schemas/identity/identity.py
index eef7ce6..133ebe1 100644
--- a/ApiLayers/Schemas/identity/identity.py
+++ b/ApiLayers/Schemas/identity/identity.py
@@ -8,24 +8,23 @@ from sqlalchemy import (
ForeignKey,
Index,
TIMESTAMP,
- func,
Text,
BigInteger,
Numeric,
+ func,
or_,
)
from sqlalchemy.orm import mapped_column, relationship, Mapped
-from ApiLibrary.date_time_actions.date_functions import system_arrow
-from AllConfigs.Token.config import Auth, ApiStatic
-from ApiLibrary.extensions.select import SelectAction, SelectActionWithEmployee
+from ApiLayers.ApiLibrary.date_time_actions.date_functions import system_arrow
+from ApiLayers.ApiLibrary.extensions.select import SelectAction, SelectActionWithEmployee
+from ApiLayers.AllConfigs.Token.config import Auth
from Services.PostgresDb import CrudCollection
+from config import ApiStatic
-# from databases.extensions import SelectAction, SelectActionWithEmployee
-# from databases.extensions.auth import UserLoginModule
-from ApiValidations.Request import InsertUsers, InsertPerson
-from LanguageModels.Database.identity.identity import (
+from ApiLayers.ApiValidations.Request import InsertUsers, InsertPerson
+from ApiLayers.LanguageModels.Database.identity.identity import (
UsersTokensLanguageModel,
UsersLanguageModel,
PeopleLanguageModel,
diff --git a/ApiLayers/Schemas/rules/rules.py b/ApiLayers/Schemas/rules/rules.py
index 95285a3..a2bcb12 100644
--- a/ApiLayers/Schemas/rules/rules.py
+++ b/ApiLayers/Schemas/rules/rules.py
@@ -1,7 +1,7 @@
from sqlalchemy import String
from sqlalchemy.orm import mapped_column, Mapped
-from LanguageModels.Database.rules.rules import EndpointRestrictionLanguageModel
+from ApiLayers.LanguageModels.Database.rules.rules import EndpointRestrictionLanguageModel
from Services.PostgresDb import CrudCollection
diff --git a/DockerApiServices/AuthServiceApi/Dockerfile b/DockerApiServices/AuthServiceApi/Dockerfile
index 082ced1..a406c4f 100644
--- a/DockerApiServices/AuthServiceApi/Dockerfile
+++ b/DockerApiServices/AuthServiceApi/Dockerfile
@@ -19,15 +19,18 @@ RUN poetry config virtualenvs.create false \
&& rm -rf ~/.cache/pypoetry
# Copy application code
-COPY DockerApiServices/AllApiNeeds /app
+COPY DockerApiServices/AuthServiceApi /app
# Copy application code
COPY ApiLayers /app/ApiLayers
+COPY Services /app/Services
# Events
-COPY Events/AllEvents/auth /app/Events/AllEvents/auth
+# COPY Events/base_request_model.py /app/Events/base_request_model.py
+COPY Events/Engine /app/Events/Engine
COPY Events/base_request_model.py /app/Events/base_request_model.py
-COPY Events/abstract_class.py /app/Events/abstract_class.py
+COPY Events/AllEvents/authentication /app/Events/AllEvents/authentication
+COPY DockerApiServices/AuthServiceApi/events_file.py /app/Events/AllEvents/events_file.py
# Set Python path to include app directory
ENV PYTHONPATH=/app \
diff --git a/ApiLayers/AllApiNeeds/app.py b/DockerApiServices/AuthServiceApi/app.py
similarity index 77%
rename from ApiLayers/AllApiNeeds/app.py
rename to DockerApiServices/AuthServiceApi/app.py
index 1d12a8b..68ed880 100644
--- a/ApiLayers/AllApiNeeds/app.py
+++ b/DockerApiServices/AuthServiceApi/app.py
@@ -10,9 +10,11 @@ This module initializes and configures the FastAPI application with:
"""
import uvicorn
+
from prometheus_fastapi_instrumentator import Instrumentator
-from app_handler import setup_middleware, get_uvicorn_config
+from app_handler import setup_middleware
from create_file import create_app
+from config import ApiConfig
app = create_app() # Initialize FastAPI application
@@ -21,5 +23,5 @@ setup_middleware(app) # Configure middleware and exception handlers
if __name__ == "__main__":
- uvicorn_config = get_uvicorn_config() # Run the application with Uvicorn
- uvicorn.Server(uvicorn.Config(**uvicorn_config)).run()
+ # Run the application with Uvicorn
+ uvicorn.Server(uvicorn.Config(**ApiConfig.as_dict())).run()
diff --git a/ApiLayers/AllApiNeeds/app_handler.py b/DockerApiServices/AuthServiceApi/app_handler.py
similarity index 75%
rename from ApiLayers/AllApiNeeds/app_handler.py
rename to DockerApiServices/AuthServiceApi/app_handler.py
index 7c1b5f2..3156e6a 100644
--- a/ApiLayers/AllApiNeeds/app_handler.py
+++ b/DockerApiServices/AuthServiceApi/app_handler.py
@@ -7,13 +7,12 @@ This module contains all the handler functions for configuring and setting up th
- Uvicorn server configuration
"""
-from typing import Dict, Any
-
+from fastapi import FastAPI, Request, status
from fastapi.middleware.cors import CORSMiddleware
-from fastapi import FastAPI, Request, HTTPException, status
from fastapi.responses import JSONResponse
-from ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
-from middleware.auth_middleware import RequestTimingMiddleware, LoggerTimingMiddleware
+
+from ApiLayers.ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
+from ApiLayers.Middleware.auth_middleware import RequestTimingMiddleware, LoggerTimingMiddleware
def setup_cors_middleware(app: FastAPI) -> None:
@@ -56,7 +55,7 @@ def setup_exception_handlers(app: FastAPI) -> None:
Args:
app: FastAPI application instance
"""
- from ErrorHandlers.ErrorHandlers.api_exc_handler import HTTPExceptionApiHandler
+ from ApiLayers.ErrorHandlers.ErrorHandlers.api_exc_handler import HTTPExceptionApiHandler
custom_exception_handler = HTTPExceptionApiHandler(response_model=JSONResponse)
app.add_exception_handler(
@@ -76,19 +75,3 @@ def setup_middleware(app: FastAPI) -> None:
app.add_middleware(RequestTimingMiddleware)
app.add_middleware(LoggerTimingMiddleware)
setup_exception_handlers(app)
-
-
-def get_uvicorn_config() -> Dict[str, Any]:
- """
- Get Uvicorn server configuration.
-
- Returns:
- Dict[str, Any]: Uvicorn configuration dictionary
- """
- return {
- "app": "app:app",
- "host": "0.0.0.0",
- "port": 41575,
- "log_level": "info",
- "reload": True,
- }
diff --git a/DockerApiServices/AuthServiceApi/config.py b/DockerApiServices/AuthServiceApi/config.py
new file mode 100644
index 0000000..1241b17
--- /dev/null
+++ b/DockerApiServices/AuthServiceApi/config.py
@@ -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"
diff --git a/DockerApiServices/AuthServiceApi/create_file.py b/DockerApiServices/AuthServiceApi/create_file.py
new file mode 100644
index 0000000..68b3f88
--- /dev/null
+++ b/DockerApiServices/AuthServiceApi/create_file.py
@@ -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
diff --git a/DockerApiServices/AuthServiceApi/create_routes.py b/DockerApiServices/AuthServiceApi/create_routes.py
new file mode 100644
index 0000000..62c276e
--- /dev/null
+++ b/DockerApiServices/AuthServiceApi/create_routes.py
@@ -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
diff --git a/DockerApiServices/AuthServiceApi/events_file.py b/DockerApiServices/AuthServiceApi/events_file.py
new file mode 100644
index 0000000..8be1ffc
--- /dev/null
+++ b/DockerApiServices/AuthServiceApi/events_file.py
@@ -0,0 +1,3 @@
+import Events.AllEvents.authentication as auths_events
+
+events_list = (auths_events,)
diff --git a/ApiLayers/AllApiNeeds/open_api_creator.py b/DockerApiServices/AuthServiceApi/open_api_creator.py
similarity index 82%
rename from ApiLayers/AllApiNeeds/open_api_creator.py
rename to DockerApiServices/AuthServiceApi/open_api_creator.py
index 6163e2d..01a37c6 100644
--- a/ApiLayers/AllApiNeeds/open_api_creator.py
+++ b/DockerApiServices/AuthServiceApi/open_api_creator.py
@@ -9,14 +9,13 @@ This module provides functionality to create and customize OpenAPI documentation
- Custom documentation extensions
"""
-from typing import Any, Dict, List, Optional, Set
-from fastapi import FastAPI, APIRouter
+from typing import Any, Dict
+from fastapi import FastAPI
from fastapi.routing import APIRoute
from fastapi.openapi.utils import get_openapi
-from AllConfigs.Token.config import Auth
-from AllConfigs.main import MainConfig as Config
from create_routes import get_all_routers
+from config import ApiConfig
class OpenAPISchemaCreator:
@@ -32,28 +31,8 @@ class OpenAPISchemaCreator:
app: FastAPI application instance
"""
self.app = app
- _, self.protected_routes = get_all_routers()
- # self.tags_metadata = self._create_tags_metadata()
-
- @staticmethod
- def _create_tags_metadata() -> List[Dict[str, str]]:
- """
- Create metadata for API tags.
-
- Returns:
- List[Dict[str, str]]: List of tag metadata
- """
- return [
- {
- "name": "Authentication",
- "description": "Operations related to user authentication and authorization",
- },
- {
- "name": "Users",
- "description": "User management and profile operations",
- },
- # Add more tags as needed
- ]
+ self.cluster = get_all_routers()
+ self.safe_endpoint_list = self.cluster.safe_endpoints if hasattr(self.cluster, 'safe_endpoints') else []
def _create_security_schemes(self) -> Dict[str, Any]:
"""
@@ -62,8 +41,9 @@ class OpenAPISchemaCreator:
Returns:
Dict[str, Any]: Security scheme configurations
"""
+ from ApiLayers.AllConfigs.Token.config import Auth
return {
- "Bearer Auth": {
+ "BearerAuth": {
"type": "apiKey",
"in": "header",
"name": Auth.ACCESS_TOKEN_TAG,
@@ -206,19 +186,17 @@ class OpenAPISchemaCreator:
method: HTTP method
schema: OpenAPI schema to modify
"""
- # Check if route is protected based on dynamic routing info
- if path in self.protected_routes and method in self.protected_routes[path]:
- schema["paths"][path][method]["security"] = [
- {"Bearer Auth": []},
- ]
- schema["paths"][path][method]["responses"].update(
- self._create_common_responses()
- )
+ if not schema.get("paths", {}).get(path, {}).get(method):
+ return
- # Process request body examples
- self._process_request_body(path, method, schema)
- # Process response examples
- self._process_response_examples(path, method, schema)
+ # Check if endpoint is in safe list
+ endpoint_path = f"{path}:{method}"
+ if endpoint_path not in [f"{e.URL}:{e.METHOD.lower()}" for e in self.safe_endpoint_list]:
+ if "security" not in schema["paths"][path][method]:
+ schema["paths"][path][method]["security"] = []
+ schema["paths"][path][method]["security"].append(
+ {"BearerAuth": []}
+ )
def create_schema(self) -> Dict[str, Any]:
"""
@@ -228,8 +206,8 @@ class OpenAPISchemaCreator:
Dict[str, Any]: Complete OpenAPI schema
"""
openapi_schema = get_openapi(
- title=Config.TITLE,
- description=Config.DESCRIPTION,
+ title=ApiConfig.TITLE,
+ description=ApiConfig.DESCRIPTION,
version="1.1.1",
routes=self.app.routes,
)
@@ -238,9 +216,8 @@ class OpenAPISchemaCreator:
if "components" not in openapi_schema:
openapi_schema["components"] = {}
- openapi_schema["components"][
- "securitySchemes"
- ] = self._create_security_schemes()
+ openapi_schema["components"]["securitySchemes"] = self._create_security_schemes()
+
# Configure route security and responses
for route in self.app.routes:
if isinstance(route, APIRoute) and route.include_in_schema:
@@ -249,13 +226,12 @@ class OpenAPISchemaCreator:
for method in methods:
self.configure_route_security(path, method, openapi_schema)
- # # Add custom documentation extensions
+ # Add custom documentation extensions
openapi_schema["x-documentation"] = {
"postman_collection": "/docs/postman",
"swagger_ui": "/docs",
"redoc": "/redoc",
}
-
return openapi_schema
diff --git a/DockerApiServices/EventServiceApi/Dockerfile b/DockerApiServices/EventServiceApi/Dockerfile
index aa09676..29d3790 100644
--- a/DockerApiServices/EventServiceApi/Dockerfile
+++ b/DockerApiServices/EventServiceApi/Dockerfile
@@ -19,22 +19,18 @@ RUN poetry config virtualenvs.create false \
&& rm -rf ~/.cache/pypoetry
# Copy application code
-COPY DockerApiServices/AllApiNeeds /app
-COPY ErrorHandlers /app/ErrorHandlers
-COPY LanguageModels /app/LanguageModels
-COPY ApiLibrary /app/ApiLibrary
-COPY ApiValidations /app/ApiValidations
-COPY AllConfigs /app/AllConfigs
-COPY ErrorHandlers /app/ErrorHandlers
-COPY Schemas /app/Schemas
+COPY DockerApiServices/EventServiceApi /app
+
+# Copy application code
+COPY ApiLayers /app/ApiLayers
COPY Services /app/Services
-COPY ApiServices /app/ApiServices
-
-# Copy Events structure with consistent naming
-COPY ApiEvents/EventServiceApi /app/ApiEvents
-COPY ApiEvents/abstract_class.py /app/ApiEvents/abstract_class.py
-COPY ApiEvents/base_request_model.py /app/ApiEvents/base_request_model.py
+# Events
+# COPY Events/base_request_model.py /app/Events/base_request_model.py
+COPY Events/Engine /app/Events/Engine
+COPY Events/base_request_model.py /app/Events/base_request_model.py
+COPY Events/AllEvents/events /app/Events/AllEvents/events
+COPY DockerApiServices/EventServiceApi/events_file.py /app/Events/AllEvents/events_file.py
# Set Python path to include app directory
ENV PYTHONPATH=/app \
diff --git a/DockerApiServices/EventServiceApi/app.py b/DockerApiServices/EventServiceApi/app.py
new file mode 100644
index 0000000..68ed880
--- /dev/null
+++ b/DockerApiServices/EventServiceApi/app.py
@@ -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()
diff --git a/DockerApiServices/EventServiceApi/app_handler.py b/DockerApiServices/EventServiceApi/app_handler.py
new file mode 100644
index 0000000..3156e6a
--- /dev/null
+++ b/DockerApiServices/EventServiceApi/app_handler.py
@@ -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)
diff --git a/DockerApiServices/EventServiceApi/config.py b/DockerApiServices/EventServiceApi/config.py
new file mode 100644
index 0000000..d5b9fcf
--- /dev/null
+++ b/DockerApiServices/EventServiceApi/config.py
@@ -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
+
diff --git a/DockerApiServices/EventServiceApi/create_file.py b/DockerApiServices/EventServiceApi/create_file.py
new file mode 100644
index 0000000..68b3f88
--- /dev/null
+++ b/DockerApiServices/EventServiceApi/create_file.py
@@ -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
diff --git a/DockerApiServices/EventServiceApi/create_routes.py b/DockerApiServices/EventServiceApi/create_routes.py
new file mode 100644
index 0000000..8006964
--- /dev/null
+++ b/DockerApiServices/EventServiceApi/create_routes.py
@@ -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
+
+
diff --git a/DockerApiServices/EventServiceApi/events_file.py b/DockerApiServices/EventServiceApi/events_file.py
new file mode 100644
index 0000000..de548b3
--- /dev/null
+++ b/DockerApiServices/EventServiceApi/events_file.py
@@ -0,0 +1,3 @@
+import Events.AllEvents.events as events_events
+
+events_list = (events_events,)
diff --git a/DockerApiServices/EventServiceApi/open_api_creator.py b/DockerApiServices/EventServiceApi/open_api_creator.py
new file mode 100644
index 0000000..01a37c6
--- /dev/null
+++ b/DockerApiServices/EventServiceApi/open_api_creator.py
@@ -0,0 +1,249 @@
+"""
+OpenAPI Schema Creator Module
+
+This module provides functionality to create and customize OpenAPI documentation:
+- Custom security schemes (Bearer Auth, API Key)
+- Response schemas and examples
+- Tag management and descriptions
+- Error responses and validation
+- Custom documentation extensions
+"""
+
+from typing import Any, Dict
+from fastapi import FastAPI
+from fastapi.routing import APIRoute
+from fastapi.openapi.utils import get_openapi
+
+from create_routes import get_all_routers
+from config import ApiConfig
+
+
+class OpenAPISchemaCreator:
+ """
+ OpenAPI schema creator and customizer for FastAPI applications.
+ """
+
+ def __init__(self, app: FastAPI):
+ """
+ Initialize the OpenAPI schema creator.
+
+ Args:
+ app: FastAPI application instance
+ """
+ self.app = app
+ self.cluster = get_all_routers()
+ self.safe_endpoint_list = self.cluster.safe_endpoints if hasattr(self.cluster, 'safe_endpoints') else []
+
+ def _create_security_schemes(self) -> Dict[str, Any]:
+ """
+ Create security scheme definitions.
+
+ Returns:
+ Dict[str, Any]: Security scheme configurations
+ """
+ from ApiLayers.AllConfigs.Token.config import Auth
+ return {
+ "BearerAuth": {
+ "type": "apiKey",
+ "in": "header",
+ "name": Auth.ACCESS_TOKEN_TAG,
+ "description": "Enter: **'Bearer <JWT>'**, where JWT is the access token",
+ }
+ }
+
+ def _create_common_responses(self) -> Dict[str, Any]:
+ """
+ Create common response schemas.
+
+ Returns:
+ Dict[str, Any]: Common response configurations
+ """
+ return {
+ "401": {
+ "description": "Unauthorized - Invalid or missing credentials",
+ "content": {
+ "application/json": {
+ "schema": {"$ref": "#/components/schemas/HTTPValidationError"}
+ }
+ },
+ },
+ "403": {
+ "description": "Forbidden - Insufficient permissions",
+ "content": {
+ "application/json": {
+ "schema": {"$ref": "#/components/schemas/HTTPValidationError"}
+ }
+ },
+ },
+ "422": {
+ "description": "Validation Error",
+ "content": {
+ "application/json": {
+ "schema": {"$ref": "#/components/schemas/HTTPValidationError"}
+ }
+ },
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "detail": {"type": "string"},
+ "error_code": {"type": "string"},
+ },
+ },
+ "example": {
+ "detail": "Internal server error occurred",
+ "error_code": "INTERNAL_ERROR",
+ },
+ }
+ },
+ },
+ }
+
+ def _process_request_body(
+ self, path: str, method: str, schema: Dict[str, Any]
+ ) -> None:
+ """
+ Process request body to include examples from model config.
+
+ Args:
+ path: Route path
+ method: HTTP method
+ schema: OpenAPI schema to modify
+ """
+ try:
+ route_schema = schema["paths"][path][method]
+ if "requestBody" in route_schema:
+ request_body = route_schema["requestBody"]
+ if "content" in request_body:
+ content = request_body["content"]
+ if "application/json" in content:
+ json_content = content["application/json"]
+ if (
+ "schema" in json_content
+ and "$ref" in json_content["schema"]
+ ):
+ ref = json_content["schema"]["$ref"]
+ model_name = ref.split("/")[-1]
+ if model_name in schema["components"]["schemas"]:
+ model_schema = schema["components"]["schemas"][
+ model_name
+ ]
+ if "example" in model_schema:
+ json_content["example"] = model_schema["example"]
+ except KeyError:
+ pass
+
+ def _process_response_examples(
+ self, path: str, method: str, schema: Dict[str, Any]
+ ) -> None:
+ """
+ Process response body to include examples from model config.
+
+ Args:
+ path: Route path
+ method: HTTP method
+ schema: OpenAPI schema to modify
+ """
+ try:
+ route_schema = schema["paths"][path][method]
+ if "responses" in route_schema:
+ responses = route_schema["responses"]
+ if "200" in responses:
+ response = responses["200"]
+ if "content" in response:
+ content = response["content"]
+ if "application/json" in content:
+ json_content = content["application/json"]
+ if (
+ "schema" in json_content
+ and "$ref" in json_content["schema"]
+ ):
+ ref = json_content["schema"]["$ref"]
+ model_name = ref.split("/")[-1]
+ if model_name in schema["components"]["schemas"]:
+ model_schema = schema["components"]["schemas"][
+ model_name
+ ]
+ if "example" in model_schema:
+ json_content["example"] = model_schema[
+ "example"
+ ]
+ except KeyError:
+ pass
+
+ def configure_route_security(
+ self, path: str, method: str, schema: Dict[str, Any]
+ ) -> None:
+ """
+ Configure security requirements for a specific route.
+
+ Args:
+ path: Route path
+ method: HTTP method
+ schema: OpenAPI schema to modify
+ """
+ if not schema.get("paths", {}).get(path, {}).get(method):
+ return
+
+ # Check if endpoint is in safe list
+ endpoint_path = f"{path}:{method}"
+ if endpoint_path not in [f"{e.URL}:{e.METHOD.lower()}" for e in self.safe_endpoint_list]:
+ if "security" not in schema["paths"][path][method]:
+ schema["paths"][path][method]["security"] = []
+ schema["paths"][path][method]["security"].append(
+ {"BearerAuth": []}
+ )
+
+ def create_schema(self) -> Dict[str, Any]:
+ """
+ Create the complete OpenAPI schema.
+
+ Returns:
+ Dict[str, Any]: Complete OpenAPI schema
+ """
+ openapi_schema = get_openapi(
+ title=ApiConfig.TITLE,
+ description=ApiConfig.DESCRIPTION,
+ version="1.1.1",
+ routes=self.app.routes,
+ )
+
+ # Add security schemes
+ if "components" not in openapi_schema:
+ openapi_schema["components"] = {}
+
+ openapi_schema["components"]["securitySchemes"] = self._create_security_schemes()
+
+ # Configure route security and responses
+ for route in self.app.routes:
+ if isinstance(route, APIRoute) and route.include_in_schema:
+ path = str(route.path)
+ methods = [method.lower() for method in route.methods]
+ for method in methods:
+ self.configure_route_security(path, method, openapi_schema)
+
+ # Add custom documentation extensions
+ openapi_schema["x-documentation"] = {
+ "postman_collection": "/docs/postman",
+ "swagger_ui": "/docs",
+ "redoc": "/redoc",
+ }
+ return openapi_schema
+
+
+def create_openapi_schema(app: FastAPI) -> Dict[str, Any]:
+ """
+ Create OpenAPI schema for a FastAPI application.
+
+ Args:
+ app: FastAPI application instance
+
+ Returns:
+ Dict[str, Any]: Complete OpenAPI schema
+ """
+ creator = OpenAPISchemaCreator(app)
+ return creator.create_schema()
diff --git a/DockerApiServices/InitServiceApi/Dockerfile b/DockerApiServices/InitServiceApi/Dockerfile
new file mode 100644
index 0000000..36f3401
--- /dev/null
+++ b/DockerApiServices/InitServiceApi/Dockerfile
@@ -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"]
diff --git a/DockerApiServices/ValidationServiceApi/Dockerfile b/DockerApiServices/ValidationServiceApi/Dockerfile
index a6809dc..1fbab7f 100644
--- a/DockerApiServices/ValidationServiceApi/Dockerfile
+++ b/DockerApiServices/ValidationServiceApi/Dockerfile
@@ -19,23 +19,17 @@ RUN poetry config virtualenvs.create false \
&& rm -rf ~/.cache/pypoetry
# Copy application code
-COPY DockerApiServices/AllApiNeeds /app
-COPY ErrorHandlers /app/ErrorHandlers
-COPY LanguageModels /app/LanguageModels
-COPY ApiLibrary /app/ApiLibrary
-COPY ApiValidations /app/ApiValidations
-COPY AllConfigs /app/AllConfigs
-COPY ErrorHandlers /app/ErrorHandlers
-COPY Schemas /app/Schemas
-COPY Services /app/Services
-COPY ApiServices /app/ApiServices
+COPY DockerApiServices/ValidationServiceApi /app
-# Copy Events structure with consistent naming
-COPY ApiEvents/ValidationServiceApi /app/ApiEvents
-ADD ApiEvents/AuthServiceApi/events /app/ApiEvents/events
-ADD ApiEvents/EventServiceApi/events /app/ApiEvents/events
-COPY ApiEvents/abstract_class.py /app/ApiEvents/abstract_class.py
-COPY ApiEvents/base_request_model.py /app/ApiEvents/base_request_model.py
+# Copy application code
+COPY ApiLayers /app/ApiLayers
+COPY Services /app/Services
+
+# Events
+# COPY Events/base_request_model.py /app/Events/base_request_model.py
+COPY Events/Engine /app/Events/Engine
+COPY Events/AllEvents/validations /app/Events/AllEvents/validations
+COPY DockerApiServices/ValidationServiceApi/events_file.py /app/Events/AllEvents/events_file.py
# Set Python path to include app directory
ENV PYTHONPATH=/app \
diff --git a/DockerApiServices/ValidationServiceApi/app.py b/DockerApiServices/ValidationServiceApi/app.py
new file mode 100644
index 0000000..68ed880
--- /dev/null
+++ b/DockerApiServices/ValidationServiceApi/app.py
@@ -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()
diff --git a/DockerApiServices/ValidationServiceApi/app_handler.py b/DockerApiServices/ValidationServiceApi/app_handler.py
new file mode 100644
index 0000000..3156e6a
--- /dev/null
+++ b/DockerApiServices/ValidationServiceApi/app_handler.py
@@ -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)
diff --git a/DockerApiServices/ValidationServiceApi/config.py b/DockerApiServices/ValidationServiceApi/config.py
new file mode 100644
index 0000000..dfbf1eb
--- /dev/null
+++ b/DockerApiServices/ValidationServiceApi/config.py
@@ -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
+
diff --git a/DockerApiServices/ValidationServiceApi/create_file.py b/DockerApiServices/ValidationServiceApi/create_file.py
new file mode 100644
index 0000000..0e18791
--- /dev/null
+++ b/DockerApiServices/ValidationServiceApi/create_file.py
@@ -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
diff --git a/DockerApiServices/ValidationServiceApi/create_routes.py b/DockerApiServices/ValidationServiceApi/create_routes.py
new file mode 100644
index 0000000..8006964
--- /dev/null
+++ b/DockerApiServices/ValidationServiceApi/create_routes.py
@@ -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
+
+
diff --git a/DockerApiServices/ValidationServiceApi/events_file.py b/DockerApiServices/ValidationServiceApi/events_file.py
new file mode 100644
index 0000000..d15b914
--- /dev/null
+++ b/DockerApiServices/ValidationServiceApi/events_file.py
@@ -0,0 +1,3 @@
+import Events.AllEvents.validations as validations_events
+
+events_list = (validations_events,)
diff --git a/DockerApiServices/ValidationServiceApi/open_api_creator.py b/DockerApiServices/ValidationServiceApi/open_api_creator.py
new file mode 100644
index 0000000..01a37c6
--- /dev/null
+++ b/DockerApiServices/ValidationServiceApi/open_api_creator.py
@@ -0,0 +1,249 @@
+"""
+OpenAPI Schema Creator Module
+
+This module provides functionality to create and customize OpenAPI documentation:
+- Custom security schemes (Bearer Auth, API Key)
+- Response schemas and examples
+- Tag management and descriptions
+- Error responses and validation
+- Custom documentation extensions
+"""
+
+from typing import Any, Dict
+from fastapi import FastAPI
+from fastapi.routing import APIRoute
+from fastapi.openapi.utils import get_openapi
+
+from create_routes import get_all_routers
+from config import ApiConfig
+
+
+class OpenAPISchemaCreator:
+ """
+ OpenAPI schema creator and customizer for FastAPI applications.
+ """
+
+ def __init__(self, app: FastAPI):
+ """
+ Initialize the OpenAPI schema creator.
+
+ Args:
+ app: FastAPI application instance
+ """
+ self.app = app
+ self.cluster = get_all_routers()
+ self.safe_endpoint_list = self.cluster.safe_endpoints if hasattr(self.cluster, 'safe_endpoints') else []
+
+ def _create_security_schemes(self) -> Dict[str, Any]:
+ """
+ Create security scheme definitions.
+
+ Returns:
+ Dict[str, Any]: Security scheme configurations
+ """
+ from ApiLayers.AllConfigs.Token.config import Auth
+ return {
+ "BearerAuth": {
+ "type": "apiKey",
+ "in": "header",
+ "name": Auth.ACCESS_TOKEN_TAG,
+ "description": "Enter: **'Bearer <JWT>'**, where JWT is the access token",
+ }
+ }
+
+ def _create_common_responses(self) -> Dict[str, Any]:
+ """
+ Create common response schemas.
+
+ Returns:
+ Dict[str, Any]: Common response configurations
+ """
+ return {
+ "401": {
+ "description": "Unauthorized - Invalid or missing credentials",
+ "content": {
+ "application/json": {
+ "schema": {"$ref": "#/components/schemas/HTTPValidationError"}
+ }
+ },
+ },
+ "403": {
+ "description": "Forbidden - Insufficient permissions",
+ "content": {
+ "application/json": {
+ "schema": {"$ref": "#/components/schemas/HTTPValidationError"}
+ }
+ },
+ },
+ "422": {
+ "description": "Validation Error",
+ "content": {
+ "application/json": {
+ "schema": {"$ref": "#/components/schemas/HTTPValidationError"}
+ }
+ },
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "detail": {"type": "string"},
+ "error_code": {"type": "string"},
+ },
+ },
+ "example": {
+ "detail": "Internal server error occurred",
+ "error_code": "INTERNAL_ERROR",
+ },
+ }
+ },
+ },
+ }
+
+ def _process_request_body(
+ self, path: str, method: str, schema: Dict[str, Any]
+ ) -> None:
+ """
+ Process request body to include examples from model config.
+
+ Args:
+ path: Route path
+ method: HTTP method
+ schema: OpenAPI schema to modify
+ """
+ try:
+ route_schema = schema["paths"][path][method]
+ if "requestBody" in route_schema:
+ request_body = route_schema["requestBody"]
+ if "content" in request_body:
+ content = request_body["content"]
+ if "application/json" in content:
+ json_content = content["application/json"]
+ if (
+ "schema" in json_content
+ and "$ref" in json_content["schema"]
+ ):
+ ref = json_content["schema"]["$ref"]
+ model_name = ref.split("/")[-1]
+ if model_name in schema["components"]["schemas"]:
+ model_schema = schema["components"]["schemas"][
+ model_name
+ ]
+ if "example" in model_schema:
+ json_content["example"] = model_schema["example"]
+ except KeyError:
+ pass
+
+ def _process_response_examples(
+ self, path: str, method: str, schema: Dict[str, Any]
+ ) -> None:
+ """
+ Process response body to include examples from model config.
+
+ Args:
+ path: Route path
+ method: HTTP method
+ schema: OpenAPI schema to modify
+ """
+ try:
+ route_schema = schema["paths"][path][method]
+ if "responses" in route_schema:
+ responses = route_schema["responses"]
+ if "200" in responses:
+ response = responses["200"]
+ if "content" in response:
+ content = response["content"]
+ if "application/json" in content:
+ json_content = content["application/json"]
+ if (
+ "schema" in json_content
+ and "$ref" in json_content["schema"]
+ ):
+ ref = json_content["schema"]["$ref"]
+ model_name = ref.split("/")[-1]
+ if model_name in schema["components"]["schemas"]:
+ model_schema = schema["components"]["schemas"][
+ model_name
+ ]
+ if "example" in model_schema:
+ json_content["example"] = model_schema[
+ "example"
+ ]
+ except KeyError:
+ pass
+
+ def configure_route_security(
+ self, path: str, method: str, schema: Dict[str, Any]
+ ) -> None:
+ """
+ Configure security requirements for a specific route.
+
+ Args:
+ path: Route path
+ method: HTTP method
+ schema: OpenAPI schema to modify
+ """
+ if not schema.get("paths", {}).get(path, {}).get(method):
+ return
+
+ # Check if endpoint is in safe list
+ endpoint_path = f"{path}:{method}"
+ if endpoint_path not in [f"{e.URL}:{e.METHOD.lower()}" for e in self.safe_endpoint_list]:
+ if "security" not in schema["paths"][path][method]:
+ schema["paths"][path][method]["security"] = []
+ schema["paths"][path][method]["security"].append(
+ {"BearerAuth": []}
+ )
+
+ def create_schema(self) -> Dict[str, Any]:
+ """
+ Create the complete OpenAPI schema.
+
+ Returns:
+ Dict[str, Any]: Complete OpenAPI schema
+ """
+ openapi_schema = get_openapi(
+ title=ApiConfig.TITLE,
+ description=ApiConfig.DESCRIPTION,
+ version="1.1.1",
+ routes=self.app.routes,
+ )
+
+ # Add security schemes
+ if "components" not in openapi_schema:
+ openapi_schema["components"] = {}
+
+ openapi_schema["components"]["securitySchemes"] = self._create_security_schemes()
+
+ # Configure route security and responses
+ for route in self.app.routes:
+ if isinstance(route, APIRoute) and route.include_in_schema:
+ path = str(route.path)
+ methods = [method.lower() for method in route.methods]
+ for method in methods:
+ self.configure_route_security(path, method, openapi_schema)
+
+ # Add custom documentation extensions
+ openapi_schema["x-documentation"] = {
+ "postman_collection": "/docs/postman",
+ "swagger_ui": "/docs",
+ "redoc": "/redoc",
+ }
+ return openapi_schema
+
+
+def create_openapi_schema(app: FastAPI) -> Dict[str, Any]:
+ """
+ Create OpenAPI schema for a FastAPI application.
+
+ Args:
+ app: FastAPI application instance
+
+ Returns:
+ Dict[str, Any]: Complete OpenAPI schema
+ """
+ creator = OpenAPISchemaCreator(app)
+ return creator.create_schema()
diff --git a/Events/AllEvents/authentication/__init__.py b/Events/AllEvents/authentication/__init__.py
index 0f118e8..ad73225 100644
--- a/Events/AllEvents/authentication/__init__.py
+++ b/Events/AllEvents/authentication/__init__.py
@@ -2,8 +2,8 @@
Authentication package initialization.
"""
-from .auth import AUTH_CONFIG
+from .auth.cluster import AuthCluster
__all__ = [
- "AUTH_CONFIG",
+ "AuthCluster",
]
diff --git a/Events/AllEvents/authentication/auth/api_events.py b/Events/AllEvents/authentication/auth/api_events.py
index 4110037..de56d08 100644
--- a/Events/AllEvents/authentication/auth/api_events.py
+++ b/Events/AllEvents/authentication/auth/api_events.py
@@ -1,4 +1,3 @@
-from uuid import UUID
from Events.Engine.abstract_class import Event
from .models import (
@@ -14,8 +13,6 @@ from .models import (
from .function_handlers import (
authentication_login_with_domain_and_creds,
authentication_select_company_or_occupant_type,
- handle_employee_selection,
- handle_occupant_selection,
authentication_check_token_is_valid,
authentication_refresh_user_info,
authentication_change_password,
@@ -31,124 +28,126 @@ from .function_handlers import (
# Auth Login
authentication_login_super_user_event = Event(
- key=UUID("a5d2d0d1-3e9b-4b0f-8c7d-6d4a4b4c4d4e"),
+ name="authentication_login_super_user_event",
+ key="a5d2d0d1-3e9b-4b0f-8c7d-6d4a4b4c4d4e",
request_validator=LoginSuperUserRequestModel,
- response_validator=LoginSuperUserResponseModel,
+ # response_validator=LoginSuperUserResponseModel,
description="Login super user",
)
-authentication_login_super_user_event.endpoint_callable = authentication_login_with_domain_and_creds
+authentication_login_super_user_event.endpoint_callable = (
+ authentication_login_with_domain_and_creds
+)
# Auth Select Company or Occupant Type
authentication_select_company_or_occupant_type_super_user_event = Event(
- key=UUID("a5d2d0d1-3e9b-4b0f-8c7d-6d4a4b4c4d4e"),
+ name="authentication_select_company_or_occupant_type_super_user_event",
+ key="a5d2d0d1-3e9b-4b0f-8c7d-6d4a4b4c4d4e",
request_validator=SelectCompanyOrOccupantTypeSuperUserRequestModel,
- response_validator=SelectCompanyOrOccupantTypeSuperUserResponseModel,
+ # response_validator=SelectCompanyOrOccupantTypeSuperUserResponseModel,
description="Select company or occupant type super user",
)
-authentication_select_company_or_occupant_type_super_user_event.endpoint_callable = authentication_select_company_or_occupant_type
-
-authentication_employee_selection_super_user_event = Event(
- key=UUID("a5d2d0d1-3e9b-4b0f-8c7d-6d4a4b4c4d4e"),
- request_validator=EmployeeSelectionSuperUserRequestModel,
- response_validator=EmployeeSelectionSuperUserResponseModel,
- description="Employee selection super user",
+authentication_select_company_or_occupant_type_super_user_event.endpoint_callable = (
+ authentication_select_company_or_occupant_type
)
-authentication_employee_selection_super_user_event.endpoint_callable = handle_employee_selection
-
-authentication_occupant_selection_super_user_event = Event(
- key=UUID("a5d2d0d1-3e9b-4b0f-8c7d-6d4a4b4c4d4e"),
- request_validator=OccupantSelectionSuperUserRequestModel,
- response_validator=OccupantSelectionSuperUserResponseModel,
- description="Occupant selection super user",
-)
-authentication_occupant_selection_super_user_event.endpoint_callable = handle_occupant_selection
# Check Token Validity
authentication_check_token_event = Event(
- key=UUID("b6e3d1e2-4f9c-5c1g-9d8e-7e5f6f5e5d5f"),
+ name="authentication_check_token_event",
+ key="b6e3d1e2-4f9c-5c1g-9d8e-7e5f6f5e5d5f",
request_validator=None, # TODO: Add request validator
- response_validator=None, # TODO: Add response validator
+ # response_validator=None, # TODO: Add response validator
description="Check if token is valid",
)
authentication_check_token_event.endpoint_callable = authentication_check_token_is_valid
# Refresh User Info
authentication_refresh_user_info_event = Event(
- key=UUID("c7f4e2f3-5g0d-6d2h-0e9f-8f6g7g6f6e6g"),
+ name="authentication_refresh_user_info_event",
+ key="c7f4e2f3-5g0d-6d2h-0e9f-8f6g7g6f6e6g",
request_validator=None, # TODO: Add request validator
- response_validator=None, # TODO: Add response validator
+ # response_validator=None, # TODO: Add response validator
description="Refresh user information",
)
-authentication_refresh_user_info_event.endpoint_callable = authentication_refresh_user_info
+authentication_refresh_user_info_event.endpoint_callable = (
+ authentication_refresh_user_info
+)
# Change Password
authentication_change_password_event = Event(
- key=UUID("d8g5f3g4-6h1e-7e3i-1f0g-9g7h8h7g7f7h"),
+ name="authentication_change_password_event",
+ key="d8g5f3g4-6h1e-7e3i-1f0g-9g7h8h7g7f7h",
request_validator=None, # TODO: Add request validator
- response_validator=None, # TODO: Add response validator
+ # response_validator=None, # TODO: Add response validator
description="Change user password",
)
authentication_change_password_event.endpoint_callable = authentication_change_password
# Create Password
authentication_create_password_event = Event(
- key=UUID("e9h6g4h5-7i2f-8f4j-2g1h-0h8i9i8h8g8i"),
+ name="authentication_create_password_event",
+ key="e9h6g4h5-7i2f-8f4j-2g1h-0h8i9i8h8g8i",
request_validator=None, # TODO: Add request validator
- response_validator=None, # TODO: Add response validator
+ # response_validator=None, # TODO: Add response validator
description="Create new password",
)
authentication_create_password_event.endpoint_callable = authentication_create_password
# Disconnect User
authentication_disconnect_user_event = Event(
- key=UUID("f0i7h5i6-8j3g-9g5k-3h2i-1i9j0j9i9h9j"),
+ name="authentication_disconnect_user_event",
+ key="f0i7h5i6-8j3g-9g5k-3h2i-1i9j0j9i9h9j",
request_validator=None, # TODO: Add request validator
- response_validator=None, # TODO: Add response validator
+ # response_validator=None, # TODO: Add response validator
description="Disconnect all user sessions",
)
authentication_disconnect_user_event.endpoint_callable = authentication_disconnect_user
# Logout User
authentication_logout_user_event = Event(
- key=UUID("g1j8i6j7-9k4h-0h6l-4i3j-2j0k1k0j0i0k"),
+ name="authentication_logout_user_event",
+ key="g1j8i6j7-9k4h-0h6l-4i3j-2j0k1k0j0i0k",
request_validator=None, # TODO: Add request validator
- response_validator=None, # TODO: Add response validator
+ # response_validator=None, # TODO: Add response validator
description="Logout user session",
)
authentication_logout_user_event.endpoint_callable = authentication_logout_user
# Refresh Token
authentication_refresher_token_event = Event(
- key=UUID("h2k9j7k8-0l5i-1i7m-5j4k-3k1l2l1k1j1l"),
+ name="authentication_refresher_token_event",
+ key="h2k9j7k8-0l5i-1i7m-5j4k-3k1l2l1k1j1l",
request_validator=None, # TODO: Add request validator
- response_validator=None, # TODO: Add response validator
+ # response_validator=None, # TODO: Add response validator
description="Refresh authentication token",
)
authentication_refresher_token_event.endpoint_callable = authentication_refresher_token
# Forgot Password
authentication_forgot_password_event = Event(
- key=UUID("i3l0k8l9-1m6j-2j8n-6k5l-4l2m3m2l2k2m"),
+ name="authentication_forgot_password_event",
+ key="i3l0k8l9-1m6j-2j8n-6k5l-4l2m3m2l2k2m",
request_validator=None, # TODO: Add request validator
- response_validator=None, # TODO: Add response validator
+ # response_validator=None, # TODO: Add response validator
description="Request password reset",
)
authentication_forgot_password_event.endpoint_callable = authentication_forgot_password
# Reset Password
authentication_reset_password_event = Event(
- key=UUID("j4m1l9m0-2n7k-3k9o-7l6m-5m3n4n3m3l3n"),
+ name="authentication_reset_password_event",
+ key="j4m1l9m0-2n7k-3k9o-7l6m-5m3n4n3m3l3n",
request_validator=None, # TODO: Add request validator
- response_validator=None, # TODO: Add response validator
+ # response_validator=None, # TODO: Add response validator
description="Reset user password",
)
authentication_reset_password_event.endpoint_callable = authentication_reset_password
# Download Avatar
authentication_download_avatar_event = Event(
- key=UUID("k5n2m0n1-3o8l-4l0p-8m7n-6n4o5o4n4m4o"),
+ name="authentication_download_avatar_event",
+ key="k5n2m0n1-3o8l-4l0p-8m7n-6n4o5o4n4m4o",
request_validator=None, # TODO: Add request validator
- response_validator=None, # TODO: Add response validator
+ # response_validator=None, # TODO: Add response validator
description="Download user avatar and profile info",
)
authentication_download_avatar_event.endpoint_callable = authentication_download_avatar
diff --git a/Events/AllEvents/authentication/auth/auth.py b/Events/AllEvents/authentication/auth/auth.py
index 8ed30f0..0e8f680 100644
--- a/Events/AllEvents/authentication/auth/auth.py
+++ b/Events/AllEvents/authentication/auth/auth.py
@@ -2,19 +2,17 @@
Authentication related API endpoints.
"""
-from typing import Union
+from typing import Union, Any, Dict
+
+from ApiLayers.Middleware import MiddlewareModule, TokenEventMiddleware
+from ApiLayers.ApiValidations.Request import EmployeeSelection, OccupantSelection
from Events.Engine.abstract_class import MethodToEvent
-from Events.base_request_model import SuccessResponse
-
-from ApiLayers.ApiLibrary.common.line_number import get_line_number_for_error
-from ApiLayers.ApiServices.Token.token_handler import OccupantTokenObject, EmployeeTokenObject
+from Events.base_request_model import EndpointBaseRequestModel
from .api_events import (
authentication_login_super_user_event,
authentication_select_company_or_occupant_type_super_user_event,
- authentication_employee_selection_super_user_event,
- authentication_occupant_selection_super_user_event,
authentication_check_token_event,
authentication_refresh_user_info_event,
authentication_change_password_event,
@@ -27,13 +25,18 @@ from .api_events import (
authentication_download_avatar_event,
)
+from fastapi import Request
+
# Type aliases for common types
TokenDictType = Union["EmployeeTokenObject", "OccupantTokenObject"]
AuthenticationLoginEventMethods = MethodToEvent(
- events=[authentication_login_super_user_event],
+ name="AuthenticationLoginEventMethods",
+ events={
+ authentication_login_super_user_event.key: authentication_login_super_user_event,
+ },
headers=[],
errors=[],
url="/authentication/login",
@@ -42,13 +45,24 @@ AuthenticationLoginEventMethods = MethodToEvent(
description="Login to the system via domain, access key : [email] | [phone]",
)
+def authentication_login_with_domain_and_creds(
+ request: Request,
+ data: EndpointBaseRequestModel,
+) -> Dict[str, Any]:
+ function = AuthenticationLoginEventMethods.retrieve_event(
+ event_function_code=f"{authentication_login_super_user_event.key}"
+ )
+ return function.endpoint_callable(request=request, data=data)
+
+
+AuthenticationLoginEventMethods.endpoint_callable = authentication_login_with_domain_and_creds
AuthenticationSelectEventMethods = MethodToEvent(
- events=[
- authentication_select_company_or_occupant_type_super_user_event,
- authentication_employee_selection_super_user_event,
- authentication_occupant_selection_super_user_event
- ],
+ name="AuthenticationSelectEventMethods",
+ events={
+ authentication_select_company_or_occupant_type_super_user_event.key: authentication_select_company_or_occupant_type_super_user_event,
+ },
+ decorators_list=[MiddlewareModule.auth_required],
headers=[],
errors=[],
url="/authentication/select",
@@ -57,22 +71,53 @@ AuthenticationSelectEventMethods = MethodToEvent(
description="Select company or occupant type",
)
+def authentication_select_company_or_occupant_type(
+ request: Request,
+ data: EndpointBaseRequestModel,
+) -> Dict[str, Any]:
+ """
+ Select company or occupant type.
+ """
+ auth_dict = authentication_select_company_or_occupant_type.auth
+ function = AuthenticationSelectEventMethods.retrieve_event(
+ event_function_code=f"{authentication_select_company_or_occupant_type_super_user_event.key}"
+ )
+ return function.endpoint_callable(request=request, data=data, token_dict=auth_dict)
+
+
+AuthenticationSelectEventMethods.endpoint_callable = authentication_select_company_or_occupant_type
AuthenticationCheckTokenEventMethods = MethodToEvent(
- events=[authentication_check_token_event],
+ name="AuthenticationCheckTokenEventMethods",
+ events={
+ authentication_check_token_event.key: authentication_check_token_event
+ },
headers=[],
errors=[],
+ decorators_list=[MiddlewareModule.auth_required],
url="/authentication/check-token",
method="POST",
summary="Check if token is valid",
description="Check if access token is valid for user",
)
+def authentication_check_token_is_valid(request: Request):
+ function = AuthenticationCheckTokenEventMethods.retrieve_event(
+ event_function_code=f"{authentication_check_token_event.key}"
+ )
+ return function.endpoint_callable(request=request)
+
+
+AuthenticationCheckTokenEventMethods.endpoint_callable = authentication_check_token_is_valid
AuthenticationRefreshEventMethods = MethodToEvent(
- events=[authentication_refresh_user_info_event],
+ name="AuthenticationRefreshEventMethods",
+ events={
+ authentication_refresh_user_info_event.key: authentication_refresh_user_info_event
+ },
headers=[],
errors=[],
+ decorators_list=[MiddlewareModule.auth_required],
url="/authentication/refresh",
method="POST",
summary="Refresh user info",
@@ -80,19 +125,45 @@ AuthenticationRefreshEventMethods = MethodToEvent(
)
+def authentication_refresh_user_info(request: Request):
+ token_dict = authentication_refresh_user_info.auth
+ function = AuthenticationRefreshEventMethods.retrieve_event(
+ event_function_code=f"{authentication_refresh_user_info_event.key}"
+ )
+ return function.endpoint_callable(request=request, token_dict=token_dict)
+
+
+AuthenticationRefreshEventMethods.endpoint_callable = authentication_refresh_user_info
+
AuthenticationChangePasswordEventMethods = MethodToEvent(
- events=[authentication_change_password_event],
+ name="AuthenticationChangePasswordEventMethods",
+ events={
+ authentication_change_password_event.key: authentication_change_password_event
+ },
headers=[],
errors=[],
+ decorators_list=[MiddlewareModule.auth_required],
url="/authentication/change-password",
method="POST",
summary="Change password",
description="Change password with access token",
)
+def authentication_change_password_event_callable(request: Request, data: EndpointBaseRequestModel):
+ token_dict = authentication_change_password_event_callable.auth
+ function = AuthenticationChangePasswordEventMethods.retrieve_event(
+ event_function_code=f"{authentication_change_password_event.key}"
+ )
+ return function.endpoint_callable(data=data, token_dict=token_dict)
+
+
+AuthenticationChangePasswordEventMethods.endpoint_callable = authentication_change_password_event_callable
AuthenticationCreatePasswordEventMethods = MethodToEvent(
- events=[authentication_create_password_event],
+ name="AuthenticationCreatePasswordEventMethods",
+ events={
+ authentication_create_password_event: authentication_create_password_event
+ },
headers=[],
errors=[],
url="/authentication/create-password",
@@ -101,9 +172,21 @@ AuthenticationCreatePasswordEventMethods = MethodToEvent(
description="Create password with password reset token requested via email",
)
+def authentication_create_password(data: EndpointBaseRequestModel):
+ function = AuthenticationCreatePasswordEventMethods.retrieve_event(
+ event_function_code=f"{authentication_create_password_event.key}"
+ )
+ return function.endpoint_callable(data=data)
+
+
+AuthenticationCreatePasswordEventMethods.endpoint_callable = authentication_create_password
AuthenticationDisconnectUserEventMethods = MethodToEvent(
- events=[authentication_disconnect_user_event],
+ name="AuthenticationDisconnectUserEventMethods",
+ events={
+ authentication_disconnect_user_event.key: authentication_disconnect_user_event
+ },
+ decorators_list=[MiddlewareModule.auth_required],
headers=[],
errors=[],
url="/authentication/disconnect",
@@ -112,9 +195,19 @@ AuthenticationDisconnectUserEventMethods = MethodToEvent(
description="Disconnect all sessions of user in access token",
)
+def authentication_disconnect_user(request: Request, data: EndpointBaseRequestModel):
+ token_dict = authentication_disconnect_user.auth
+ function = AuthenticationDisconnectUserEventMethods.retrieve_event(
+ event_function_code=f"{authentication_disconnect_user_event.key}"
+ )
+ return function.endpoint_callable(data=data, token_dict=token_dict)
+
AuthenticationLogoutEventMethods = MethodToEvent(
- events=[authentication_logout_user_event],
+ name="AuthenticationLogoutEventMethods",
+ events={
+ authentication_logout_user_event.key: authentication_logout_user_event
+ },
headers=[],
errors=[],
url="/authentication/logout",
@@ -123,20 +216,51 @@ AuthenticationLogoutEventMethods = MethodToEvent(
description="Logout only single session of user which domain is provided",
)
+@TokenEventMiddleware.event_required
+def authentication_logout_user(request: Request, data: EndpointBaseRequestModel):
+ function = AuthenticationLogoutEventMethods.retrieve_event(
+ event_function_code=f"{authentication_logout_user_event.key}"
+ )
+ print('authentication_logout_user', dict(
+ auth=getattr(authentication_logout_user, "auth", None),
+ func_code=getattr(authentication_logout_user, "func_code", None),
+ ))
+ function.endpoint_callable.auth = getattr(authentication_logout_user, "auth", None)
+ function.endpoint_callable.func_code = getattr(authentication_logout_user, "func_code", None)
+ return function.endpoint_callable(request=request, data=data)
+
+
+AuthenticationLogoutEventMethods.endpoint_callable = authentication_logout_user
AuthenticationRefreshTokenEventMethods = MethodToEvent(
- events=[authentication_refresher_token_event],
+ name="AuthenticationRefreshTokenEventMethods",
+ events={
+ authentication_refresher_token_event.key: authentication_refresher_token_event
+ },
headers=[],
errors=[],
+ decorators_list=[MiddlewareModule.auth_required, ],
url="/authentication/refresh-token",
method="POST",
summary="Refresh token",
description="Refresh access token with refresher token",
)
+def authentication_refresher_token(request: Request, data: EndpointBaseRequestModel):
+ token_dict = authentication_refresher_token.auth
+ function = AuthenticationRefreshTokenEventMethods.retrieve_event(
+ event_function_code=f"{authentication_refresher_token_event.key}"
+ )
+ return function.endpoint_callable(data=data, request=request, token_dict=token_dict)
+
+AuthenticationRefreshTokenEventMethods.endpoint_callable = authentication_refresher_token
+
AuthenticationForgotPasswordEventMethods = MethodToEvent(
- events=[authentication_forgot_password_event],
+ name="AuthenticationForgotPasswordEventMethods",
+ events={
+ authentication_forgot_password_event.key: authentication_forgot_password_event
+ },
headers=[],
errors=[],
url="/authentication/forgot-password",
@@ -146,10 +270,25 @@ AuthenticationForgotPasswordEventMethods = MethodToEvent(
)
+def authentication_forgot_password(request: Request, data: EndpointBaseRequestModel):
+ token_dict = authentication_forgot_password.auth
+ function = AuthenticationForgotPasswordEventMethods.retrieve_event(
+ event_function_code=f"{authentication_forgot_password_event.key}"
+ )
+ return function.endpoint_callable(data=data, token_dict=token_dict)
+
+
+AuthenticationForgotPasswordEventMethods.endpoint_callable = authentication_forgot_password
+
+
AuthenticationResetPasswordEventMethods = MethodToEvent(
- events=[authentication_reset_password_event],
+ name="AuthenticationResetPasswordEventMethods",
+ events={
+ authentication_reset_password_event.key: authentication_reset_password_event
+ },
headers=[],
errors=[],
+ decorators_list=[MiddlewareModule.auth_required],
url="/authentication/reset-password",
method="POST",
summary="Reset password",
@@ -157,12 +296,38 @@ AuthenticationResetPasswordEventMethods = MethodToEvent(
)
+def authentication_reset_password(data: EndpointBaseRequestModel):
+ # token_dict = authentication_reset_password.auth
+ function = AuthenticationResetPasswordEventMethods.retrieve_event(
+ event_function_code=f"{authentication_reset_password_event.key}"
+ )
+ return function.endpoint_callable(data=data)
+
+
+AuthenticationResetPasswordEventMethods.endpoint_callable = authentication_reset_password
+
AuthenticationDownloadAvatarEventMethods = MethodToEvent(
- events=[authentication_download_avatar_event],
+ name="AuthenticationDownloadAvatarEventMethods",
+ events={
+ authentication_download_avatar_event.key: authentication_download_avatar_event
+ },
headers=[],
errors=[],
+ decorators_list=[],
url="/authentication/download-avatar",
method="POST",
summary="Download avatar",
description="Download avatar icon and profile info of user",
)
+
+
+@MiddlewareModule.auth_required
+def authentication_download_avatar(request: Request):
+ token_dict = authentication_download_avatar.auth
+ function = AuthenticationDownloadAvatarEventMethods.retrieve_event(
+ event_function_code=f"{authentication_download_avatar_event.key}"
+ )
+ return function.endpoint_callable(token_dict=token_dict)
+
+
+AuthenticationDownloadAvatarEventMethods.endpoint_callable = authentication_download_avatar
diff --git a/Events/AllEvents/authentication/auth/cluster.py b/Events/AllEvents/authentication/auth/cluster.py
index 7052ccf..7846a2a 100644
--- a/Events/AllEvents/authentication/auth/cluster.py
+++ b/Events/AllEvents/authentication/auth/cluster.py
@@ -18,6 +18,7 @@ from .auth import (
AuthCluster = CategoryCluster(
+ name="AuthCluster",
tags=["authentication"],
prefix="/authentication",
description="Authentication cluster",
diff --git a/Events/AllEvents/authentication/auth/function_handlers.py b/Events/AllEvents/authentication/auth/function_handlers.py
index af895d4..4aa71f9 100644
--- a/Events/AllEvents/authentication/auth/function_handlers.py
+++ b/Events/AllEvents/authentication/auth/function_handlers.py
@@ -1,12 +1,6 @@
-from typing import Any, TYPE_CHECKING, Union
-
-from Events.base_request_model import TokenDictType
-from Events.Engine.abstract_class import MethodToEvent
-from Events.base_request_model import SuccessResponse
+from typing import Any, TYPE_CHECKING, Union, Dict
from ApiLayers.ApiLibrary.common.line_number import get_line_number_for_error
-from ApiLayers.ApiLibrary.date_time_actions.date_functions import DateTimeLocal
-from ApiLayers.ApiServices.middleware.auth_middleware import AuthMiddlewareModule
from ApiLayers.ApiServices.Login.user_login_handler import UserLoginModule
from ApiLayers.ApiServices.Token.token_handler import TokenService
@@ -17,20 +11,17 @@ from ApiLayers.Schemas import (
BuildParts,
RelationshipEmployee2Build,
Companies,
- Departments,
- Duties,
+ Departments,
+ Duties,
Duty,
Staff,
Employees,
Event2Employee,
Event2Occupant,
OccupantTypes,
- Users
+ Users,
)
-from ApiLayers.ApiServices.Token.token_handler import OccupantTokenObject, EmployeeTokenObject
-
-if TYPE_CHECKING:
- from fastapi import Request
+from fastapi import Request
# Type aliases for common types
@@ -70,7 +61,7 @@ def authentication_login_with_domain_and_creds(request: Request, data: Any):
"user": token.get("user"),
}
-@AuthMiddlewareModule.auth_required
+
def handle_employee_selection(request: Request, data: Any, token_dict: TokenDictType):
Users.set_user_define_properties(token=token_dict)
db_session = Users.new_session()
@@ -185,7 +176,6 @@ def handle_employee_selection(request: Request, data: Any, token_dict: TokenDict
)
-@AuthMiddlewareModule.auth_required
def handle_occupant_selection(request: Request, data: Any, token_dict: TokenDictType):
"""Handle occupant type selection"""
db = BuildLivingSpace.new_session()
@@ -270,17 +260,20 @@ def handle_occupant_selection(request: Request, data: Any, token_dict: TokenDict
)
-@AuthMiddlewareModule.auth_required
def authentication_select_company_or_occupant_type(request: Request, data: Any, token_dict: TokenDictType):
"""Handle selection of company or occupant type"""
if token_dict.is_employee:
- return cls._handle_employee_selection(data, token_dict, request)
+ if handle_employee_selection(data, token_dict, request):
+ return {"selected_occupant": None, "selected_company": data.company_uu_id}
elif token_dict.is_occupant:
- return cls._handle_occupant_selection(data, token_dict, request)
+ if handle_occupant_selection(data, token_dict, request):
+ return {
+ "selected_company": None, "selected_occupant": data.build_living_space_uu_id,
+ }
+ return {"completed": False, "selected_company": None, "selected_occupant": None}
-@AuthMiddlewareModule.auth_required
-def authentication_check_token_is_valid(request: "Request", data: Any):
+def authentication_check_token_is_valid(request: Request, data: Any):
"""Check if token is valid for user"""
# try:
# if RedisActions.get_object_via_access_key(request=request):
@@ -290,8 +283,7 @@ def authentication_check_token_is_valid(request: "Request", data: Any):
return
-@AuthMiddlewareModule.auth_required
-def authentication_refresh_user_info(request: "Request", token_dict: TokenDictType, data: Any):
+def authentication_refresh_user_info(request: Request, token_dict: TokenDictType, data: Any):
"""Refresh user info using access token"""
# try:
# access_token = request.headers.get(Auth.ACCESS_TOKEN_TAG)
@@ -320,8 +312,7 @@ def authentication_refresh_user_info(request: "Request", token_dict: TokenDictTy
return
-@AuthMiddlewareModule.auth_required
-def authentication_change_password(request: "Request", token_dict: TokenDictType, data: Any):
+def authentication_change_password(request: Request, token_dict: TokenDictType, data: Any):
"""Change password with access token"""
# try:
# if not isinstance(token_dict, EmployeeTokenObject):
@@ -341,7 +332,7 @@ def authentication_change_password(request: "Request", token_dict: TokenDictType
return
-def authentication_create_password(request: "Request", data: Any):
+def authentication_create_password(request: Request, data: Any):
"""Create password with password reset token requested via email"""
# if not data.re_password == data.password:
# raise HTTPException(status_code=status.HTTP_406_NOT_ACCEPTABLE, detail="Password must match")
@@ -354,8 +345,7 @@ def authentication_create_password(request: "Request", data: Any):
return
-@AuthMiddlewareModule.auth_required
-def authentication_disconnect_user(request: "Request", token_dict: TokenDictType, data: Any):
+def authentication_disconnect_user(request: Request, token_dict: TokenDictType, data: Any):
"""Disconnect all sessions of user in access token"""
# found_user = Users.filter_one(Users.uu_id == token_dict.user_uu_id).data
# if not found_user:
@@ -370,7 +360,7 @@ def authentication_disconnect_user(request: "Request", token_dict: TokenDictType
return
-def authentication_logout_user(request: "Request", data: Any, token_dict: TokenDictType):
+def authentication_logout_user(request: Request, data: Any):
"""Logout only single session of user which domain is provided"""
# token_user = None
# if already_tokens := RedisActions.get_object_via_access_key(request=request):
@@ -382,11 +372,14 @@ def authentication_logout_user(request: "Request", data: Any, token_dict: TokenD
# selected_user.remove_refresher_token(domain=data.domain)
# return ResponseHandler.success("Session is logged out", data=token_user)
# return ResponseHandler.not_found("Logout is not successfully completed")
+ token_dict = authentication_logout_user.auth
+ print('token_dict', token_dict)
+ func_code = authentication_logout_user.func_code
+ print('func_code', func_code)
return
-@AuthMiddlewareModule.auth_required
-def authentication_refresher_token(request: "Request", token_dict: TokenDictType, data: Any):
+def authentication_refresher_token(request: Request, token_dict: TokenDictType, data: Any):
"""Refresh access token with refresher token"""
# token_refresher = UsersTokens.filter_by_one(
# token=data.refresh_token,
@@ -412,7 +405,7 @@ def authentication_refresher_token(request: "Request", token_dict: TokenDictType
return
-def authentication_forgot_password(request: "Request", data: Any):
+def authentication_forgot_password(request: Request, data: Any):
"""Send an email to user for a valid password reset token"""
# found_user: Users = Users.check_user_exits(access_key=data.access_key, domain=data.domain)
# forgot_key = AuthActions.save_access_token_to_redis(request=request, found_user=found_user, domain=data.domain)
@@ -431,8 +424,7 @@ def authentication_forgot_password(request: "Request", data: Any):
return
-@AuthMiddlewareModule.auth_required
-def authentication_reset_password(request: "Request", data: Any):
+def authentication_reset_password(request: Request, data: Any):
"""Reset password with forgot password token"""
# from sqlalchemy import or_
# found_user = Users.query.filter(
@@ -461,8 +453,7 @@ def authentication_reset_password(request: "Request", data: Any):
return
-@AuthMiddlewareModule.auth_required
-def authentication_download_avatar(request: "Request", data: Any, token_dict: TokenDictType):
+def authentication_download_avatar(request: Request, data: Any, token_dict: TokenDictType):
"""Download avatar icon and profile info of user"""
# if found_user := Users.filter_one(Users.id == token_dict.user_id).data:
# expired_starts = str(system_arrow.now() - system_arrow.get(str(found_user.expiry_ends)))
diff --git a/Events/AllEvents/authentication/auth/info.py b/Events/AllEvents/authentication/auth/info.py
index 7d60d97..dc58175 100644
--- a/Events/AllEvents/authentication/auth/info.py
+++ b/Events/AllEvents/authentication/auth/info.py
@@ -9,5 +9,3 @@ authentication_page_info = PageInfo(
parent="",
url="",
)
-
-
diff --git a/Events/AllEvents/authentication/auth/models.py b/Events/AllEvents/authentication/auth/models.py
index 872189d..41e0a34 100644
--- a/Events/AllEvents/authentication/auth/models.py
+++ b/Events/AllEvents/authentication/auth/models.py
@@ -31,4 +31,3 @@ class OccupantSelectionSuperUserRequestModel(BaseModel):
class OccupantSelectionSuperUserResponseModel(BaseModel):
pass
-
diff --git a/Events/AllEvents/events/__init__.py b/Events/AllEvents/events/__init__.py
index e69de29..de2a4c1 100644
--- a/Events/AllEvents/events/__init__.py
+++ b/Events/AllEvents/events/__init__.py
@@ -0,0 +1,7 @@
+"""
+Events package initialization.
+"""
+
+
+__all__ = [
+]
diff --git a/Events/AllEvents/events_file.py b/Events/AllEvents/events_file.py
new file mode 100644
index 0000000..106bc8a
--- /dev/null
+++ b/Events/AllEvents/events_file.py
@@ -0,0 +1,6 @@
+import Events.AllEvents.authentication as auths_events
+import Events.AllEvents.events as events_events
+import Events.AllEvents.validations as validations_events
+
+
+events_list = (auths_events, events_events, validations_events)
diff --git a/Events/AllEvents/validations/validation/validation.py b/Events/AllEvents/validations/validation/validation.py
index e5076d6..8384857 100644
--- a/Events/AllEvents/validations/validation/validation.py
+++ b/Events/AllEvents/validations/validation/validation.py
@@ -27,6 +27,7 @@ class AllModelsImport:
AddressCreateEventMethod,
AddressSearchEventMethod,
)
+
return dict(
AccountListEventMethod=AccountListEventMethod,
AccountUpdateEventMethod=AccountUpdateEventMethod,
@@ -41,7 +42,9 @@ class AllModelsImport:
class ValidationsBoth(MethodToEvent):
@classmethod
- def retrieve_both_validations_and_headers(cls, event: ValidationsPydantic) -> Dict[str, Any]:
+ def retrieve_both_validations_and_headers(
+ cls, event: ValidationsPydantic
+ ) -> Dict[str, Any]:
EVENT_MODELS = AllModelsImport.import_all_models()
return_single_model = EVENT_MODELS.get(event.class_model, None)
# event_class_validation = getattr(return_single_model, "__event_validation__", None)
@@ -52,7 +55,9 @@ class ValidationsBoth(MethodToEvent):
loc=get_line_number_for_error(),
sys_msg="Validation code not found",
)
- response_model = return_single_model.retrieve_event_response_model(event.reachable_event_code)
+ response_model = return_single_model.retrieve_event_response_model(
+ event.reachable_event_code
+ )
language_model_all = return_single_model.retrieve_language_parameters(
function_code=event.reachable_event_code, language=event.lang
)
@@ -85,7 +90,9 @@ class ValidationsValidations(MethodToEvent):
loc=get_line_number_for_error(),
sys_msg="Validation code not found",
)
- response_model = return_single_model.retrieve_event_response_model(event.reachable_event_code)
+ response_model = return_single_model.retrieve_event_response_model(
+ event.reachable_event_code
+ )
language_model_all = return_single_model.retrieve_language_parameters(
function_code=event.reachable_event_code, language=event.lang
)
@@ -107,8 +114,7 @@ class ValidationsValidations(MethodToEvent):
class ValidationsHeaders(MethodToEvent):
@classmethod
- def retrieve_headers(cls, event: ValidationsPydantic
-) -> Dict[str, Any]:
+ def retrieve_headers(cls, event: ValidationsPydantic) -> Dict[str, Any]:
EVENT_MODELS = AllModelsImport.import_all_models()
return_single_model = EVENT_MODELS.get(event.class_model, None)
# event_class_validation = getattr(return_single_model, "__event_validation__", None)
@@ -119,7 +125,9 @@ class ValidationsHeaders(MethodToEvent):
loc=get_line_number_for_error(),
sys_msg="Validation code not found",
)
- response_model = return_single_model.retrieve_event_response_model(event.reachable_event_code)
+ response_model = return_single_model.retrieve_event_response_model(
+ event.reachable_event_code
+ )
language_model_all = return_single_model.retrieve_language_parameters(
function_code=event.reachable_event_code, language=event.lang
)
diff --git a/Events/Engine/__init__.py b/Events/Engine/__init__.py
index 8cbbe63..531e19c 100644
--- a/Events/Engine/__init__.py
+++ b/Events/Engine/__init__.py
@@ -7,15 +7,16 @@ making common utilities and base classes available for all API services.
from .abstract_class import (
MethodToEvent,
PageInfo,
- ClusterToMethod,
+ CategoryCluster,
Event,
)
+
# from .base_request_model import BaseRequestModel, DictRequestModel
# Re-export commonly used classes
__all__ = [
"MethodToEvent",
"PageInfo",
- "ClusterToMethod",
+ "CategoryCluster",
"Event",
]
diff --git a/Events/Engine/abstract_class.py b/Events/Engine/abstract_class.py
index faf11f4..7ceaf11 100644
--- a/Events/Engine/abstract_class.py
+++ b/Events/Engine/abstract_class.py
@@ -1,153 +1,8 @@
-from typing import Any, ClassVar, Dict, List, Optional
+from abc import abstractmethod
+from typing import Any, Dict, List, Optional, Callable
from uuid import UUID
-from .pageinfo import PageInfo
-
-
-class Event:
-
- KEY_: str # static string uuid.uuid4().__str__()
- RESPONSE_VALIDATOR: ClassVar["PydanticModel"]
- REQUEST_VALIDATOR: ClassVar["PydanticModel"]
- DESCRIPTION: str
- EXTRA_OPTIONS: Optional[Dict[str, Any]] = None
-
- def __init__(
- self, key: UUID, request_validator: "PydanticModel", response_validator: "PydanticModel",
- description: str, extra_options: Optional[Dict[str, Any]] = None
- ) -> None:
- self.KEY_ = key
- self.REQUEST_VALIDATOR = request_validator
- self.RESPONSE_VALIDATOR = response_validator
- self.DESCRIPTION = description
- self.EXTRA_OPTIONS = extra_options
-
- @property
- def name(self):
- return f"This is an event of {self.__class__.__name__}. Description: {self.DESCRIPTION}"
-
- @property
- def key(self):
- return str(self.KEY_)
-
- @abstractmethod
- def endpoint_callable(request: "Request", data: Any):
- """
- return cls.retrieve_event(event_function_code).retrieve_callable(token_dict, data)
- """
- pass
-
-
-class MethodToEvent:
- """
- for all endpoint callable
- def endpoint_callable(request: Request, data: PydanticModel):
- return cls.retrieve_event(event_function_code).retrieve_callable(token_dict, data)
- """
- EVENTS: list[Event]
- HEADER_LANGUAGE_MODELS: list[Dict] # [Table.__language_model__ | Dict[__language_model__]]
- ERRORS_LANGUAGE_MODELS: Optional[list[Dict]] # [Dict[ErrorCode][lang]]
-
- URL: str
- METHOD: str
- SUMMARY: str
- DESCRIPTION: str
- EXTRA_OPTIONS: Optional[Dict[str, Any]] = None
-
- def __init__(
- self,
- events: list[Event],
- headers: list[Dict],
- url: str,
- method: str,
- summary: str,
- description: str,
- errors: Optional[list[Dict]] = None,
- extra_options: Optional[Dict[str, Any]] = None,
- ):
- self.EVENTS = events
- self.URL = url
- self.METHOD = method
- self.SUMMARY = summary
- self.DESCRIPTION = description
- self.HEADER_LANGUAGE_MODELS = headers
- self.ERRORS_LANGUAGE_MODELS = errors
- self.EXTRA_OPTIONS = extra_options
-
- def retrieve_all_event_keys():
- """
- self.EVENTS.iter()
- [FUNCTION_CODE]
- """
- pass
-
- def retrieve_event(event_function_code: str):
- if list_found := [event for event in self.EVENTS if str(event.key) == event_function_code]:
- return list_found[0]
- raise ValueError(f"Event with function code {event_function_code} not found")
-
- def retrieve_redis_value() -> Dict:
- """
- Key(f"METHOD_FUNCTION_CODES:{ClusterToMethod}:MethodEvent:Endpoint") : Value([FUNCTION_CODE, ...])
- """
-
- pass
-
-
-class CategoryCluster:
-
- TAGS: list
- PREFIX: str
- PAGEINFO: PageInfo
- DESCRIPTION: str
- ENDPOINTS: list = [MethodToEvent]
- SUBCATEGORY: Optional[List["CategoryCluster"]] = []
- INCLUDE_IN_SCHEMA: Optional[bool] = True
-
- def __init__(
- self,
- tags: list,
- prefix: str,
- description: str,
- pageinfo: PageInfo,
- endpoints: list,
- sub_category: list = [],
- include_in_schema: Optional[bool] = True,
- ):
- self.TAGS = tags
- self.PREFIX = prefix
- self.PAGEINFO = pageinfo
- self.DESCRIPTION = description
- self.ENDPOINTS = endpoints or []
- self.SUBCATEGORY = sub_category or []
- self.INCLUDE_IN_SCHEMA = include_in_schema
-
-
- def retrieve_all_function_codes():
- """
- [FUNCTION_CODE, ...]
- self.ENDPOINTS -> iter()
- """
- pass
-
- def retrieve_page_info():
- """
- PAGE_INFO:ClusterToMethod = {
- "PageInfo": {...}
- "subCategory": PAGE_INFO:ClusterToMethod
- }
- PAGE_INFO:ClusterToMethod = {
- "PageInfo": {...}
- "subCategory": PAGE_INFO:ClusterToMethod
- }
- """
- pass
-
- def retrieve_redis_value() -> Dict:
- """
- Key(CLUSTER_FUNCTION_CODES:ClusterToMethod) : Value(PAGE_INFO, [FUNCTION_CODE, ...])
- """
- pass
+from ApiLayers.AllConfigs.Redis.configs import RedisCategoryKeys
class PageInfo:
@@ -155,7 +10,7 @@ class PageInfo:
NAME: str
BUTTON_NAME: str
PAGE_URL: str
- PAGEINFO: "PageInfo"
+ PAGEINFO: Dict[str, Any]
def __init__(
self,
@@ -173,4 +28,195 @@ class PageInfo:
self.PARENT = parent
+class Event:
+ KEY_: str # static string uuid.uuid4().__str__()
+ RESPONSE_VALIDATOR: Optional[Any]
+ REQUEST_VALIDATOR: Optional[Any]
+ DESCRIPTION: str
+ EXTRA_OPTIONS: Optional[Dict[str, Any]] = None
+ endpoint_callable: Any
+
+ def __init__(
+ self,
+ name: str,
+ key: str | UUID,
+ description: str,
+ request_validator: Optional[Any] = None,
+ response_validator: Optional[Any] = None,
+ extra_options: Optional[Dict[str, Any]] = None,
+ ) -> None:
+ self.NAME = name
+ self.KEY_ = key
+ self.REQUEST_VALIDATOR = request_validator
+ self.RESPONSE_VALIDATOR = response_validator
+ self.DESCRIPTION = description
+ self.EXTRA_OPTIONS = extra_options
+
+ @property
+ def description(self):
+ return f"This is an event of {self.name}. Description: {self.DESCRIPTION}"
+
+ @property
+ def name(self):
+ return self.NAME
+
+ @property
+ def key(self):
+ return str(self.KEY_)
+
+ @abstractmethod
+ def endpoint_callable(self, **kwargs) -> Any:
+ """
+ Retrieves the endpoint function based on the event key.
+ """
+ return self.endpoint_callable(**kwargs)
+
+
+class MethodToEvent:
+ """
+ for all endpoint callable
+ def endpoint_callable(request: Request, data: PydanticModel):
+ return cls.retrieve_event(event_function_code).retrieve_callable(token_dict, data)
+ [Table.__language_model__ | Dict[__language_model__]]
+ [Dict[ErrorCode][lang]]
+
+ """
+
+ EVENTS: dict[str, Event]
+ HEADER_LANGUAGE_MODELS: list[Dict]
+ ERRORS_LANGUAGE_MODELS: Optional[list[Dict]]
+ URL: str
+ METHOD: str
+ SUMMARY: str
+ DESCRIPTION: str
+ DECORATORS_LIST: Optional[Callable] = []
+ EXTRA_OPTIONS: Optional[Dict[str, Any]] = None
+
+ def __init__(
+ self,
+ name: str,
+ events: dict[str, Event],
+ headers: list[Dict],
+ url: str,
+ method: str,
+ summary: str,
+ description: str,
+ decorators_list: Optional[List[Callable]] = None,
+ errors: Optional[list[Dict]] = None,
+ extra_options: Optional[Dict[str, Any]] = None,
+ ):
+ self.EVENTS = events
+ self.URL = url
+ self.METHOD = method
+ self.SUMMARY = summary
+ self.NAME = name
+ self.DESCRIPTION = description
+ self.DECORATORS_LIST = decorators_list
+ self.HEADER_LANGUAGE_MODELS = headers
+ self.ERRORS_LANGUAGE_MODELS = errors
+ self.EXTRA_OPTIONS = extra_options
+
+ @property
+ def name(self):
+ return self.NAME
+
+ def retrieve_all_event_keys(self):
+ """
+ Retrieves all event keys from the events list.
+ """
+ return [str(event_key) for event_key in self.EVENTS.keys()]
+
+ def retrieve_event(self, event_function_code: str) -> Event:
+ """
+ Retrieves the event object from the events list based on the event function code.
+ """
+ if found_event := self.EVENTS.get(event_function_code, None):
+ return found_event
+ raise ValueError(f"Event with function code {event_function_code} not found")
+
+ def retrieve_redis_value(self, cluster_name: str) -> Dict:
+ """
+ Key("METHOD_FUNCTION_CODES:{ClusterToMethod}:MethodEvent:Endpoint") : Value([FUNCTION_CODE, ...])
+ """
+ redis_key = f"{RedisCategoryKeys.METHOD_FUNCTION_CODES}:{cluster_name}:{self.name}:{self.URL}"
+ return {redis_key: self.retrieve_all_event_keys()}
+
+ @staticmethod
+ def endpoint_callable(**kwargs):
+ """
+ return cls.retrieve_event(event_function_code).retrieve_callable(token_dict, data)
+ """
+ raise NotImplementedError("Endpoint callable method is not implemented")
+
+
+class CategoryCluster:
+
+ TAGS: list
+ PREFIX: str
+ PAGEINFO: PageInfo
+ DESCRIPTION: str
+ ENDPOINTS: list[MethodToEvent] # [MethodToEvent, ...]
+ SUBCATEGORY: Optional[List["CategoryCluster"]] # [CategoryCluster, ...]
+ INCLUDE_IN_SCHEMA: Optional[bool] = True
+
+ def __init__(
+ self,
+ name: str,
+ tags: list,
+ prefix: str,
+ description: str,
+ pageinfo: PageInfo,
+ endpoints: list[MethodToEvent],
+ sub_category: list,
+ include_in_schema: Optional[bool] = True,
+ ):
+ self.NAME = name
+ self.TAGS = tags
+ self.PREFIX = prefix
+ self.PAGEINFO = pageinfo
+ self.DESCRIPTION = description
+ self.ENDPOINTS = endpoints or []
+ self.SUBCATEGORY = sub_category or []
+ self.INCLUDE_IN_SCHEMA = include_in_schema
+
+ @property
+ def name(self):
+ return self.NAME
+
+ def get_redis_cluster_index_value(self):
+ """
+ RedisCategoryKeys.CLUSTER_2_METHOD_EVENT
+ Returns the class name and function codes for the class.
+ """
+ dict_cluster_2_method, list_endpoints = {}, [i.name for i in self.ENDPOINTS]
+ for endpoint_name in list_endpoints:
+ dict_cluster_2_method[endpoint_name] = self.name
+ dict_cluster_2_method[self.name] = list_endpoints
+ return dict_cluster_2_method
+
+ def retrieve_all_function_codes(self):
+ """
+ Retrieves all function codes by iterating over the events list.
+ """
+ all_function_codes = []
+ for event_method in self.ENDPOINTS:
+ all_function_codes.extend([str(event_key) for event_key in event_method.EVENTS.keys()])
+ return all_function_codes
+
+ def retrieve_redis_value(self) -> Dict:
+ """
+ Create Redis Key and Value from function codes
+ Key(CLUSTER_FUNCTION_CODES:ClusterToMethod) : Value(PAGE_INFO, [FUNCTION_CODE, ...])
+ """
+ return {
+ f"{RedisCategoryKeys.CLUSTER_FUNCTION_CODES}:{self.name}": self.retrieve_all_function_codes()
+ }
+
+ def retrieve_page_info(self):
+ """
+ PAGE_INFO:ClusterToMethod = {"PageInfo": {...}, "subCategory": PAGE_INFO:ClusterToMethod}
+ """
+ raise NotImplementedError(
+ "CategoryCluster retrieve_page_info() method is not implemented"
+ )
diff --git a/Events/Engine/set_defaults/category_cluster_models.py b/Events/Engine/set_defaults/category_cluster_models.py
new file mode 100644
index 0000000..f4164c6
--- /dev/null
+++ b/Events/Engine/set_defaults/category_cluster_models.py
@@ -0,0 +1,42 @@
+from Events.Engine import CategoryCluster
+
+
+class CategoryBulk:
+
+ def __init__(self, category_cluster: CategoryCluster = None, name: str = ""):
+ self.category_cluster = category_cluster
+ self.name = name
+
+
+class CategoryClusterController:
+
+ imports_dict: list[CategoryBulk] = []
+
+ @property
+ def imports(self):
+ return self.imports_dict
+
+ @classmethod
+ def import_all_category_clusters(cls, category_clusters):
+ """
+ Imports all category clusters from the given list
+ { "category_cluster_name": "category_cluster_module" }
+ """
+ if not hasattr(category_clusters, "__all__"):
+ raise ValueError(f"Given module {str(category_clusters)} does not have __all__ attribute")
+ for iter_module in [str(item) for item in category_clusters.__all__]:
+ # CategoryCluster which represent api routers for each category
+ cls.imports_dict.append(
+ CategoryBulk(
+ category_cluster=getattr(category_clusters, iter_module, None),
+ name=iter_module
+ ))
+
+ @classmethod
+ def as_dict(cls):
+ to_dict = {}
+ for cluster in cls.imports_dict:
+ to_dict[cluster.name] = cluster.category_cluster
+ return to_dict
+
+cluster_controller = CategoryClusterController()
\ No newline at end of file
diff --git a/Events/Engine/set_defaults/prepare_redis_items.py b/Events/Engine/set_defaults/prepare_redis_items.py
new file mode 100644
index 0000000..ce80f4f
--- /dev/null
+++ b/Events/Engine/set_defaults/prepare_redis_items.py
@@ -0,0 +1,84 @@
+from ApiLayers.AllConfigs.Redis.configs import RedisCategoryKeys
+
+
+class PrepareRedisItems:
+
+ MENU_FIRST_LAYER_KEY: str = RedisCategoryKeys.MENU_FIRST_LAYER
+ MENU_FIRST_LAYER_VALUE: set[str] = set()
+ CLUSTER_INDEX_KEY: str = RedisCategoryKeys.CLUSTER_INDEX
+ CLUSTER_INDEX_VALUE: dict = {}
+ CLUSTER_FUNCTION_CODES_KEY: str = RedisCategoryKeys.CLUSTER_FUNCTION_CODES
+ CLUSTER_FUNCTION_CODES_VALUE: dict = {}
+ METHOD_FUNCTION_CODES_KEY: str = RedisCategoryKeys.METHOD_FUNCTION_CODES
+ METHOD_FUNCTION_CODES_VALUE: dict = {}
+ ENDPOINT2CLASS_KEY: str = RedisCategoryKeys.ENDPOINT2CLASS
+ ENDPOINT2CLASS_VALUE: dict = {}
+
+ @property
+ def as_dict(self):
+ return {
+ self.MENU_FIRST_LAYER_KEY: list(self.MENU_FIRST_LAYER_VALUE),
+ self.CLUSTER_INDEX_KEY: self.CLUSTER_INDEX_VALUE,
+ self.CLUSTER_FUNCTION_CODES_KEY: self.CLUSTER_FUNCTION_CODES_VALUE,
+ self.METHOD_FUNCTION_CODES_KEY: self.METHOD_FUNCTION_CODES_VALUE,
+ self.ENDPOINT2CLASS_KEY: self.ENDPOINT2CLASS_VALUE,
+ }
+
+
+class DecoratorModule:
+
+ @staticmethod
+ def get_all_decorators(func):
+ """
+ Get all decorators of a function, excluding the original function itself.
+ Returns a list of decorator functions in the order they were applied.
+ """
+ decorators = []
+ current_func = func
+ original_qualname = getattr(func, '__qualname__', '')
+
+ while hasattr(current_func, '__wrapped__'):
+ if hasattr(current_func, '__closure__') and current_func.__closure__:
+ for cell in current_func.__closure__:
+ decorator = cell.cell_contents
+ # Only add if it's a callable and not the original function
+ if callable(decorator) and getattr(decorator, '__qualname__', '') != original_qualname:
+ decorators.append(decorator)
+ current_func = current_func.__wrapped__
+ return list(dict.fromkeys(decorators)) # Remove duplicates while preserving order
+
+ @staticmethod
+ def get_actual_decorators(method_endpoint):
+ original_qualname = getattr(method_endpoint.endpoint_callable, '__qualname__', '')
+ actual_decorators = [
+ d for d in method_endpoint.DECORATORS_LIST or []
+ if callable(d) and getattr(d, '__qualname__', '') != original_qualname
+ ]
+ return actual_decorators
+
+ @classmethod
+ def apply_decorators(cls, method_endpoint):
+ # Get the original function and its qualname
+ function_callable = method_endpoint.endpoint_callable
+ # Filter out the original function and apply decorators
+ actual_decorators = cls.get_actual_decorators(method_endpoint)
+
+ # Apply decorators in reverse order (to match @ syntax behavior)
+ for decorator in reversed(actual_decorators):
+ try:
+ function_callable = decorator(function_callable)
+ except Exception as e:
+ print(f"Warning: Failed to apply decorator {decorator.__qualname__}: {str(e)}")
+
+ method_endpoint.endpoint_callable = function_callable
+
+ # Get the final list of applied decorators (for debugging)
+ applied_decorators = cls.get_all_decorators(method_endpoint.endpoint_callable)
+ applied_decorators_qualname = [getattr(d, '__qualname__', str(d)) for d in applied_decorators]
+ if applied_decorators:
+ print(f"Applied decorators for {method_endpoint.name}:", applied_decorators_qualname)
+ return applied_decorators_qualname
+
+ @classmethod
+ def list_qualname(cls, method_endpoint_list):
+ return [getattr(method_endpoint, '__qualname__', '') for method_endpoint in method_endpoint_list]
\ No newline at end of file
diff --git a/Events/Engine/set_defaults/run.py b/Events/Engine/set_defaults/run.py
index 139597f..24f95d9 100644
--- a/Events/Engine/set_defaults/run.py
+++ b/Events/Engine/set_defaults/run.py
@@ -1,2 +1,16 @@
+from Events.AllEvents.events_file import events_list
+from .category_cluster_models import cluster_controller
+def get_cluster_controller_group():
+ for cluster in events_list:
+ cluster_controller.import_all_category_clusters(cluster)
+ return cluster_controller
+
+"""
+prepare_routing = PrepareRouting(cluster_controller_group=cluster_controller)
+prepare_events = PrepareEvents(cluster_controller_group=cluster_controller)
+set_items_2_redis = SetItems2Redis(prepare_events=prepare_events)
+print(set_items_2_redis)
+print(prepare_routing)
+"""
diff --git a/Events/Engine/set_defaults/setClusters.py b/Events/Engine/set_defaults/setClusters.py
index 781eb41..30449b9 100644
--- a/Events/Engine/set_defaults/setClusters.py
+++ b/Events/Engine/set_defaults/setClusters.py
@@ -1,7 +1,171 @@
-import AllEvents.auth as auths_events
-import AllEvents.events as events_events
-import AllEvents.validations as validations_events
+from typing import Any
+
+from ApiLayers.ApiServices.Cluster.create_router import (
+ CreateRouterFromCluster,
+ CreateEndpointFromCluster
+)
+from Events.Engine.abstract_class import CategoryCluster
+from Services.Redis.Actions.actions import RedisActions
+from Services.Redis.Models.cluster import RedisList
+
+from .prepare_redis_items import DecoratorModule, PrepareRedisItems
+from .category_cluster_models import CategoryClusterController
-for event in [*auths_events.__all__, *events_events.__all__, *validations_events.__all__]:
- print(event)
+class PrepareRouting(DecoratorModule):
+
+ __routers_list: list[Any] = list()
+ __endpoints_list: list[Any] = list()
+ __safe_endpoint_list: list[Any] = list()
+
+ def __init__(self, cluster_controller_group: CategoryClusterController):
+ self.cluster_controller_group = cluster_controller_group
+ self.prepare_needs()
+
+ def __str__(self):
+ return f"\nPrepared Routing:\n\n{self.routers}\n\n{self.endpoints}\n\n{self.safe_endpoints}\n"
+
+ @property
+ def routers(self):
+ return self.__routers_list
+
+ @property
+ def endpoints(self):
+ return self.__endpoints_list
+
+ @property
+ def safe_endpoints(self):
+ return self.__safe_endpoint_list
+
+ def create_endpoints(self, cluster: CategoryCluster, created_router):
+ for method_endpoint in list(cluster.ENDPOINTS):
+ # Filter out the original function and apply decorators
+ applied_decorators_qualname = self.apply_decorators(method_endpoint)
+ # Register the endpoint with FastAPI router
+ create_endpoint = CreateEndpointFromCluster(
+ router=created_router, method_endpoint=method_endpoint
+ )
+ created_router = create_endpoint.router
+ if "MiddlewareModule" in applied_decorators_qualname:
+ self.__safe_endpoint_list.append(method_endpoint)
+ self.__endpoints_list.append(method_endpoint)
+
+ def create_router(self, cluster: CategoryCluster):
+ ### Create Router Parameters create router for each cluster
+ created_router = CreateRouterFromCluster(
+ prefix=cluster.PREFIX,
+ tags=cluster.TAGS,
+ include_in_schema=cluster.INCLUDE_IN_SCHEMA,
+ )
+ self.__routers_list.append(created_router.router)
+ return created_router.router
+
+ def prepare_needs(self):
+ # @Pages iterate(ClusterToMethod)
+ for cluster_control in self.cluster_controller_group.imports:
+ cluster = cluster_control.category_cluster
+ created_router = self.create_router(cluster)
+ self.create_endpoints(cluster, created_router)
+
+
+class PrepareEvents(DecoratorModule):
+
+ def __init__(self, cluster_controller_group: CategoryClusterController):
+ self.cluster_controller_group = cluster_controller_group
+ self.valid_redis_items: PrepareRedisItems = PrepareRedisItems()
+ self.prepare_needs()
+
+ def prepare_needs(self):
+ # @Pages iterate(ClusterToMethod)
+ for cluster_control in self.cluster_controller_group.imports:
+ cluster = cluster_control.category_cluster
+ ### Create Redis Parameters
+ # [SAVE]REDIS => MENU_FIRST_LAYER = [ClusterToMethod, ...]
+ self.valid_redis_items.MENU_FIRST_LAYER_VALUE.add(cluster.name)
+ # [SAVE]REDIS => CLUSTER_INDEX = {ClusterToMethod: [MethodEvent, ...], "MethodEvent": "ClusterToMethod"}
+ self.valid_redis_items.CLUSTER_INDEX_VALUE.update(cluster.get_redis_cluster_index_value())
+ # [SAVE]REDIS => CLUSTER_FUNCTION_CODES = {"ClusterToMethod"} : [FUNCTION_CODE, ...]}
+ self.valid_redis_items.CLUSTER_FUNCTION_CODES_VALUE = {
+ f"{self.valid_redis_items.CLUSTER_FUNCTION_CODES_KEY}:{cluster.name}" : tuple(cluster.retrieve_all_function_codes())
+ }
+
+ for method_endpoint in list(cluster.ENDPOINTS):
+ # [SAVE]REDIS => ENDPOINT2CLASS = {MethodEvent: Endpoint("/.../.../..."), ...}
+ self.valid_redis_items.ENDPOINT2CLASS_VALUE.update(
+ {f"{cluster.name}:{method_endpoint.name}": method_endpoint.URL}
+ )
+ self.valid_redis_items.ENDPOINT2CLASS_VALUE.update(
+ {method_endpoint.URL :f"{cluster.name}:{method_endpoint.name}"}
+ )
+ # [SAVE]REDIS => METHOD_FUNCTION_CODES:MethodEvent:Endpoint = [FUNCTION_CODE, ...]
+ self.valid_redis_items.METHOD_FUNCTION_CODES_VALUE.update(
+ method_endpoint.retrieve_redis_value(cluster_name=cluster.name)
+ )
+
+
+class SetItems2Redis:
+
+ std_out: str = ""
+
+ def __init__(self, prepare_events: PrepareEvents):
+ self.prepare_events = prepare_events
+ self.set_items()
+
+ def __str__(self):
+ self.std_out = f"\nSetItems2Redis:\n\n{self.std_out}"
+ return self.std_out
+
+ def set_items(self):
+ from ApiLayers.AllConfigs.Redis.configs import RedisCategoryKeys
+ dict_prep = self.prepare_events.valid_redis_items.as_dict
+ RedisActions.delete(
+ list_keys=[
+ f"{RedisCategoryKeys.MENU_FIRST_LAYER}:*",
+ f"{RedisCategoryKeys.CLUSTER_INDEX}:*",
+ f"{RedisCategoryKeys.CLUSTER_FUNCTION_CODES}:*",
+ f"{RedisCategoryKeys.METHOD_FUNCTION_CODES}:*"
+ f"{RedisCategoryKeys.ENDPOINT2CLASS}:*",
+ ]
+ )
+
+ # Save MENU_FIRST_LAYER to Redis
+ redis_list = RedisList(redis_key=RedisCategoryKeys.MENU_FIRST_LAYER)
+ RedisActions.set_json(
+ list_keys=redis_list.to_list(), value=dict_prep.get(RedisCategoryKeys.MENU_FIRST_LAYER)
+ )
+ self.std_out = f"{RedisCategoryKeys.MENU_FIRST_LAYER}: {dict_prep.get(RedisCategoryKeys.MENU_FIRST_LAYER)}\n"
+
+ # Save CLUSTER_INDEX to Redis
+ redis_list = RedisList(redis_key=RedisCategoryKeys.CLUSTER_INDEX)
+ RedisActions.set_json(
+ list_keys=redis_list.to_list(), value=dict_prep.get(RedisCategoryKeys.CLUSTER_INDEX)
+ )
+ self.std_out += f"\n{RedisCategoryKeys.CLUSTER_INDEX}: {dict_prep.get(RedisCategoryKeys.CLUSTER_INDEX)}\n"
+
+ # Save CLUSTER_FUNCTION_CODES to Redis by iterating over the dict
+ for redis_key, redis_value in dict_prep.get(RedisCategoryKeys.CLUSTER_FUNCTION_CODES).items():
+ redis_list = RedisList(redis_key=redis_key)
+ RedisActions.set_json(
+ list_keys=redis_list.to_list(), value=list(redis_value)
+ )
+ self.std_out += f"\n{RedisCategoryKeys.CLUSTER_FUNCTION_CODES}: {dict_prep.get(RedisCategoryKeys.CLUSTER_FUNCTION_CODES)}\n"
+
+ # Save METHOD_FUNCTION_CODES to Redis by iterating over the dict
+ for redis_key, redis_value in dict_prep.get(RedisCategoryKeys.METHOD_FUNCTION_CODES).items():
+ redis_list = RedisList(redis_key=redis_key)
+ RedisActions.set_json(
+ list_keys=redis_list.to_list(), value=list(redis_value)
+ )
+ self.std_out += f"\n{RedisCategoryKeys.METHOD_FUNCTION_CODES}: {dict_prep.get(RedisCategoryKeys.METHOD_FUNCTION_CODES)}\n"
+
+ # Save ENDPOINT2CLASS to Redis by iterating over the dict
+ for redis_key, redis_value in dict_prep.get(RedisCategoryKeys.ENDPOINT2CLASS).items():
+ redis_list = RedisList(redis_key=f"{RedisCategoryKeys.ENDPOINT2CLASS}:{redis_key}\n")
+ RedisActions.set_json(
+ list_keys=redis_list.to_list(), value=redis_value
+ )
+ self.std_out += f"\n{RedisCategoryKeys.ENDPOINT2CLASS}: {dict_prep.get(RedisCategoryKeys.ENDPOINT2CLASS)}\n"
+
+ RedisActions.set_json(
+ list_keys=[f"{RedisCategoryKeys.REBUILD}:*"], value=False
+ )
diff --git a/Events/abstract_class.py b/Events/abstract_class.py
deleted file mode 100644
index e8839b3..0000000
--- a/Events/abstract_class.py
+++ /dev/null
@@ -1,38 +0,0 @@
-
-class ClusterToMethod:
-
- TAGS: list = ["Tag or Router"]
- PREFIX: str = "/..."
- PAGEINFO: PageInfo
- ENDPOINTS: list = [MethodEvent, ...]
- SUBCATEGORY: List[ClassVar[Any]] = [ClusterToMethod, ...]
-
- def retrieve_all_function_codes():
- """
- [FUNCTION_CODE, ...]
- self.ENDPOINTS -> iter()
- """
- pass
-
- def retrieve_page_info():
- """
- PAGE_INFO:ClusterToMethod = {
- "PageInfo": {...}
- "subCategory": PAGE_INFO:ClusterToMethod
- }
- PAGE_INFO:ClusterToMethod = {
- "PageInfo": {...}
- "subCategory": PAGE_INFO:ClusterToMethod
- }
- """
- pass
-
- def retrieve_redis_value() -> Dict:
- """
- Key(CLUSTER_FUNCTION_CODES:ClusterToMethod) : Value(PAGE_INFO, [FUNCTION_CODE, ...])
- """
- pass
-
-
-
-
diff --git a/Scratches/endpoint.py b/Scratches/endpoint.py
index dfcf4dd..949e649 100644
--- a/Scratches/endpoint.py
+++ b/Scratches/endpoint.py
@@ -17,7 +17,7 @@ class CategoryCreate(CategoryBase):
class CategoryResponse(CategoryBase):
- children: List['CategoryResponse'] = []
+ children: List["CategoryResponse"] = []
parent_id: Optional[str] = None
@@ -28,7 +28,7 @@ class CategoryNode:
name: str
description: Optional[str]
parent_id: Optional[str] = None
- children: List['CategoryNode'] = field(default_factory=list)
+ children: List["CategoryNode"] = field(default_factory=list)
# Category Service for managing the hierarchy
@@ -41,7 +41,7 @@ class CategoryService:
id=category.id,
name=category.name,
description=category.description,
- parent_id=category.parent_id
+ parent_id=category.parent_id,
)
self.categories[category.id] = node
@@ -61,7 +61,9 @@ class CategoryService:
while current:
path.append(current)
- current = self.categories.get(current.parent_id) if current.parent_id else None
+ current = (
+ self.categories.get(current.parent_id) if current.parent_id else None
+ )
return list(reversed(path))
@@ -85,9 +87,8 @@ class CategoryEndpointFactory:
endpoint_function=self.create_category,
request_model=CategoryCreate,
response_model=CategoryResponse,
- is_auth_required=True
+ is_auth_required=True,
),
-
# Get category tree endpoint
EndpointFactoryConfig(
url_prefix=base_prefix,
@@ -99,9 +100,8 @@ class CategoryEndpointFactory:
description="Get category and its children",
endpoint_function=self.get_category_tree,
response_model=CategoryResponse,
- is_auth_required=True
+ is_auth_required=True,
),
-
# Get category path endpoint
EndpointFactoryConfig(
url_prefix=base_prefix,
@@ -113,15 +113,15 @@ class CategoryEndpointFactory:
description="Get full path from root to this category",
endpoint_function=self.get_category_path,
response_model=List[CategoryResponse],
- is_auth_required=True
- )
+ is_auth_required=True,
+ ),
]
return RouteFactoryConfig(
name="categories",
tags=["Categories"],
prefix=base_prefix,
- endpoints=endpoints
+ endpoints=endpoints,
)
async def create_category(self, category: CategoryCreate) -> CategoryResponse:
@@ -146,7 +146,7 @@ class CategoryEndpointFactory:
name=node.name,
description=node.description,
parent_id=node.parent_id,
- children=[self._convert_to_response(child) for child in node.children]
+ children=[self._convert_to_response(child) for child in node.children],
)
@@ -156,10 +156,7 @@ def create_category_router(base_prefix: str = "/api/v1") -> APIRouter:
factory = CategoryEndpointFactory(category_service)
route_config = factory.create_route_config(base_prefix)
- router = APIRouter(
- prefix=route_config.prefix,
- tags=route_config.tags
- )
+ router = APIRouter(prefix=route_config.prefix, tags=route_config.tags)
for endpoint in route_config.endpoints:
router.add_api_route(
@@ -169,7 +166,7 @@ def create_category_router(base_prefix: str = "/api/v1") -> APIRouter:
response_model=endpoint.response_model,
summary=endpoint.summary,
description=endpoint.description,
- **endpoint.extra_options
+ **endpoint.extra_options,
)
- return router
\ No newline at end of file
+ return router
diff --git a/Services/PostgresDb/Models/core_alchemy.py b/Services/PostgresDb/Models/core_alchemy.py
index 1483935..a956259 100644
--- a/Services/PostgresDb/Models/core_alchemy.py
+++ b/Services/PostgresDb/Models/core_alchemy.py
@@ -2,8 +2,10 @@ from typing import Type, TypeVar
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.orm import Session
-from ApiLibrary import get_line_number_for_error
-from ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
+
+from ApiLayers.ApiLibrary import get_line_number_for_error
+from ApiLayers.ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
+
# Type variable for class methods returning self
T = TypeVar("T", bound="FilterAttributes")
diff --git a/Services/PostgresDb/Models/crud_alchemy.py b/Services/PostgresDb/Models/crud_alchemy.py
index bccef05..911278a 100644
--- a/Services/PostgresDb/Models/crud_alchemy.py
+++ b/Services/PostgresDb/Models/crud_alchemy.py
@@ -6,8 +6,8 @@ from sqlalchemy import TIMESTAMP, NUMERIC
from sqlalchemy.orm import Session, Mapped
from pydantic import BaseModel
-from ApiLibrary import system_arrow, get_line_number_for_error, client_arrow
-from ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
+from ApiLayers.ApiLibrary import system_arrow, get_line_number_for_error
+from ApiLayers.ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
from Services.PostgresDb.Models.core_alchemy import BaseAlchemyModel
from Services.PostgresDb.Models.system_fields import SystemFields
diff --git a/Services/PostgresDb/Models/filter_functions.py b/Services/PostgresDb/Models/filter_functions.py
index b5e07d0..6ad6654 100644
--- a/Services/PostgresDb/Models/filter_functions.py
+++ b/Services/PostgresDb/Models/filter_functions.py
@@ -13,9 +13,9 @@ from sqlalchemy.sql.elements import BinaryExpression
from sqlalchemy_mixins.smartquery import SmartQueryMixin
from Services.PostgresDb.Models.response import PostgresResponse
-from Services.PostgresDb.Models_old.base_model import BaseModel
+from Services.PostgresDb.Models.core_alchemy import BaseAlchemyModel
-from ApiLibrary import system_arrow
+from ApiLayers.ApiLibrary import system_arrow
T = TypeVar("T", bound="FilterAttributes")
@@ -63,7 +63,7 @@ class ArgumentModel:
return arg
-class QueryModel(ArgumentModel, BaseModel, SmartQueryMixin):
+class QueryModel(ArgumentModel, BaseAlchemyModel, SmartQueryMixin):
pre_query = None
__abstract__ = True
diff --git a/Services/PostgresDb/__init__.py b/Services/PostgresDb/__init__.py
index 912af25..e0568d3 100644
--- a/Services/PostgresDb/__init__.py
+++ b/Services/PostgresDb/__init__.py
@@ -1,4 +1,4 @@
-from Services.PostgresDb.Models.mixins import CrudCollection, BaseCollection
+from Services.PostgresDb.Models.mixin import CrudCollection, BaseCollection
__all__ = [
"CrudCollection",
diff --git a/Services/PostgresDb/database.py b/Services/PostgresDb/database.py
index f1d70ca..2a294b4 100644
--- a/Services/PostgresDb/database.py
+++ b/Services/PostgresDb/database.py
@@ -5,7 +5,7 @@ from typing import Generator
from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base, sessionmaker, scoped_session, Session
-from AllConfigs.SqlDatabase.configs import WagDatabase
+from ApiLayers.AllConfigs.SqlDatabase.configs import WagDatabase
# Configure the database engine with proper pooling
engine = create_engine(
diff --git a/Services/Redis/Actions/actions.py b/Services/Redis/Actions/actions.py
index 7791fa7..3733357 100644
--- a/Services/Redis/Actions/actions.py
+++ b/Services/Redis/Actions/actions.py
@@ -2,7 +2,7 @@ import arrow
from typing import Optional, List, Dict, Union
-from AllConfigs.main import MainConfig
+from ApiLayers.AllConfigs.main import MainConfig
from Services.Redis.conn import redis_cli
from Services.Redis.Models.base import RedisRow
diff --git a/Services/Redis/Models/access.py b/Services/Redis/Models/access.py
new file mode 100644
index 0000000..3c3161e
--- /dev/null
+++ b/Services/Redis/Models/access.py
@@ -0,0 +1,30 @@
+from typing import Optional
+from uuid import UUID
+from pydantic import field_validator
+
+from Services.Redis.Models.row import BaseRedisModel
+
+
+class AccessToken(BaseRedisModel):
+
+ accessToken: Optional[str] = None
+ userUUID: Optional[str | UUID] = None
+
+ @field_validator("userUUID", mode="after")
+ def validate_uuid(cls, v):
+ """Convert UUID to string during validation."""
+ if v is None:
+ return None
+ return str(v)
+
+ def to_list(self):
+ """Convert to list for Redis storage."""
+ return [self.accessToken, str(self.userUUID) if self.userUUID else None]
+
+ @property
+ def count(self):
+ return 2
+
+ @property
+ def delimiter(self):
+ return ":"
diff --git a/Services/Redis/Models/cluster.py b/Services/Redis/Models/cluster.py
new file mode 100644
index 0000000..1724cc3
--- /dev/null
+++ b/Services/Redis/Models/cluster.py
@@ -0,0 +1,17 @@
+from Services.Redis.Models.row import BaseRedisModel
+
+
+class RedisList(BaseRedisModel):
+ redis_key: str
+
+ def to_list(self):
+ """Convert to list for Redis storage."""
+ return [self.redis_key]
+
+ @property
+ def count(self):
+ return 1
+
+ @property
+ def delimiter(self):
+ return ":"
diff --git a/Services/Redis/Models/row.py b/Services/Redis/Models/row.py
index 86ec4c5..b9fd12b 100644
--- a/Services/Redis/Models/row.py
+++ b/Services/Redis/Models/row.py
@@ -1,28 +1,20 @@
-from typing import Optional, Literal
-from uuid import UUID
-from pydantic import BaseModel, field_validator
+from abc import abstractmethod
+from pydantic import BaseModel
-class AccessToken(BaseModel):
+class BaseRedisModel(BaseModel):
- accessToken: Optional[str] = None
- userUUID: Optional[str | UUID] = None
-
- @field_validator("userUUID", mode="after")
- def validate_uuid(cls, v):
- """Convert UUID to string during validation."""
- if v is None:
- return None
- return str(v)
-
- def to_list(self):
+ @abstractmethod
+ def to_list(self) -> list:
"""Convert to list for Redis storage."""
- return [self.accessToken, str(self.userUUID) if self.userUUID else None]
+ pass
- @property
- def count(self):
- return 2
+ @abstractmethod
+ def count(self) -> int:
+ """Return the number of elements in the list."""
+ pass
- @property
- def delimiter(self):
- return "*"
+ @abstractmethod
+ def delimiter(self) -> str:
+ """Return the delimiter for the list."""
+ pass
diff --git a/Services/Redis/__init__.py b/Services/Redis/__init__.py
index 28635af..3fe242a 100644
--- a/Services/Redis/__init__.py
+++ b/Services/Redis/__init__.py
@@ -1,5 +1,5 @@
from Services.Redis.Actions.actions import RedisActions
-from Services.Redis.Models.row import AccessToken
+from Services.Redis.Models.access import AccessToken
__all__ = [
diff --git a/Services/Redis/conn.py b/Services/Redis/conn.py
index 066aace..d9e7d0d 100644
--- a/Services/Redis/conn.py
+++ b/Services/Redis/conn.py
@@ -1,6 +1,6 @@
from redis import Redis
-from AllConfigs.Redis.configs import WagRedis
+from ApiLayers.AllConfigs.Redis.configs import WagRedis
class RedisConn:
diff --git a/docker-compose-services.yml b/docker-compose-services.yml
index d2ba154..60a634b 100644
--- a/docker-compose-services.yml
+++ b/docker-compose-services.yml
@@ -1,4 +1,9 @@
services:
+ init-service:
+ build:
+ context: .
+ dockerfile: DockerApiServices/InitServiceApi/Dockerfile
+
auth-service:
build:
context: .
@@ -11,12 +16,12 @@ services:
context: .
dockerfile: DockerApiServices/EventServiceApi/Dockerfile
ports:
- - "41576:41575"
+ - "41576:41576"
validation-service:
build:
context: .
dockerfile: DockerApiServices/ValidationServiceApi/Dockerfile
ports:
- - "41577:41575"
+ - "41577:41577"
# and lets try to implement potry again in the dockerfile now we now that it is about copy of files
diff --git a/docs/improvements/validation_service/backend/unified_schema_service.py b/docs/improvements/validation_service/backend/unified_schema_service.py
index 82ed3c3..115a2d0 100644
--- a/docs/improvements/validation_service/backend/unified_schema_service.py
+++ b/docs/improvements/validation_service/backend/unified_schema_service.py
@@ -2,30 +2,37 @@ from typing import Dict, Any, Type, Optional
from pydantic import BaseModel
from fastapi import APIRouter, Header
+
class ValidationMessages(BaseModel):
"""Messages for Zod validation"""
+
required: str
invalid_type: str
invalid_string: Dict[str, str] # email, url, etc
- too_small: Dict[str, str] # string, array, number
- too_big: Dict[str, str] # string, array, number
+ too_small: Dict[str, str] # string, array, number
+ too_big: Dict[str, str] # string, array, number
invalid_date: str
invalid_enum: str
custom: Dict[str, str]
+
class SchemaField(BaseModel):
"""Schema field definition"""
+
type: str
items: Optional[str] = None # For arrays
values: Optional[list] = None # For enums
validations: Optional[Dict[str, Any]] = None
+
class SchemaDefinition(BaseModel):
"""Complete schema definition"""
+
name: str
fields: Dict[str, SchemaField]
messages: ValidationMessages
+
class UnifiedSchemaService:
def __init__(self):
self.messages = {
@@ -35,24 +42,24 @@ class UnifiedSchemaService:
invalid_string={
"email": "Geçerli bir e-posta adresi giriniz",
"url": "Geçerli bir URL giriniz",
- "uuid": "Geçerli bir UUID giriniz"
+ "uuid": "Geçerli bir UUID giriniz",
},
too_small={
"string": "{min} karakterden az olamaz",
"array": "En az {min} öğe gereklidir",
- "number": "En az {min} olmalıdır"
+ "number": "En az {min} olmalıdır",
},
too_big={
"string": "{max} karakterden fazla olamaz",
"array": "En fazla {max} öğe olabilir",
- "number": "En fazla {max} olabilir"
+ "number": "En fazla {max} olabilir",
},
invalid_date="Geçerli bir tarih giriniz",
invalid_enum="Geçersiz seçim",
custom={
"password_match": "Şifreler eşleşmiyor",
- "strong_password": "Şifre güçlü değil"
- }
+ "strong_password": "Şifre güçlü değil",
+ },
),
"en": ValidationMessages(
required="This field is required",
@@ -60,48 +67,44 @@ class UnifiedSchemaService:
invalid_string={
"email": "Please enter a valid email",
"url": "Please enter a valid URL",
- "uuid": "Please enter a valid UUID"
+ "uuid": "Please enter a valid UUID",
},
too_small={
"string": "Must be at least {min} characters",
"array": "Must contain at least {min} items",
- "number": "Must be at least {min}"
+ "number": "Must be at least {min}",
},
too_big={
"string": "Must be at most {max} characters",
"array": "Must contain at most {max} items",
- "number": "Must be at most {max}"
+ "number": "Must be at most {max}",
},
invalid_date="Please enter a valid date",
invalid_enum="Invalid selection",
custom={
"password_match": "Passwords do not match",
- "strong_password": "Password is not strong enough"
- }
- )
+ "strong_password": "Password is not strong enough",
+ },
+ ),
}
def get_schema_with_messages(
- self,
- model: Type[BaseModel],
- lang: str = "tr"
+ self, model: Type[BaseModel], lang: str = "tr"
) -> SchemaDefinition:
"""Get schema definition with validation messages"""
fields: Dict[str, SchemaField] = {}
-
+
for field_name, field in model.__fields__.items():
field_info = SchemaField(
type=self._get_field_type(field.outer_type_),
items=self._get_items_type(field.outer_type_),
values=self._get_enum_values(field.outer_type_),
- validations=self._get_validations(field)
+ validations=self._get_validations(field),
)
fields[field_name] = field_info
return SchemaDefinition(
- name=model.__name__,
- fields=fields,
- messages=self.messages[lang]
+ name=model.__name__, fields=fields, messages=self.messages[lang]
)
def _get_field_type(self, type_: Type) -> str:
@@ -120,13 +123,14 @@ class UnifiedSchemaService:
# Implementation similar to SchemaConverter
pass
+
router = APIRouter(prefix="/api/schema", tags=["Schema"])
schema_service = UnifiedSchemaService()
+
@router.get("/model/{model_name}")
async def get_model_schema(
- model_name: str,
- accept_language: Optional[str] = Header(default="tr")
+ model_name: str, accept_language: Optional[str] = Header(default="tr")
) -> SchemaDefinition:
"""Get model schema with validation messages"""
# You'd need to implement model lookup
@@ -135,12 +139,11 @@ async def get_model_schema(
"Product": ProductModel,
# Add your models here
}
-
+
if model_name not in models:
raise ValueError(f"Model {model_name} not found")
-
+
lang = accept_language.split(",")[0][:2]
return schema_service.get_schema_with_messages(
- models[model_name],
- lang if lang in ["tr", "en"] else "tr"
+ models[model_name], lang if lang in ["tr", "en"] else "tr"
)
diff --git a/Services/PostgresDb/Models_old/alchemy_response.py b/trash/Models_old/alchemy_response.py
similarity index 100%
rename from Services/PostgresDb/Models_old/alchemy_response.py
rename to trash/Models_old/alchemy_response.py
diff --git a/Services/PostgresDb/Models_old/base_model.py b/trash/Models_old/base_model.py
similarity index 100%
rename from Services/PostgresDb/Models_old/base_model.py
rename to trash/Models_old/base_model.py
diff --git a/Services/PostgresDb/Models_old/filter_functions.py b/trash/Models_old/filter_functions.py
similarity index 100%
rename from Services/PostgresDb/Models_old/filter_functions.py
rename to trash/Models_old/filter_functions.py
diff --git a/Services/PostgresDb/Models_old/mixins.py b/trash/Models_old/mixins.py
similarity index 100%
rename from Services/PostgresDb/Models_old/mixins.py
rename to trash/Models_old/mixins.py
diff --git a/Services/PostgresDb/Models_old/query.py b/trash/Models_old/query.py
similarity index 100%
rename from Services/PostgresDb/Models_old/query.py
rename to trash/Models_old/query.py
diff --git a/Services/PostgresDb/Models_old/response.py b/trash/Models_old/response.py
similarity index 100%
rename from Services/PostgresDb/Models_old/response.py
rename to trash/Models_old/response.py
diff --git a/trash/abstract_class.py b/trash/abstract_class.py
new file mode 100644
index 0000000..8c748fa
--- /dev/null
+++ b/trash/abstract_class.py
@@ -0,0 +1,33 @@
+class ClusterToMethod:
+
+ TAGS: list = ["Tag or Router"]
+ PREFIX: str = "/..."
+ PAGEINFO: PageInfo
+ ENDPOINTS: list # [MethodEvent, ...]
+ SUBCATEGORY: List[ClassVar[Any]] = [ClusterToMethod, ...]
+
+ def retrieve_all_function_codes():
+ """
+ [FUNCTION_CODE, ...]
+ self.ENDPOINTS -> iter()
+ """
+ pass
+
+ def retrieve_page_info():
+ """
+ PAGE_INFO:ClusterToMethod = {
+ "PageInfo": {...}
+ "subCategory": PAGE_INFO:ClusterToMethod
+ }
+ PAGE_INFO:ClusterToMethod = {
+ "PageInfo": {...}
+ "subCategory": PAGE_INFO:ClusterToMethod
+ }
+ """
+ pass
+
+ def retrieve_redis_value() -> Dict:
+ """
+ Key(CLUSTER_FUNCTION_CODES:ClusterToMethod) : Value(PAGE_INFO, [FUNCTION_CODE, ...])
+ """
+ pass
diff --git a/Events/abstract_class_old.py b/trash/abstract_class_old.py
similarity index 89%
rename from Events/abstract_class_old.py
rename to trash/abstract_class_old.py
index 7b5a668..1e8a21d 100644
--- a/Events/abstract_class_old.py
+++ b/trash/abstract_class_old.py
@@ -4,6 +4,7 @@ Abstract base classes for API route and event handling.
This module provides core abstractions for route configuration and factory,
with support for authentication and event handling.
"""
+
import uuid
import inspect
@@ -229,7 +230,7 @@ class MethodToEvent:
path: str,
method: str = "POST",
response_model: Optional[Type] = None,
- **kwargs
+ **kwargs,
) -> None:
"""Register an API endpoint configuration for an event.
@@ -247,7 +248,7 @@ class MethodToEvent:
"path": path,
"method": method,
"response_model": response_model,
- **kwargs
+ **kwargs,
}
@classmethod
@@ -269,7 +270,7 @@ class MethodToEvent:
icon: str,
url: str,
component: Optional[str] = None,
- parent: Optional[str] = None
+ parent: Optional[str] = None,
) -> None:
"""Configure the frontend page information.
@@ -283,16 +284,20 @@ class MethodToEvent:
"""
required_langs = {"tr", "en"}
if not all(lang in title for lang in required_langs):
- raise ValueError(f"Title must contain all required languages: {required_langs}")
+ raise ValueError(
+ f"Title must contain all required languages: {required_langs}"
+ )
- cls.__page_info__.update({
- "name": name,
- "title": title,
- "icon": icon,
- "url": url,
- "component": component,
- "parent": parent
- })
+ cls.__page_info__.update(
+ {
+ "name": name,
+ "title": title,
+ "icon": icon,
+ "url": url,
+ "component": component,
+ "parent": parent,
+ }
+ )
@classmethod
def get_endpoint_config(cls) -> Dict[str, Any]:
@@ -311,9 +316,7 @@ class MethodToEvent:
@classmethod
def get_page_info_with_permissions(
- cls,
- user_permission_uuids: Set[str],
- include_endpoints: bool = False
+ cls, user_permission_uuids: Set[str], include_endpoints: bool = False
) -> Optional[Dict[str, Any]]:
"""Get page info if user has required permissions.
@@ -333,7 +336,7 @@ class MethodToEvent:
**cls.__page_info__,
"category": cls.event_category,
"type": cls.event_type,
- "description": cls.event_description
+ "description": cls.event_description,
}
# Optionally include available endpoints
@@ -344,7 +347,7 @@ class MethodToEvent:
available_endpoints[uuid] = {
"path": f"{cls.__endpoint_config__['router_prefix']}{endpoint['path']}",
"method": endpoint["method"],
- "event_name": cls.__event_keys__[uuid]
+ "event_name": cls.__event_keys__[uuid],
}
if available_endpoints:
page_info["available_endpoints"] = available_endpoints
@@ -360,7 +363,7 @@ class MethodToEvent:
"page_info": cls.__page_info__,
"category": cls.event_category,
"type": cls.event_type,
- "description": cls.event_description
+ "description": cls.event_description,
}
@classmethod
@@ -482,17 +485,25 @@ class EventMethodRegistry:
"""Registry for mapping event method UUIDs to categories and managing permissions."""
def __init__(self):
- self._uuid_map: Dict[str, Tuple[Type[MethodToEvent], str]] = {} # uuid -> (method_class, event_name)
- self._category_events: Dict[str, Set[str]] = defaultdict(set) # category -> set of uuids
+ self._uuid_map: Dict[str, Tuple[Type[MethodToEvent], str]] = (
+ {}
+ ) # uuid -> (method_class, event_name)
+ self._category_events: Dict[str, Set[str]] = defaultdict(
+ set
+ ) # category -> set of uuids
- def register_method(self, category_name: str, method_class: Type[MethodToEvent]) -> None:
+ def register_method(
+ self, category_name: str, method_class: Type[MethodToEvent]
+ ) -> None:
"""Register a method class with its category."""
# Register all UUIDs from the method
for event_uuid, event_name in method_class.__event_keys__.items():
self._uuid_map[event_uuid] = (method_class, event_name)
self._category_events[category_name].add(event_uuid)
- def get_method_by_uuid(self, event_uuid: str) -> Optional[Tuple[Type[MethodToEvent], str]]:
+ def get_method_by_uuid(
+ self, event_uuid: str
+ ) -> Optional[Tuple[Type[MethodToEvent], str]]:
"""Get method class and event name by UUID."""
return self._uuid_map.get(event_uuid)
@@ -528,10 +539,14 @@ class EventCategory:
"""Validate title has required languages."""
required_langs = {"tr", "en"}
if not all(lang in title for lang in required_langs):
- raise ValueError(f"Title must contain all required languages: {required_langs}")
+ raise ValueError(
+ f"Title must contain all required languages: {required_langs}"
+ )
return title
- def _process_subcategories(self, categories: List[Union[Dict, "EventCategory"]]) -> List["EventCategory"]:
+ def _process_subcategories(
+ self, categories: List[Union[Dict, "EventCategory"]]
+ ) -> List["EventCategory"]:
"""Process subcategories ensuring they are all EventCategory instances."""
processed = []
for category in categories:
@@ -551,7 +566,9 @@ class EventCategory:
for events in self.all_endpoints.values()
)
- def get_menu_item(self, user_permission_uuids: Set[str]) -> Optional[Dict[str, Any]]:
+ def get_menu_item(
+ self, user_permission_uuids: Set[str]
+ ) -> Optional[Dict[str, Any]]:
"""Get menu item if category has available events."""
# First check if this category has available events
if not self.has_available_events(user_permission_uuids):
@@ -561,7 +578,7 @@ class EventCategory:
"name": self.name,
"title": self.title,
"icon": self.icon,
- "url": self.url
+ "url": self.url,
}
if self.component:
@@ -578,7 +595,9 @@ class EventCategory:
return menu_item
- def get_available_events(self, registry: EventMethodRegistry, user_permission_uuids: Set[str]) -> Dict[str, List[Dict[str, Any]]]:
+ def get_available_events(
+ self, registry: EventMethodRegistry, user_permission_uuids: Set[str]
+ ) -> Dict[str, List[Dict[str, Any]]]:
"""Get available events based on user permission UUIDs."""
available_events = defaultdict(list)
@@ -588,16 +607,20 @@ class EventCategory:
method_info = registry.get_method_by_uuid(event_uuid)
if method_info:
method_class, event_name = method_info
- available_events[method_class.event_type].append({
- "uuid": event_uuid,
- "name": event_name,
- "description": method_class.event_description,
- "category": method_class.event_category
- })
+ available_events[method_class.event_type].append(
+ {
+ "uuid": event_uuid,
+ "name": event_name,
+ "description": method_class.event_description,
+ "category": method_class.event_category,
+ }
+ )
# Process subcategories recursively
for subcategory in self.sub_categories:
- sub_events = subcategory.get_available_events(registry, user_permission_uuids)
+ sub_events = subcategory.get_available_events(
+ registry, user_permission_uuids
+ )
for event_type, events in sub_events.items():
available_events[event_type].extend(events)
@@ -614,10 +637,14 @@ class EventCategory:
component=data.get("component"),
page_info=data.get("pageInfo"),
all_endpoints=data.get("allEndpoints", {}),
- sub_categories=data.get("subCategories", [])
+ sub_categories=data.get("subCategories", []),
)
- def to_dict(self, registry: EventMethodRegistry, user_permission_uuids: Optional[Set[str]] = None) -> Dict[str, Any]:
+ def to_dict(
+ self,
+ registry: EventMethodRegistry,
+ user_permission_uuids: Optional[Set[str]] = None,
+ ) -> Dict[str, Any]:
"""Convert category to dictionary with optional permission filtering."""
result = {
"name": self.name,
@@ -629,7 +656,9 @@ class EventCategory:
if user_permission_uuids is not None:
# Only include endpoints and their info if user has permissions
- available_events = self.get_available_events(registry, user_permission_uuids)
+ available_events = self.get_available_events(
+ registry, user_permission_uuids
+ )
if available_events:
result["availableEvents"] = available_events
result["allEndpoints"] = self.all_endpoints
@@ -663,7 +692,8 @@ class EventCategoryManager:
def get_menu_tree(self, user_permission_uuids: Set[str]) -> List[Dict[str, Any]]:
"""Get menu tree based on available events."""
return [
- menu_item for category in self.categories
+ menu_item
+ for category in self.categories
if (menu_item := category.get_menu_item(user_permission_uuids))
]
@@ -677,7 +707,9 @@ class EventCategoryManager:
category = EventCategory.from_dict(category)
self.register_category(category)
- def add_categories(self, categories: List[Union[EventCategory, Dict[str, Any]]]) -> None:
+ def add_categories(
+ self, categories: List[Union[EventCategory, Dict[str, Any]]]
+ ) -> None:
"""Add multiple categories at once."""
for category in categories:
self.add_category(category)
@@ -686,21 +718,30 @@ class EventCategoryManager:
"""Get category by name."""
return next((cat for cat in self.categories if cat.name == name), None)
- def get_all_categories(self, user_permission_uuids: Optional[Set[str]] = None) -> List[Dict[str, Any]]:
+ def get_all_categories(
+ self, user_permission_uuids: Optional[Set[str]] = None
+ ) -> List[Dict[str, Any]]:
"""Get all categories as dictionary, filtered by user permissions."""
- return [cat.to_dict(self.registry, user_permission_uuids) for cat in self.categories]
+ return [
+ cat.to_dict(self.registry, user_permission_uuids) for cat in self.categories
+ ]
def get_category_endpoints(self, category_name: str) -> Set[str]:
"""Get all endpoint UUIDs for a category."""
category = self.get_category(category_name)
return category.all_endpoints.get(category_name, set()) if category else set()
- def get_subcategories(self, category_name: str, user_permission_uuids: Optional[Set[str]] = None) -> List[Dict[str, Any]]:
+ def get_subcategories(
+ self, category_name: str, user_permission_uuids: Optional[Set[str]] = None
+ ) -> List[Dict[str, Any]]:
"""Get subcategories for a category."""
category = self.get_category(category_name)
if not category:
return []
- return [sub.to_dict(self.registry, user_permission_uuids) for sub in category.sub_categories]
+ return [
+ sub.to_dict(self.registry, user_permission_uuids)
+ for sub in category.sub_categories
+ ]
def find_category_by_url(self, url: str) -> Optional[EventCategory]:
"""Find a category by its URL."""
@@ -728,16 +769,16 @@ class EventMethodRegistry:
def register_method_class(cls, method_class: Type[MethodToEvent]) -> None:
"""Register a MethodToEvent class."""
if not issubclass(method_class, MethodToEvent):
- raise ValueError(f"{method_class.__name__} must be a subclass of MethodToEvent")
-
+ raise ValueError(
+ f"{method_class.__name__} must be a subclass of MethodToEvent"
+ )
+
page_info = method_class.get_page_info()
cls._method_classes[page_info["name"]] = method_class
@classmethod
def get_all_menu_items(
- cls,
- user_permission_uuids: Set[str],
- include_endpoints: bool = False
+ cls, user_permission_uuids: Set[str], include_endpoints: bool = False
) -> List[Dict[str, Any]]:
"""Get all menu items based on user permissions.
@@ -751,7 +792,9 @@ class EventMethodRegistry:
# First get all page infos
page_infos = {}
for method_class in cls._method_classes.values():
- if page_info := method_class.get_page_info_with_permissions(user_permission_uuids, include_endpoints):
+ if page_info := method_class.get_page_info_with_permissions(
+ user_permission_uuids, include_endpoints
+ ):
page_infos[page_info["name"]] = page_info
# Build tree structure
@@ -771,18 +814,15 @@ class EventMethodRegistry:
# Start with this page's info
menu_item = page_info.copy()
-
+
# Find and add children
children = []
for child_info in page_infos.values():
if child_info.get("parent") == name:
children.append(child_info)
-
+
if children:
- menu_item["items"] = sorted(
- children,
- key=lambda x: x["name"]
- )
+ menu_item["items"] = sorted(children, key=lambda x: x["name"])
menu_tree.append(menu_item)
@@ -790,8 +830,7 @@ class EventMethodRegistry:
@classmethod
def get_available_endpoints(
- cls,
- user_permission_uuids: Set[str]
+ cls, user_permission_uuids: Set[str]
) -> Dict[str, Dict[str, Any]]:
"""Get all available endpoints based on user permissions.
@@ -802,15 +841,14 @@ class EventMethodRegistry:
Dict mapping event UUIDs to endpoint configurations
"""
available_endpoints = {}
-
+
for method_class in cls._method_classes.values():
if page_info := method_class.get_page_info_with_permissions(
- user_permission_uuids,
- include_endpoints=True
+ user_permission_uuids, include_endpoints=True
):
if endpoints := page_info.get("available_endpoints"):
available_endpoints.update(endpoints)
-
+
return available_endpoints
@@ -916,4 +954,4 @@ user_permission_uuids = {
"ec98ef2c-bcd0-432d-a8f4-1822a56c33b2"
}
menu_tree = manager.get_menu_tree(user_permission_uuids)
-"""
\ No newline at end of file
+"""
diff --git a/trash/auth_old.py b/trash/auth_old.py
index 10f014a..c67f6ba 100644
--- a/trash/auth_old.py
+++ b/trash/auth_old.py
@@ -25,17 +25,20 @@ from ApiLayers.Schemas import (
BuildParts,
RelationshipEmployee2Build,
Companies,
- Departments,
- Duties,
+ Departments,
+ Duties,
Duty,
Staff,
Employees,
Event2Employee,
Event2Occupant,
OccupantTypes,
- Users
+ Users,
+)
+from ApiLayers.ApiServices.Token.token_handler import (
+ OccupantTokenObject,
+ EmployeeTokenObject,
)
-from ApiLayers.ApiServices.Token.token_handler import OccupantTokenObject, EmployeeTokenObject
from .api_events import (
authentication_login_super_user_event,