redis implemntations and api setup completed

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

View File

@@ -1,25 +0,0 @@
"""
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, get_uvicorn_config
from create_file import create_app
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__":
uvicorn_config = get_uvicorn_config() # Run the application with Uvicorn
uvicorn.Server(uvicorn.Config(**uvicorn_config)).run()

View File

@@ -1,94 +0,0 @@
"""
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 typing import Dict, Any
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
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 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)
def get_uvicorn_config() -> Dict[str, Any]:
"""
Get Uvicorn server configuration.
Returns:
Dict[str, Any]: Uvicorn configuration dictionary
"""
return {
"app": "app:app",
"host": "0.0.0.0",
"port": 41575,
"log_level": "info",
"reload": True,
}

View File

@@ -1,21 +0,0 @@
"""
Base FastAPI application configuration.
"""
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
def create_app() -> FastAPI:
app = FastAPI(title="API Service")
# Configure CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
return app

View File

@@ -1,94 +0,0 @@
"""
FastAPI Application Factory Module
This module provides functionality to create and configure a FastAPI application with:
- Custom OpenAPI schema configuration
- Security scheme configuration for Bearer authentication
- Automatic router registration
- Response class configuration
- Security requirements for protected endpoints
"""
from typing import Any, Dict, List, Tuple
from fastapi import FastAPI, APIRouter
from fastapi.responses import JSONResponse, RedirectResponse
from fastapi.openapi.utils import get_openapi
from AllConfigs.Token.config import Auth
from AllConfigs.main import MainConfig as Config
from create_routes import get_all_routers
def setup_security_schema() -> Dict[str, Any]:
"""
Configure security schema for the OpenAPI documentation.
Returns:
Dict[str, Any]: Security schema configuration
"""
return {
"components": {
"securitySchemes": {
"Bearer Auth": {
"type": "apiKey",
"in": "header",
"name": Auth.ACCESS_TOKEN_TAG,
"description": "Enter: **'Bearer <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

View File

@@ -1,127 +0,0 @@
"""
Route configuration and factory module.
Handles dynamic route creation based on configurations.
"""
from typing import Optional, Dict, Any, List, Callable, TypeVar, ParamSpec
P = ParamSpec("P") # For function parameters
R = TypeVar("R") # For return type
from dataclasses import dataclass
from functools import wraps
from fastapi import APIRouter, Request
from fastapi.routing import APIRoute
from middleware.auth_middleware import MiddlewareModule
from pydantic import BaseModel
from AllConfigs.main import MainConfig as Config
@dataclass
class EndpointFactoryConfig:
endpoint: str
method: str
summary: str
description: str
endpoint_function: Callable[P, R] # Now accepts any parameters and return type
is_auth_required: bool = True
is_event_required: bool = False
extra_options: Dict[str, Any] = None
def __post_init__(self):
if self.extra_options is None:
self.extra_options = {}
class EnhancedEndpointFactory:
def __init__(self, router_config: dict):
self.router = APIRouter(
prefix=router_config["prefix"],
tags=router_config["tags"],
include_in_schema=router_config.get("include_in_schema", True),
)
self.endpoints = router_config["endpoints"]
self.protected_routes: Dict[str, List[str]] = {}
def create_endpoint(self, config: EndpointFactoryConfig):
"""
Create an endpoint directly from the configuration.
Args:
config: EndpointFactoryConfig instance containing endpoint configuration
"""
endpoint_path = config.endpoint
endpoint_function = config.endpoint_function
if config.is_auth_required:
# endpoint_function = MiddlewareModule.auth_required(endpoint_function)
# Track protected routes
full_path = f"{self.router.prefix}{endpoint_path}"
if full_path not in self.protected_routes:
self.protected_routes[full_path] = []
self.protected_routes[full_path].append(config.method.lower())
# Register the endpoint with FastAPI router
getattr(self.router, config.method.lower())(
endpoint_path,
summary=config.summary,
description=config.description,
**config.extra_options,
)(endpoint_function)
def get_router(self) -> APIRouter:
"""Get the configured router."""
return self.router
def get_protected_routes(self) -> Dict[str, List[str]]:
"""Get the protected routes mapping."""
return self.protected_routes
async def health_check(request: Request):
"""Default health check endpoint."""
return {"status": "healthy", "message": "Service is running"}
async def ping_test(request: Request, service_name: str = "base-router"):
"""Default ping test endpoint."""
return {"ping": "pong", "service": service_name}
def get_all_routers() -> tuple[List[APIRouter], Dict[str, List[str]]]:
"""
Get all routers and protected routes from route configurations.
Returns:
tuple: (routers, protected_routes)
"""
from ApiEvents.route_configs import get_route_configs
routers = []
all_protected_routes = {}
# Get route configurations from the registry
route_configs = get_route_configs()
factory_all = []
for config in route_configs:
factory = EnhancedEndpointFactory(config)
# Create endpoints from configuration
for endpoint_dict in config["endpoints"]:
endpoint_config = EndpointFactoryConfig(
endpoint=endpoint_dict["endpoint"],
method=endpoint_dict["method"],
summary=endpoint_dict["summary"],
description=endpoint_dict["description"],
endpoint_function=endpoint_dict["endpoint_function"],
is_auth_required=endpoint_dict["is_auth_required"],
is_event_required=endpoint_dict["is_event_required"],
extra_options=endpoint_dict.get("extra_options", {}),
)
factory.create_endpoint(endpoint_config)
factory_all.append(endpoint_config.__dict__)
# Add router and protected routes
routers.append(factory.get_router())
all_protected_routes.update(factory.get_protected_routes())
return routers, all_protected_routes

View File

@@ -1,273 +0,0 @@
"""
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, List, Optional, Set
from fastapi import FastAPI, APIRouter
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
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.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
]
def _create_security_schemes(self) -> Dict[str, Any]:
"""
Create security scheme definitions.
Returns:
Dict[str, Any]: Security scheme configurations
"""
return {
"Bearer Auth": {
"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
"""
# 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()
)
# Process request body examples
self._process_request_body(path, method, schema)
# Process response examples
self._process_response_examples(path, method, schema)
def create_schema(self) -> Dict[str, Any]:
"""
Create the complete OpenAPI schema.
Returns:
Dict[str, Any]: Complete OpenAPI schema
"""
openapi_schema = get_openapi(
title=Config.TITLE,
description=Config.DESCRIPTION,
version="1.1.1",
routes=self.app.routes,
)
# Add security schemes
if "components" not in openapi_schema:
openapi_schema["components"] = {}
openapi_schema["components"][
"securitySchemes"
] = self._create_security_schemes()
# Configure route security and responses
for route in self.app.routes:
if isinstance(route, APIRoute) and route.include_in_schema:
path = str(route.path)
methods = [method.lower() for method in route.methods]
for method in methods:
self.configure_route_security(path, method, openapi_schema)
# # Add custom documentation extensions
openapi_schema["x-documentation"] = {
"postman_collection": "/docs/postman",
"swagger_ui": "/docs",
"redoc": "/redoc",
}
return openapi_schema
def create_openapi_schema(app: FastAPI) -> Dict[str, Any]:
"""
Create OpenAPI schema for a FastAPI application.
Args:
app: FastAPI application instance
Returns:
Dict[str, Any]: Complete OpenAPI schema
"""
creator = OpenAPISchemaCreator(app)
return creator.create_schema()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,39 @@
from fastapi import APIRouter
import uuid
from Events.Engine.abstract_class import CategoryCluster, MethodToEvent
class CreateRouterFromCluster:
def __init__(self, **kwargs):
self.prefix = kwargs.get("prefix")
self.tags = kwargs.get("tags")
self.router = APIRouter(prefix=self.prefix, tags=self.tags)
class CreateEndpointFromCluster:
def __init__(self, **kwargs):
self.router: CategoryCluster = kwargs.get("router")
self.method_endpoint: MethodToEvent = kwargs.get("method_endpoint")
self.unique_id = str(uuid.uuid4())[:8] # Use first 8 chars of UUID for brevity
self.attach_router()
def attach_router(self):
method = getattr(self.router, self.method_endpoint.METHOD.lower())
# Create a unique operation ID based on the endpoint path, method, and a unique identifier
base_path = self.method_endpoint.URL.strip('/').replace('/', '_').replace('-', '_')
operation_id = f"{base_path}_{self.method_endpoint.METHOD.lower()}_{self.unique_id}"
kwargs = {
"path": self.method_endpoint.URL,
"summary": self.method_endpoint.SUMMARY,
"description": self.method_endpoint.DESCRIPTION,
"operation_id": operation_id
}
if hasattr(self.method_endpoint, 'RESPONSE_MODEL') and self.method_endpoint.RESPONSE_MODEL is not None:
kwargs["response_model"] = self.method_endpoint.RESPONSE_MODEL
method(**kwargs)(self.method_endpoint.endpoint_callable)

View File

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

View File

@@ -1,11 +1,12 @@
from typing import Any, ClassVar, Dict
from 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:

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,10 +1,12 @@
from typing import Any, Dict, Union, Awaitable
from typing import Any, Union, Awaitable
from fastapi import Request, WebSocket
from fastapi.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)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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