event decarotor checked & event 2 endpoint dynmc create is tested
This commit is contained in:
parent
76d286b519
commit
049a7c1e11
|
|
@ -1,4 +1,9 @@
|
||||||
import typing
|
import typing
|
||||||
|
from collections.abc import Callable
|
||||||
|
|
||||||
|
from fastapi import Request
|
||||||
|
from typing import Dict, Any
|
||||||
|
|
||||||
from ApiValidations.Custom.token_objects import (
|
from ApiValidations.Custom.token_objects import (
|
||||||
OccupantTokenObject,
|
OccupantTokenObject,
|
||||||
EmployeeTokenObject,
|
EmployeeTokenObject,
|
||||||
|
|
@ -17,12 +22,14 @@ from ApiValidations.Request import (
|
||||||
ListOptions,
|
ListOptions,
|
||||||
)
|
)
|
||||||
from Services.PostgresDb.Models.alchemy_response import AlchemyJsonResponse
|
from Services.PostgresDb.Models.alchemy_response import AlchemyJsonResponse
|
||||||
from ApiEvents.abstract_class import (
|
from ApiValidations.Response import AccountRecordResponse
|
||||||
|
from events.abstract_class import (
|
||||||
MethodToEvent,
|
MethodToEvent,
|
||||||
RouteFactoryConfig,
|
RouteFactoryConfig,
|
||||||
EndpointFactoryConfig,
|
EndpointFactoryConfig,
|
||||||
)
|
)
|
||||||
from ApiValidations.Response import AccountRecordResponse
|
|
||||||
|
# from events.utils import with_token_event
|
||||||
|
|
||||||
|
|
||||||
class AccountRecordsListEventMethods(MethodToEvent):
|
class AccountRecordsListEventMethods(MethodToEvent):
|
||||||
|
|
@ -355,3 +362,108 @@ class AccountRecordsPatchEventMethods(MethodToEvent):
|
||||||
message="Account record patched successfully",
|
message="Account record patched successfully",
|
||||||
result=account_record,
|
result=account_record,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def address_list(request: Request, data: dict) -> Dict[str, Any]:
|
||||||
|
"""Handle address list endpoint."""
|
||||||
|
# Access context through the handler
|
||||||
|
handler = address_list.handler
|
||||||
|
handler_context = address_list.handler.context
|
||||||
|
function_name = AccountRecordsListEventMethods.__event_keys__.get(handler.function_code)
|
||||||
|
original_function = getattr(AccountRecordsListEventMethods, function_name)
|
||||||
|
# original_function(data, request)
|
||||||
|
return {
|
||||||
|
"data": data,
|
||||||
|
"function_code": handler.function_code, # This will be the URL
|
||||||
|
"token_dict": handler_context.get('token_dict'),
|
||||||
|
"url_of_endpoint": handler_context.get('url_of_endpoint'),
|
||||||
|
"request": str(request.headers),
|
||||||
|
}
|
||||||
|
|
||||||
|
def address_create(request: Request, data: dict):
|
||||||
|
"""Handle address creation endpoint."""
|
||||||
|
return {
|
||||||
|
"data": data,
|
||||||
|
"request": str(request.headers),
|
||||||
|
"request_url": str(request.url),
|
||||||
|
"request_base_url": str(request.base_url),
|
||||||
|
}
|
||||||
|
|
||||||
|
def address_search(request: Request, data: dict):
|
||||||
|
"""Handle address search endpoint."""
|
||||||
|
# Get function_code from the wrapper's closure
|
||||||
|
function_code = address_search.function_code
|
||||||
|
return {
|
||||||
|
"data": data,
|
||||||
|
"function_code": function_code
|
||||||
|
}
|
||||||
|
|
||||||
|
def address_update(request: Request, address_uu_id: str, data: dict):
|
||||||
|
"""Handle address update endpoint."""
|
||||||
|
# Get function_code from the wrapper's closure
|
||||||
|
function_code = address_update.function_code
|
||||||
|
return {
|
||||||
|
"address_uu_id": address_uu_id,
|
||||||
|
"data": data,
|
||||||
|
"function_code": function_code
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Account Records Router Configuration
|
||||||
|
ACCOUNT_RECORDS_CONFIG = RouteFactoryConfig(
|
||||||
|
name='account_records',
|
||||||
|
prefix='/account/records',
|
||||||
|
tags=['Account Records'],
|
||||||
|
include_in_schema=True,
|
||||||
|
endpoints=[
|
||||||
|
EndpointFactoryConfig(
|
||||||
|
url_prefix = "/account/records",
|
||||||
|
url_endpoint="/address/list",
|
||||||
|
url_of_endpoint = "/account/records/address/list",
|
||||||
|
endpoint="/address/list",
|
||||||
|
method="POST",
|
||||||
|
summary="List Active/Delete/Confirm Address",
|
||||||
|
description="List Active/Delete/Confirm Address",
|
||||||
|
is_auth_required=True,
|
||||||
|
is_event_required=True,
|
||||||
|
endpoint_function=address_list
|
||||||
|
),
|
||||||
|
EndpointFactoryConfig(
|
||||||
|
url_prefix = "/account/records",
|
||||||
|
url_endpoint="/address/create",
|
||||||
|
url_of_endpoint = "/account/records/address/create",
|
||||||
|
endpoint="/address/create",
|
||||||
|
method="POST",
|
||||||
|
summary="Create Address with given auth levels",
|
||||||
|
description="Create Address with given auth levels",
|
||||||
|
is_auth_required=False,
|
||||||
|
is_event_required=False,
|
||||||
|
endpoint_function=address_create
|
||||||
|
),
|
||||||
|
EndpointFactoryConfig(
|
||||||
|
url_prefix = "/account/records",
|
||||||
|
url_endpoint="/address/search",
|
||||||
|
url_of_endpoint = "/account/records/address/search",
|
||||||
|
endpoint="/address/search",
|
||||||
|
method="POST",
|
||||||
|
summary="Search Address with given auth levels",
|
||||||
|
description="Search Address with given auth levels",
|
||||||
|
is_auth_required=True,
|
||||||
|
is_event_required=True,
|
||||||
|
endpoint_function=address_search
|
||||||
|
),
|
||||||
|
EndpointFactoryConfig(
|
||||||
|
url_prefix = "/account/records",
|
||||||
|
url_endpoint="/address/update/{address_uu_id}",
|
||||||
|
url_of_endpoint="/account/records/address/update/{address_uu_id}",
|
||||||
|
endpoint="/address/update/{address_uu_id}",
|
||||||
|
method="PUT",
|
||||||
|
summary="Update Address with given auth levels",
|
||||||
|
description="Update Address with given auth levels",
|
||||||
|
is_auth_required=True,
|
||||||
|
is_event_required=True,
|
||||||
|
endpoint_function=address_update
|
||||||
|
)
|
||||||
|
]
|
||||||
|
).as_dict()
|
||||||
|
|
|
||||||
|
|
@ -5,93 +5,13 @@ This module collects and registers all route configurations from different modul
|
||||||
to be used by the dynamic route creation system.
|
to be used by the dynamic route creation system.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Dict, List, Any, Callable
|
from typing import Dict, List, Any
|
||||||
from fastapi import Request
|
from events.account.account_records import ACCOUNT_RECORDS_CONFIG
|
||||||
|
|
||||||
from ApiEvents.abstract_class import RouteFactoryConfig, EndpointFactoryConfig
|
|
||||||
from ApiEvents.EventServiceApi.utils import with_token_event
|
|
||||||
from ApiEvents.EventServiceApi.account.account_records import (
|
|
||||||
AccountRecordsListEventMethods,
|
|
||||||
ListOptions,
|
|
||||||
InsertAccountRecord,
|
|
||||||
SearchAddress,
|
|
||||||
UpdateAccountRecord,
|
|
||||||
)
|
|
||||||
|
|
||||||
@with_token_event
|
|
||||||
def address_list(request: Request, list_options: ListOptions):
|
|
||||||
"""Handle address list endpoint."""
|
|
||||||
pass
|
|
||||||
|
|
||||||
@with_token_event
|
|
||||||
def address_create(request: Request, data: InsertAccountRecord):
|
|
||||||
"""Handle address creation endpoint."""
|
|
||||||
pass
|
|
||||||
|
|
||||||
@with_token_event
|
|
||||||
def address_search(request: Request, data: SearchAddress):
|
|
||||||
"""Handle address search endpoint."""
|
|
||||||
pass
|
|
||||||
|
|
||||||
@with_token_event
|
|
||||||
def address_update(request: Request, address_uu_id: str, data: UpdateAccountRecord):
|
|
||||||
"""Handle address update endpoint."""
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Account Records Router Configuration
|
|
||||||
ACCOUNT_RECORDS_CONFIG = {
|
|
||||||
'name': 'account_records',
|
|
||||||
'prefix': '/account/records',
|
|
||||||
'tags': ['Account Records'],
|
|
||||||
'include_in_schema': True,
|
|
||||||
'endpoints': [
|
|
||||||
EndpointFactoryConfig(
|
|
||||||
endpoint="/list",
|
|
||||||
method="POST",
|
|
||||||
summary="List Active/Delete/Confirm Address",
|
|
||||||
description="List Active/Delete/Confirm Address",
|
|
||||||
is_auth_required=True,
|
|
||||||
is_event_required=True,
|
|
||||||
request_model=ListOptions,
|
|
||||||
endpoint_function=address_list
|
|
||||||
),
|
|
||||||
EndpointFactoryConfig(
|
|
||||||
endpoint="/create",
|
|
||||||
method="POST",
|
|
||||||
summary="Create Address with given auth levels",
|
|
||||||
description="Create Address with given auth levels",
|
|
||||||
is_auth_required=True,
|
|
||||||
is_event_required=True,
|
|
||||||
request_model=InsertAccountRecord,
|
|
||||||
endpoint_function=address_create
|
|
||||||
),
|
|
||||||
EndpointFactoryConfig(
|
|
||||||
endpoint="/search",
|
|
||||||
method="POST",
|
|
||||||
summary="Search Address with given auth levels",
|
|
||||||
description="Search Address with given auth levels",
|
|
||||||
is_auth_required=True,
|
|
||||||
is_event_required=True,
|
|
||||||
request_model=SearchAddress,
|
|
||||||
endpoint_function=address_search
|
|
||||||
),
|
|
||||||
EndpointFactoryConfig(
|
|
||||||
endpoint="/update/{address_uu_id}",
|
|
||||||
method="POST",
|
|
||||||
summary="Update Address with given auth levels",
|
|
||||||
description="Update Address with given auth levels",
|
|
||||||
is_auth_required=True,
|
|
||||||
is_event_required=True,
|
|
||||||
request_model=UpdateAccountRecord,
|
|
||||||
endpoint_function=address_update
|
|
||||||
)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
# Registry of all route configurations
|
# Registry of all route configurations
|
||||||
ROUTE_CONFIGS = [
|
ROUTE_CONFIGS = [
|
||||||
ACCOUNT_RECORDS_CONFIG,
|
ACCOUNT_RECORDS_CONFIG,
|
||||||
# Add other route configurations here
|
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_route_configs() -> List[Dict[str, Any]]:
|
def get_route_configs() -> List[Dict[str, Any]]:
|
||||||
|
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
"""
|
|
||||||
Utility functions for API event handling.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from functools import wraps
|
|
||||||
from inspect import signature
|
|
||||||
from typing import Callable, TypeVar, ParamSpec, Any
|
|
||||||
from fastapi import Request
|
|
||||||
|
|
||||||
from Services.PostgresDb.Models.token_models import parse_token_object_to_dict
|
|
||||||
|
|
||||||
P = ParamSpec('P')
|
|
||||||
R = TypeVar('R')
|
|
||||||
|
|
||||||
def with_token_event(func: Callable[P, R]) -> Callable[P, R]:
|
|
||||||
"""
|
|
||||||
Decorator that handles token parsing and event execution.
|
|
||||||
|
|
||||||
This decorator:
|
|
||||||
1. Parses the token from the request
|
|
||||||
2. Calls the appropriate event with the token and other arguments
|
|
||||||
|
|
||||||
Args:
|
|
||||||
func: The endpoint function to wrap
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Wrapped function that handles token parsing and event execution
|
|
||||||
"""
|
|
||||||
@wraps(func)
|
|
||||||
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
|
|
||||||
# Extract request from args or kwargs
|
|
||||||
request = next(
|
|
||||||
(arg for arg in args if isinstance(arg, Request)),
|
|
||||||
kwargs.get('request')
|
|
||||||
)
|
|
||||||
if not request:
|
|
||||||
raise ValueError("Request object not found in arguments")
|
|
||||||
|
|
||||||
# Parse token
|
|
||||||
token_dict = parse_token_object_to_dict(request=request)
|
|
||||||
|
|
||||||
# Add token_dict to kwargs
|
|
||||||
kwargs['token_dict'] = token_dict
|
|
||||||
|
|
||||||
# Call the original function
|
|
||||||
return token_dict.available_event(**{
|
|
||||||
k: v for k, v in kwargs.items()
|
|
||||||
if k in signature(token_dict.available_event).parameters
|
|
||||||
})
|
|
||||||
|
|
||||||
return wrapper
|
|
||||||
|
|
@ -5,10 +5,11 @@ This module provides core abstractions for route configuration and factory,
|
||||||
with support for authentication and event handling.
|
with support for authentication and event handling.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Optional, Dict, Any, List, Type, Union, ClassVar, Tuple, TypeVar
|
from typing import Optional, Dict, Any, List, Type, Union, ClassVar, Tuple, TypeVar, Callable
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
ResponseModel = TypeVar('ResponseModel', bound=BaseModel)
|
ResponseModel = TypeVar('ResponseModel', bound=BaseModel)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -17,25 +18,44 @@ class EndpointFactoryConfig:
|
||||||
"""Configuration class for API endpoints.
|
"""Configuration class for API endpoints.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
|
url_of_endpoint: Full URL path for this endpoint
|
||||||
endpoint: URL path for this endpoint
|
endpoint: URL path for this endpoint
|
||||||
method: HTTP method (GET, POST, etc.)
|
method: HTTP method (GET, POST, etc.)
|
||||||
summary: Short description for API documentation
|
summary: Short description for API documentation
|
||||||
description: Detailed description for API documentation
|
description: Detailed description for API documentation
|
||||||
|
endpoint_function: Function to handle the endpoint
|
||||||
is_auth_required: Whether authentication is required
|
is_auth_required: Whether authentication is required
|
||||||
is_event_required: Whether event handling is required
|
is_event_required: Whether event handling is required
|
||||||
request_model: Expected request model type
|
|
||||||
extra_options: Additional endpoint options
|
extra_options: Additional endpoint options
|
||||||
response_model: Expected response model type
|
|
||||||
"""
|
"""
|
||||||
|
url_prefix :str
|
||||||
|
url_endpoint: str
|
||||||
|
url_of_endpoint: str
|
||||||
endpoint: str
|
endpoint: str
|
||||||
method: str
|
method: str
|
||||||
summary: str
|
summary: str
|
||||||
description: str
|
description: str
|
||||||
is_auth_required: bool
|
endpoint_function: Callable
|
||||||
is_event_required: bool
|
is_auth_required: bool = True
|
||||||
request_model: Type[BaseModel]
|
is_event_required: bool = False
|
||||||
extra_options: Dict[str, Any] = field(default_factory=dict)
|
extra_options: Dict[str, Any] = field(default_factory=dict)
|
||||||
response_model: Optional[Type[BaseModel]] = None
|
|
||||||
|
def __post_init__(self):
|
||||||
|
"""Post-initialization processing.
|
||||||
|
|
||||||
|
Apply appropriate wrappers based on auth and event requirements:
|
||||||
|
- If both auth and event required -> wrap with with_token_event
|
||||||
|
- If only auth required -> wrap with MiddlewareModule.auth_required
|
||||||
|
"""
|
||||||
|
# Store url_of_endpoint for the handler
|
||||||
|
self.endpoint_function.url_of_endpoint = self.url_of_endpoint
|
||||||
|
|
||||||
|
if self.is_auth_required and self.is_event_required:
|
||||||
|
from events.utils import with_token_event
|
||||||
|
self.endpoint_function = with_token_event(self.endpoint_function)
|
||||||
|
elif self.is_auth_required:
|
||||||
|
from DockerApiServices.AllApiNeeds.middleware.auth_middleware import MiddlewareModule
|
||||||
|
self.endpoint_function = MiddlewareModule.auth_required(self.endpoint_function)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|
@ -75,10 +95,9 @@ class RouteFactoryConfig:
|
||||||
"method": ep.method,
|
"method": ep.method,
|
||||||
"summary": ep.summary,
|
"summary": ep.summary,
|
||||||
"description": ep.description,
|
"description": ep.description,
|
||||||
|
"endpoint_function": ep.endpoint_function,
|
||||||
"is_auth_required": ep.is_auth_required,
|
"is_auth_required": ep.is_auth_required,
|
||||||
"is_event_required": ep.is_event_required,
|
"is_event_required": ep.is_event_required,
|
||||||
"response_model": ep.response_model.__name__ if ep.response_model else None,
|
|
||||||
"request_model": ep.request_model.__name__,
|
|
||||||
"extra_options": ep.extra_options
|
"extra_options": ep.extra_options
|
||||||
}
|
}
|
||||||
for ep in self.endpoints
|
for ep in self.endpoints
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
"""
|
||||||
|
Utility functions for API event handling.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from typing import TypeVar, Callable, Dict, Any
|
||||||
|
from functools import wraps
|
||||||
|
from fastapi import Request
|
||||||
|
|
||||||
|
R = TypeVar('R')
|
||||||
|
|
||||||
|
class BaseEndpointHandler:
|
||||||
|
"""Base class for handling endpoint execution with context."""
|
||||||
|
|
||||||
|
def __init__(self, func: Callable, url_of_endpoint: str):
|
||||||
|
self.func = func
|
||||||
|
self.url_of_endpoint = url_of_endpoint
|
||||||
|
self.function_code = url_of_endpoint # Set initial function_code
|
||||||
|
self._context = {
|
||||||
|
'url_of_endpoint': url_of_endpoint,
|
||||||
|
'function_code': url_of_endpoint, # Initialize with URL
|
||||||
|
}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def context(self) -> dict:
|
||||||
|
"""Get the endpoint context."""
|
||||||
|
return self._context
|
||||||
|
|
||||||
|
def update_context(self, **kwargs):
|
||||||
|
"""Update the endpoint context with new values."""
|
||||||
|
self._context.update(kwargs)
|
||||||
|
# Update function_code property if it's in the context
|
||||||
|
if 'function_code' in kwargs:
|
||||||
|
self.function_code = kwargs['function_code']
|
||||||
|
|
||||||
|
def __call__(self, *args, **kwargs):
|
||||||
|
return self.func(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class TokenEventHandler(BaseEndpointHandler):
|
||||||
|
"""Handler for endpoints that require token and event tracking."""
|
||||||
|
|
||||||
|
def __init__(self, func: Callable, url_of_endpoint: str):
|
||||||
|
super().__init__(func, url_of_endpoint)
|
||||||
|
self.update_context(
|
||||||
|
token_dict={
|
||||||
|
'user_id': '1234567890',
|
||||||
|
'username': 'test_user',
|
||||||
|
'email': 'asda@email.com',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class AuthHandler(BaseEndpointHandler):
|
||||||
|
"""Handler for endpoints that require only authentication."""
|
||||||
|
|
||||||
|
def __init__(self, func: Callable, url_of_endpoint: str):
|
||||||
|
super().__init__(func, url_of_endpoint)
|
||||||
|
self.update_context(
|
||||||
|
auth_level="user",
|
||||||
|
permissions=["read", "write"]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def with_token_event(func: Callable[..., Dict[str, Any]]) -> Callable[..., Dict[str, Any]]:
|
||||||
|
"""Decorator for endpoints with token and event requirements."""
|
||||||
|
@wraps(func)
|
||||||
|
def wrapper(*args, **kwargs) -> Dict[str, Any]:
|
||||||
|
# Create handler with context
|
||||||
|
handler = TokenEventHandler(
|
||||||
|
func=func,
|
||||||
|
url_of_endpoint=func.url_of_endpoint
|
||||||
|
)
|
||||||
|
|
||||||
|
# Update event-specific context
|
||||||
|
handler.update_context(
|
||||||
|
function_code=f"7192c2aa-5352-4e36-98b3-dafb7d036a3d" # Keep function_code as URL
|
||||||
|
)
|
||||||
|
|
||||||
|
# Make context available to the function
|
||||||
|
func.handler = handler
|
||||||
|
|
||||||
|
# Call the original function
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
def auth_required(func: Callable[..., Dict[str, Any]]) -> Callable[..., Dict[str, Any]]:
|
||||||
|
"""Decorator for endpoints with only auth requirements."""
|
||||||
|
@wraps(func)
|
||||||
|
def wrapper(*args, **kwargs) -> Dict[str, Any]:
|
||||||
|
# Create handler with context
|
||||||
|
handler = AuthHandler(
|
||||||
|
func=func,
|
||||||
|
url_of_endpoint=func.url_of_endpoint
|
||||||
|
)
|
||||||
|
|
||||||
|
# Make context available to the function
|
||||||
|
func.handler = handler
|
||||||
|
|
||||||
|
# Call the original function
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
from AllConfigs.Token.config import Auth
|
||||||
|
from ErrorHandlers import HTTPExceptionApi
|
||||||
|
from Services.Redis import RedisActions, AccessToken
|
||||||
|
from fastapi import Request
|
||||||
|
from ApiValidations.Custom.token_objects import EmployeeTokenObject, OccupantTokenObject
|
||||||
|
|
||||||
|
|
||||||
|
class TokenService:
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def raise_error_if_request_has_no_token(cls, request: Request) -> None:
|
||||||
|
"""Get access token from request headers."""
|
||||||
|
if not hasattr(request, "headers"):
|
||||||
|
raise HTTPExceptionApi(
|
||||||
|
error_code="",
|
||||||
|
lang="en",
|
||||||
|
)
|
||||||
|
if not request.headers.get(Auth.ACCESS_TOKEN_TAG):
|
||||||
|
raise HTTPExceptionApi(
|
||||||
|
error_code="",
|
||||||
|
lang="en",
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_access_token_from_request(cls, request: Request) -> str:
|
||||||
|
"""Get access token from request headers."""
|
||||||
|
cls.raise_error_if_request_has_no_token(request=request)
|
||||||
|
return request.headers.get(Auth.ACCESS_TOKEN_TAG)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_object_via_access_key(cls, access_token: str) -> Union[EmployeeTokenObject, OccupantTokenObject]:
|
||||||
|
"""Get access token from request headers."""
|
||||||
|
access_token = AccessToken(
|
||||||
|
accessToken=access_token,
|
||||||
|
userUUID="",
|
||||||
|
)
|
||||||
|
if redis_object := RedisActions.get_json(
|
||||||
|
list_keys=access_token.to_list()
|
||||||
|
).first.data:
|
||||||
|
access_token.userUUID = redis_object.get("user_uu_id")
|
||||||
|
if redis_object.get("user_type") == 1:
|
||||||
|
if not redis_object.get("selected_company", None):
|
||||||
|
redis_object["selected_company"] = None
|
||||||
|
return EmployeeTokenObject(**redis_object)
|
||||||
|
elif redis_object.get("user_type") == 2:
|
||||||
|
if not redis_object.get("selected_occupant", None):
|
||||||
|
redis_object["selected_occupant"] = None
|
||||||
|
return OccupantTokenObject(**redis_object)
|
||||||
|
raise HTTPExceptionApi(
|
||||||
|
error_code="",
|
||||||
|
lang="en",
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_object_via_user_uu_id(cls, user_id: str) -> Union[EmployeeTokenObject, OccupantTokenObject]:
|
||||||
|
"""Get access token from user uuid."""
|
||||||
|
access_token = AccessToken(
|
||||||
|
accessToken="",
|
||||||
|
userUUID=user_id,
|
||||||
|
)
|
||||||
|
if redis_object := RedisActions.get_json(
|
||||||
|
list_keys=access_token.to_list()
|
||||||
|
).first.data:
|
||||||
|
access_token.userUUID = redis_object.get("user_uu_id")
|
||||||
|
if redis_object.get("user_type") == 1:
|
||||||
|
if not redis_object.get("selected_company", None):
|
||||||
|
redis_object["selected_company"] = None
|
||||||
|
return EmployeeTokenObject(**redis_object)
|
||||||
|
elif redis_object.get("user_type") == 2:
|
||||||
|
if not redis_object.get("selected_occupant", None):
|
||||||
|
redis_object["selected_occupant"] = None
|
||||||
|
return OccupantTokenObject(**redis_object)
|
||||||
|
raise HTTPExceptionApi(
|
||||||
|
error_code="",
|
||||||
|
lang="en",
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
from ApiServices.Token.token_handler import TokenService
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'TokenService',
|
||||||
|
]
|
||||||
|
|
@ -15,7 +15,7 @@ from fastapi.routing import APIRoute
|
||||||
from middleware.auth_middleware import MiddlewareModule
|
from middleware.auth_middleware import MiddlewareModule
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from AllConfigs.main import MainConfig as Config
|
from AllConfigs.main import MainConfig as Config
|
||||||
from ApiEvents.EventServiceApi.route_configs import get_route_configs
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|
@ -99,21 +99,35 @@ def get_all_routers() -> tuple[List[APIRouter], Dict[str, List[str]]]:
|
||||||
Returns:
|
Returns:
|
||||||
tuple: (routers, protected_routes)
|
tuple: (routers, protected_routes)
|
||||||
"""
|
"""
|
||||||
|
from events.route_configs import get_route_configs
|
||||||
|
|
||||||
routers = []
|
routers = []
|
||||||
all_protected_routes = {}
|
all_protected_routes = {}
|
||||||
|
|
||||||
# Get route configurations from the registry
|
# Get route configurations from the registry
|
||||||
route_configs = get_route_configs()
|
route_configs = get_route_configs()
|
||||||
|
factory_all = []
|
||||||
for config in route_configs:
|
for config in route_configs:
|
||||||
factory = EnhancedEndpointFactory(config)
|
factory = EnhancedEndpointFactory(config)
|
||||||
|
|
||||||
# Create endpoints from configuration
|
# Create endpoints from configuration
|
||||||
for endpoint_config in config['endpoints']:
|
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.create_endpoint(endpoint_config)
|
||||||
|
factory_all.append(
|
||||||
|
endpoint_config.__dict__
|
||||||
|
)
|
||||||
|
|
||||||
# Add router and protected routes
|
# Add router and protected routes
|
||||||
routers.append(factory.get_router())
|
routers.append(factory.get_router())
|
||||||
all_protected_routes.update(factory.get_protected_routes())
|
all_protected_routes.update(factory.get_protected_routes())
|
||||||
|
|
||||||
return routers, all_protected_routes
|
return routers, all_protected_routes
|
||||||
|
|
@ -95,25 +95,15 @@ class MiddlewareModule:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
async def wrapper(request: Request, *args, **kwargs):
|
def wrapper(request: Request, *args, **kwargs):
|
||||||
try:
|
from ApiServices import TokenService
|
||||||
# Get token from header
|
# Get token from header
|
||||||
_, token = cls.get_access_token(request)
|
# token = TokenService.get_access_token_from_request(request=request)
|
||||||
|
# print(token)
|
||||||
# Validate token and get user data
|
# if not token:
|
||||||
token_data = await cls.validate_token(token)
|
# raise HTTPExceptionApi(error_code="NOT_AUTHORIZED", lang="tr")
|
||||||
|
|
||||||
# Add user data to request state for use in endpoint
|
|
||||||
request.state.user = token_data
|
|
||||||
|
|
||||||
# Call the original endpoint function
|
# Call the original endpoint function
|
||||||
return await func(request, *args, **kwargs)
|
return func(request, *args, **kwargs)
|
||||||
|
|
||||||
except HTTPExceptionApi:
|
|
||||||
raise HTTPExceptionApi(error_code="NOT_AUTHORIZED", lang="tr")
|
|
||||||
except Exception as e:
|
|
||||||
raise HTTPExceptionApi(error_code="NOT_AUTHORIZED", lang="tr")
|
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,20 @@ RUN poetry config virtualenvs.create false \
|
||||||
|
|
||||||
# Copy application code
|
# Copy application code
|
||||||
COPY DockerApiServices/AllApiNeeds /app/
|
COPY DockerApiServices/AllApiNeeds /app/
|
||||||
|
COPY ErrorHandlers /app/ErrorHandlers
|
||||||
|
COPY LanguageModels /app/LanguageModels
|
||||||
COPY ApiLibrary /app/ApiLibrary
|
COPY ApiLibrary /app/ApiLibrary
|
||||||
COPY ApiValidations /app/ApiValidations
|
COPY ApiValidations /app/ApiValidations
|
||||||
COPY AllConfigs /app/AllConfigs
|
COPY AllConfigs /app/AllConfigs
|
||||||
COPY ErrorHandlers /app/ErrorHandlers
|
COPY ErrorHandlers /app/ErrorHandlers
|
||||||
COPY Schemas /app/Schemas
|
COPY Schemas /app/Schemas
|
||||||
COPY Services /app/Services
|
COPY Services /app/Services
|
||||||
|
COPY ApiServices /app/ApiServices
|
||||||
|
|
||||||
|
# Copy Events structure with consistent naming
|
||||||
|
COPY ApiEvents/EventServiceApi /app/events
|
||||||
|
COPY ApiEvents/utils.py /app/events/utils.py
|
||||||
|
COPY ApiEvents/abstract_class.py /app/events/abstract_class.py
|
||||||
|
|
||||||
# Set Python path to include app directory
|
# Set Python path to include app directory
|
||||||
ENV PYTHONPATH=/app \
|
ENV PYTHONPATH=/app \
|
||||||
|
|
|
||||||
|
|
@ -17,18 +17,15 @@ class HTTPExceptionApiHandler:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def retrieve_error_status_code(exc: HTTPExceptionApi) -> int:
|
def retrieve_error_status_code(exc: HTTPExceptionApi) -> int:
|
||||||
from ErrorHandlers import DEFAULT_ERROR
|
|
||||||
|
|
||||||
error_by_codes = BaseErrorModelClass.retrieve_error_by_codes()
|
error_by_codes = BaseErrorModelClass.retrieve_error_by_codes()
|
||||||
grab_status_code = error_by_codes.get(
|
grab_status_code = error_by_codes.get(
|
||||||
str(exc.error_code).upper(), DEFAULT_ERROR
|
str(exc.error_code).upper(), 500
|
||||||
)
|
)
|
||||||
return int(grab_status_code)
|
return int(grab_status_code)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def retrieve_error_message(exc: HTTPExceptionApi, error_languages) -> str:
|
def retrieve_error_message(exc: HTTPExceptionApi, error_languages) -> str:
|
||||||
from ErrorHandlers import DEFAULT_ERROR
|
from ErrorHandlers import DEFAULT_ERROR
|
||||||
|
|
||||||
return error_languages.get(str(exc.error_code).upper(), DEFAULT_ERROR)
|
return error_languages.get(str(exc.error_code).upper(), DEFAULT_ERROR)
|
||||||
|
|
||||||
async def handle_exception(
|
async def handle_exception(
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,12 @@ services:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: DockerApiServices/EventServiceApi/Dockerfile
|
dockerfile: DockerApiServices/EventServiceApi/Dockerfile
|
||||||
ports:
|
ports:
|
||||||
- "8001:8000"
|
- "41576:41575"
|
||||||
|
|
||||||
validation-service:
|
validation-service:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: DockerApiServices/ValidationServiceApi/Dockerfile
|
dockerfile: DockerApiServices/ValidationServiceApi/Dockerfile
|
||||||
ports:
|
ports:
|
||||||
- "8002:8000"
|
- "41577:41575"
|
||||||
# and lets try to implement potry again in the dockerfile now we now that it is about copy of files
|
# and lets try to implement potry again in the dockerfile now we now that it is about copy of files
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue