middleware and respnse models updated

This commit is contained in:
berkay 2025-01-27 17:25:49 +03:00
parent e403993d24
commit b88f910a43
54 changed files with 1125 additions and 808 deletions

View File

@ -6,14 +6,59 @@
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="b5202e0c-6ddf-4a56-a13a-e18798c4c7cf" name="Changes" comment=""> <list default="true" id="b5202e0c-6ddf-4a56-a13a-e18798c4c7cf" name="Changes" comment="">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/AllConfigs/Redis/configs.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/AllConfigs/Redis/configs.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/ApiLayers/ApiLibrary/token/password_module.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiLibrary/token/password_module.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiServices/Cluster/create_router.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiServices/Cluster/create_router.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiServices/Cluster/handle_cluster.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiServices/Cluster/handle_cluster.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiServices/Login/user_login_handler.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiServices/Login/user_login_handler.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/ApiLayers/ApiServices/Login/user_login_handler.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiServices/Login/user_login_handler.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiServices/Token/token_handler.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiServices/Token/token_handler.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Custom/wrapper_contexts.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Custom/wrapper_contexts.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/decision_book.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Request/decision_book.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Response/default_response.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Response/default_response.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/ApiLayers/ApiValidations/Response/default_response.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ApiValidations/Response/default_response.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/ErrorHandlers/Exceptions/api_exc.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ErrorHandlers/Exceptions/api_exc.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/ApiLayers/ErrorHandlers/Exceptions/api_exc.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/ErrorHandlers/Exceptions/api_exc.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/__init__.py" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/account/account.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/account/account.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/account/iban.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/account/iban.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/building/budget.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/building/budget.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/building/build.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/building/build.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/building/decision_book.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/building/decision_book.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/company/company.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/company/company.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/company/department.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/company/department.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/company/employee.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/company/employee.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/event/event.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/event/event.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/identity/identity.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/identity/identity.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/rules/rules.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/LanguageModels/Database/rules/rules.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/LanguageModels/Errors/__init__.py" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/Middleware/auth_middleware.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/Middleware/auth_middleware.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/Middleware/token_event_middleware.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/Middleware/token_event_middleware.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/Schemas/building/build.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/Schemas/building/build.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/Schemas/identity/identity.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/Schemas/identity/identity.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ApiLayers/Schemas/rules/rules.py" beforeDir="false" afterPath="$PROJECT_DIR$/ApiLayers/Schemas/rules/rules.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/DockerApiServices/AuthServiceApi/app_handler.py" beforeDir="false" afterPath="$PROJECT_DIR$/DockerApiServices/AuthServiceApi/app_handler.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/DockerApiServices/AuthServiceApi/config.py" beforeDir="false" afterPath="$PROJECT_DIR$/DockerApiServices/AuthServiceApi/config.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/DockerApiServices/AuthServiceApi/create_routes.py" beforeDir="false" afterPath="$PROJECT_DIR$/DockerApiServices/AuthServiceApi/create_routes.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/DockerApiServices/AuthServiceApi/create_routes.py" beforeDir="false" afterPath="$PROJECT_DIR$/DockerApiServices/AuthServiceApi/create_routes.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/DockerApiServices/AuthServiceApi/open_api_creator.py" beforeDir="false" afterPath="$PROJECT_DIR$/DockerApiServices/AuthServiceApi/open_api_creator.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/DockerApiServices/EventServiceApi/app_handler.py" beforeDir="false" afterPath="$PROJECT_DIR$/DockerApiServices/EventServiceApi/app_handler.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/DockerApiServices/EventServiceApi/config.py" beforeDir="false" afterPath="$PROJECT_DIR$/DockerApiServices/EventServiceApi/config.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/DockerApiServices/EventServiceApi/create_routes.py" beforeDir="false" afterPath="$PROJECT_DIR$/DockerApiServices/EventServiceApi/create_routes.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/DockerApiServices/EventServiceApi/open_api_creator.py" beforeDir="false" afterPath="$PROJECT_DIR$/DockerApiServices/EventServiceApi/open_api_creator.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/DockerApiServices/ValidationServiceApi/app_handler.py" beforeDir="false" afterPath="$PROJECT_DIR$/DockerApiServices/ValidationServiceApi/app_handler.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/DockerApiServices/ValidationServiceApi/config.py" beforeDir="false" afterPath="$PROJECT_DIR$/DockerApiServices/ValidationServiceApi/config.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/DockerApiServices/ValidationServiceApi/create_routes.py" beforeDir="false" afterPath="$PROJECT_DIR$/DockerApiServices/ValidationServiceApi/create_routes.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/DockerApiServices/ValidationServiceApi/open_api_creator.py" beforeDir="false" afterPath="$PROJECT_DIR$/DockerApiServices/ValidationServiceApi/open_api_creator.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Events/AllEvents/authentication/auth/api_events.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/AllEvents/authentication/auth/api_events.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Events/AllEvents/authentication/auth/auth.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/AllEvents/authentication/auth/auth.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/Events/AllEvents/authentication/auth/auth.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/AllEvents/authentication/auth/auth.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Events/AllEvents/authentication/auth/function_handlers.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/AllEvents/authentication/auth/function_handlers.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/Events/AllEvents/authentication/auth/function_handlers.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/AllEvents/authentication/auth/function_handlers.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Events/AllEvents/authentication/auth/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/AllEvents/authentication/auth/models.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Events/AllEvents/events/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/AllEvents/events/__init__.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Events/AllEvents/events_file.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/AllEvents/events_file.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Events/Engine/abstract_class.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/Engine/abstract_class.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Events/Engine/set_defaults/category_cluster_models.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/Engine/set_defaults/category_cluster_models.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Events/Engine/set_defaults/prepare_redis_items.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/Engine/set_defaults/prepare_redis_items.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Events/Engine/set_defaults/run.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/Engine/set_defaults/run.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Events/Engine/set_defaults/setClusters.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/Engine/set_defaults/setClusters.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Events/base_request_model.py" beforeDir="false" afterPath="$PROJECT_DIR$/Events/base_request_model.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Services/PostgresDb/Models/filter_functions.py" beforeDir="false" afterPath="$PROJECT_DIR$/Services/PostgresDb/Models/filter_functions.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/Services/PostgresDb/Models/filter_functions.py" beforeDir="false" afterPath="$PROJECT_DIR$/Services/PostgresDb/Models/filter_functions.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Services/PostgresDb/Models/mixin.py" beforeDir="false" afterPath="$PROJECT_DIR$/Services/PostgresDb/Models/mixin.py" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />

View File

@ -13,7 +13,7 @@ class PasswordModule:
return str(uuid.uuid4()) if str_std else uuid.uuid4() return str(uuid.uuid4()) if str_std else uuid.uuid4()
@staticmethod @staticmethod
def generate_token(length=32): def generate_token(length=32) -> str:
letters = "abcdefghijklmnopqrstuvwxyz" letters = "abcdefghijklmnopqrstuvwxyz"
merged_letters = [letter for letter in letters] + [ merged_letters = [letter for letter in letters] + [
letter.upper() for letter in letters letter.upper() for letter in letters
@ -27,17 +27,17 @@ class PasswordModule:
return token_generated return token_generated
@staticmethod @staticmethod
def generate_access_token(): def generate_access_token() -> str:
return secrets.token_urlsafe(Auth.ACCESS_TOKEN_LENGTH) return secrets.token_urlsafe(Auth.ACCESS_TOKEN_LENGTH)
@staticmethod @staticmethod
def generate_refresher_token(): def generate_refresher_token() -> str:
return secrets.token_urlsafe(Auth.REFRESHER_TOKEN_LENGTH) return secrets.token_urlsafe(Auth.REFRESHER_TOKEN_LENGTH)
@staticmethod @staticmethod
def create_hashed_password(domain: str, id_: str, password: str): def create_hashed_password(domain: str, id_: str, password: str) -> str:
return hashlib.sha256(f"{domain}:{id_}:{password}".encode("utf-8")).hexdigest() return hashlib.sha256(f"{domain}:{id_}:{password}".encode("utf-8")).hexdigest()
@classmethod @classmethod
def check_password(cls, domain, id_, password, password_hashed): def check_password(cls, domain, id_, password, password_hashed) -> bool:
return cls.create_hashed_password(domain, id_, password) == password_hashed return cls.create_hashed_password(domain, id_, password) == password_hashed

View File

@ -20,14 +20,17 @@ class CreateEndpointFromCluster:
def attach_router(self): def attach_router(self):
method = getattr(self.router, self.method_endpoint.METHOD.lower()) method = getattr(self.router, self.method_endpoint.METHOD.lower())
# Create a unique operation ID based on the endpoint path, method, and a unique identifier # Create a unique operation ID based on the endpoint path, method, and a unique identifier
kwargs = { kwargs = {
"path": self.method_endpoint.URL, "path": self.method_endpoint.URL,
"summary": self.method_endpoint.SUMMARY, "summary": self.method_endpoint.SUMMARY,
"description": self.method_endpoint.DESCRIPTION, "description": self.method_endpoint.DESCRIPTION,
} }
if hasattr(self.method_endpoint, 'RESPONSE_MODEL') and self.method_endpoint.RESPONSE_MODEL is not None: if (
hasattr(self.method_endpoint, "RESPONSE_MODEL")
and self.method_endpoint.RESPONSE_MODEL is not None
):
kwargs["response_model"] = self.method_endpoint.RESPONSE_MODEL kwargs["response_model"] = self.method_endpoint.RESPONSE_MODEL
method(**kwargs)(self.method_endpoint.endpoint_callable) method(**kwargs)(self.method_endpoint.endpoint_callable)

View File

@ -2,4 +2,3 @@ from Services.Redis import RedisActions, AccessToken
from Services.Redis.Models.cluster import RedisList from Services.Redis.Models.cluster import RedisList
redis_list = RedisList(redis_key="test") redis_list = RedisList(redis_key="test")

View File

@ -1,9 +1,7 @@
from typing import Any, Dict
from ApiLayers.ErrorHandlers import HTTPExceptionApi
from ApiLayers.ApiValidations.Request.authentication import Login from ApiLayers.ApiValidations.Request.authentication import Login
from ApiLayers.ApiLibrary.token.password_module import PasswordModule from ApiLayers.ApiLibrary.token.password_module import PasswordModule
from ApiLayers.ApiLibrary.common.line_number import get_line_number_for_error from ApiLayers.ApiLibrary.common.line_number import get_line_number_for_error
from ApiLayers.ErrorHandlers import HTTPExceptionApi
class UserLoginModule: class UserLoginModule:
@ -11,13 +9,27 @@ class UserLoginModule:
def __init__(self, request: "Request"): def __init__(self, request: "Request"):
self.request = request self.request = request
self.user = None self.user = None
self.access_object = None
self.access_token = None
self.refresh_token = None
@property
def as_dict(self) -> dict:
return {
"user": self.user,
"access_object": self.access_object,
"access_token": self.access_token,
"refresh_token": self.refresh_token,
}
@staticmethod @staticmethod
def check_user_exists(access_key: str): def check_user_exists(access_key: str):
from ApiLayers.Schemas import Users from ApiLayers.Schemas import Users
"""Check if user exists.""" """
db_session = Users.new_session() Check if the user exists in the database.
"""
db_session = Users.new_session() # Check if user exists.
if "@" in access_key: if "@" in access_key:
found_user: Users = Users.filter_one( found_user: Users = Users.filter_one(
Users.email == access_key.lower(), db=db_session Users.email == access_key.lower(), db=db_session
@ -31,39 +43,48 @@ class UserLoginModule:
error_code="HTTP_400_BAD_REQUEST", error_code="HTTP_400_BAD_REQUEST",
lang="en", lang="en",
loc=get_line_number_for_error(), loc=get_line_number_for_error(),
sys_msg="User not found", sys_msg="check_user_exists: User not found",
) )
return found_user return found_user
def login_user_via_credentials(self, access_data: "Login") -> Dict[str, Any]: def login_user_via_credentials(self, access_data: "Login") -> None:
from ApiLayers.ApiServices.Token.token_handler import TokenService from ApiLayers.ApiServices.Token.token_handler import TokenService
from ApiLayers.Schemas import Users from ApiLayers.Schemas import Users
"""
Login the user via the credentials.
"""
# Get the actual data from the BaseRequestModel if needed # Get the actual data from the BaseRequestModel if needed
found_user: Users = self.check_user_exists(access_key=access_data.access_key) found_user: Users = self.check_user_exists(access_key=access_data.access_key)
self.user = found_user
if len(found_user.hash_password) < 5: if len(found_user.hash_password) < 5:
raise HTTPExceptionApi( raise HTTPExceptionApi(
error_code="HTTP_400_BAD_REQUEST", error_code="HTTP_400_BAD_REQUEST",
lang=found_user.lang, lang=found_user.lang,
loc=get_line_number_for_error(), loc=get_line_number_for_error(),
sys_msg="Invalid password create a password to user first", sys_msg="login_user_via_credentials: Invalid password create a password to user first",
) )
# Check if the password is correct
if PasswordModule.check_password( if PasswordModule.check_password(
domain=access_data.domain, domain=access_data.domain, id_=found_user.uu_id,
id_=found_user.uu_id, password=access_data.password, password_hashed=found_user.hash_password,
password=access_data.password,
password_hashed=found_user.hash_password,
): ):
return TokenService.set_access_token_to_redis( # Set the access token to the redis
request=self.request, token_response = TokenService.set_access_token_to_redis(
user=found_user, request=self.request, user=found_user, domain=access_data.domain, remember=access_data.remember_me,
domain=access_data.domain,
remember=access_data.remember_me,
) )
# Set the user and token information to the instance
self.user = found_user.get_dict()
self.access_token = token_response.get("access_token")
self.refresh_token = token_response.get("refresh_token")
self.access_object = {
"user_type": token_response.get("user_type", None),
"selection_list": token_response.get("selection_list", {})
}
return None
raise HTTPExceptionApi( raise HTTPExceptionApi(
error_code="HTTP_400_BAD_REQUEST", error_code="HTTP_400_BAD_REQUEST",
lang=found_user.lang, lang="tr",
loc=get_line_number_for_error(), loc=get_line_number_for_error(),
sys_msg="login_user_via_credentials raised error", sys_msg="login_user_via_credentials: raised an unknown error",
) )

View File

@ -250,7 +250,7 @@ class TokenService:
return { return {
"access_token": access_token, "access_token": access_token,
"user_type": UserType.employee.name, "user_type": UserType.employee.name,
"companies_list": companies_list, "selection_list": companies_list,
} }
raise HTTPExceptionApi( raise HTTPExceptionApi(
error_code="", error_code="",
@ -264,8 +264,8 @@ class TokenService:
"""Remove all tokens for a user with specific domain.""" """Remove all tokens for a user with specific domain."""
redis_rows = cls._get_user_tokens(user) redis_rows = cls._get_user_tokens(user)
for redis_row in redis_rows.all: for redis_row in redis_rows.all:
if redis_row.data.get("domain") == domain: if redis_row.row.get("domain") == domain:
RedisActions.delete_key(redis_row.key) redis_row.delete()
@classmethod @classmethod
def remove_all_token(cls, user: Users) -> None: def remove_all_token(cls, user: Users) -> None:

View File

@ -2,17 +2,27 @@ from typing import Optional, Any
from pydantic import BaseModel from pydantic import BaseModel
class DefaultContext(BaseModel): class DefaultContext(BaseModel): ...
...
class EventContext(DefaultContext): class EventContext(DefaultContext):
auth: Any auth: Any
code: str code: str
url: str url: str
request: Optional[Any] = None
@property
def base(self) -> dict[str, Any]:
return {"url": self.url, "code": self.code}
class AuthContext(DefaultContext): class AuthContext(DefaultContext):
auth: Any auth: Any
url: str url: str
request: Optional[Any] = None
@property
def base(self) -> dict[str, Any]:
return {"url": self.url}

View File

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

View File

@ -15,85 +15,85 @@ class BaseEndpointResponse:
from ApiLayers.AllConfigs.Redis.configs import RedisValidationKeys from ApiLayers.AllConfigs.Redis.configs import RedisValidationKeys
language_model_key = f"{RedisValidationKeys.LANGUAGE_MODELS}:{RedisValidationKeys.RESPONSES}" language_model_key = f"{RedisValidationKeys.LANGUAGE_MODELS}:{RedisValidationKeys.RESPONSES}"
language_model = RedisActions.get_json(list_keys=[language_model_key, self.code , self.lang]) language_model = RedisActions.get_json(list_keys=[language_model_key, self.code, self.lang])
if language_model.status: if language_model.status:
return language_model.first.as_dict return language_model.first.as_dict
raise ValueError("Language model not found") return {"message": f"{self.code} -> Language model not found"}
class EndpointSuccessResponse(BaseEndpointResponse): # 1. 200 OK class EndpointSuccessResponse(BaseEndpointResponse): # 200 OK
def as_dict(self, data: Optional[dict] = None): def as_dict(self, data: Optional[dict] = None):
return JSONResponse( return JSONResponse(
status_code=status.HTTP_200_OK, status_code=status.HTTP_200_OK,
content=dict(completed=True, lang=self.lang, data=data, **self.response) content=dict(completed=True, **self.response, lang=self.lang, data=data),
) )
class EndpointCreatedResponse(BaseEndpointResponse): # 2. 201 Created class EndpointCreatedResponse(BaseEndpointResponse): # 201 Created
def as_dict(self, data: Optional[dict] = None): def as_dict(self, data: Optional[dict] = None):
return JSONResponse( return JSONResponse(
status_code=status.HTTP_201_CREATED, status_code=status.HTTP_201_CREATED,
content=dict(completed=True, lang=self.lang, data=data, **self.response) content=dict(completed=True, **self.response, lang=self.lang, data=data),
) )
class EndpointAcceptedResponse(BaseEndpointResponse): # 3. 202 Accepted class EndpointAcceptedResponse(BaseEndpointResponse): # 202 Accepted
def as_dict(self, data: Optional[dict] = None): def as_dict(self, data: Optional[dict] = None):
return JSONResponse( return JSONResponse(
status_code=status.HTTP_202_ACCEPTED, status_code=status.HTTP_202_ACCEPTED,
content=dict(completed=True, lang=self.lang, data=data, **self.response) content=dict(completed=True, **self.response, lang=self.lang, data=data),
) )
class EndpointBadRequestResponse(BaseEndpointResponse): # 4. 400 Bad Request class EndpointBadRequestResponse(BaseEndpointResponse): # 400 Bad Request
def as_dict(self, data: Optional[dict] = None): def as_dict(self, data: Optional[dict] = None):
return JSONResponse( return JSONResponse(
status_code=status.HTTP_400_BAD_REQUEST, status_code=status.HTTP_400_BAD_REQUEST,
content=dict(completed=False, lang=self.lang, data=data, **self.response) content=dict(completed=False, **self.response, lang=self.lang, data=data),
) )
class EndpointUnauthorizedResponse(BaseEndpointResponse): # 5. 401 Unauthorized class EndpointUnauthorizedResponse(BaseEndpointResponse): # 401 Unauthorized
def as_dict(self): def as_dict(self):
return JSONResponse( return JSONResponse(
status_code=status.HTTP_401_UNAUTHORIZED, status_code=status.HTTP_401_UNAUTHORIZED,
content=dict(completed=False, lang=self.lang, **self.response) content=dict(completed=False, **self.response, lang=self.lang),
) )
class EndpointNotFoundResponse(BaseEndpointResponse): # 6. 404 Not Found class EndpointNotFoundResponse(BaseEndpointResponse): # 404 Not Found
def as_dict(self): def as_dict(self):
return JSONResponse( return JSONResponse(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
content=dict(completed=False, lang=self.lang, **self.response) content=dict(completed=False, **self.response, lang=self.lang),
) )
class EndpointForbiddenResponse(BaseEndpointResponse): # 3. 403 Forbidden class EndpointForbiddenResponse(BaseEndpointResponse): # 403 Forbidden
def as_dict(self): def as_dict(self):
return JSONResponse( return JSONResponse(
status_code=status.HTTP_403_FORBIDDEN, status_code=status.HTTP_403_FORBIDDEN,
content=dict(completed=False, lang=self.lang, **self.response) content=dict(completed=False, **self.response, lang=self.lang),
) )
class EndpointConflictResponse(BaseEndpointResponse): # 6. 409 Conflict class EndpointConflictResponse(BaseEndpointResponse): # 409 Conflict
def as_dict(self): def as_dict(self):
return JSONResponse( return JSONResponse(
status_code=status.HTTP_409_CONFLICT, status_code=status.HTTP_409_CONFLICT,
content=dict(completed=False, lang=self.lang, **self.response) content=dict(completed=False, **self.response, lang=self.lang),
) )
class EndpointTooManyRequestsResponse(BaseEndpointResponse): # 7. 429 Too Many Requests class EndpointTooManyRequestsResponse(BaseEndpointResponse): # 429 Too Many Requests
def __init__(self, retry_after: int, lang: str, code: str): def __init__(self, retry_after: int, lang: str, code: str):
super().__init__(lang=lang, code=code) super().__init__(lang=lang, code=code)
@ -103,16 +103,16 @@ class EndpointTooManyRequestsResponse(BaseEndpointResponse): # 7. 429 Too Ma
return JSONResponse( return JSONResponse(
status_code=status.HTTP_429_TOO_MANY_REQUESTS, status_code=status.HTTP_429_TOO_MANY_REQUESTS,
headers={"Retry-After": str(self.retry_after)}, headers={"Retry-After": str(self.retry_after)},
content=dict(completed=False, lang=self.lang, **self.response) content=dict(completed=False, **self.response, lang=self.lang),
) )
class EndpointInternalErrorResponse(BaseEndpointResponse): # 7. 500 Internal Server Error class EndpointInternalErrorResponse(BaseEndpointResponse): # 500 Internal Server Error
def as_dict(self): def as_dict(self):
return JSONResponse( return JSONResponse(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
content=dict(completed=False, lang=self.lang, **self.response) content=dict(completed=False, **self.response, lang=self.lang),
) )
@ -121,5 +121,5 @@ class EndpointErrorResponse(BaseEndpointResponse):
def as_dict(self): def as_dict(self):
return JSONResponse( return JSONResponse(
status_code=status.HTTP_304_NOT_MODIFIED, status_code=status.HTTP_304_NOT_MODIFIED,
content=dict(completed=False, lang=self.lang, **self.response) content=dict(completed=False, **self.response, lang=self.lang),
) )

View File

@ -1,9 +1,17 @@
from Services.Redis.Actions.actions import RedisActions from Services.Redis.Actions.actions import RedisActions
from ApiLayers.AllConfigs.Redis.configs import RedisValidationKeys
class HTTPExceptionApi(Exception): class HTTPExceptionApi(Exception):
def __init__(self, error_code: str, lang: str, loc: str = "", sys_msg: str = ""): def __init__(self, error_code: str, lang: str, loc: str = "", sys_msg: str = ""):
"""
Initialize the HTTPExceptionApi class.
:param error_code: The error code. To retrieve the error message.
:param lang: The language. Catch error msg from redis.
:param loc: The location. To log where error occurred.
:param sys_msg: The system message. To log the error message.
"""
self.error_code = error_code self.error_code = error_code
self.lang = lang self.lang = lang
self.loc = loc self.loc = loc
@ -13,6 +21,12 @@ class HTTPExceptionApi(Exception):
""" """
Retrieve the error message from the redis by the error code. Retrieve the error message from the redis by the error code.
""" """
error_msg = RedisActions.get_json(list_keys=["LANGUAGE_MODELS", "ERRORCODES", self.lang]) error_redis_key = (
if error_msg.status: f"{RedisValidationKeys.LANGUAGE_MODELS}:{RedisValidationKeys.ERRORCODES}"
return error_msg.first )
error_message = RedisActions.get_json(list_keys=[error_redis_key, self.lang])
if error_message.status:
error_message_dict = error_message.first.as_dict
if error_message_dict.get(self.error_code, None):
return error_message_dict.get(self.error_code)
return f"System Message -> {self.sys_msg}"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,3 +0,0 @@
from .merge_all_error_languages import MergedErrorLanguageModels
__all__ = ["MergedErrorLanguageModels"]

View File

@ -92,11 +92,12 @@ class MiddlewareModule:
auth_context = AuthContext( auth_context = AuthContext(
auth={"token": {"access_token": "", "refresher_token": "", "context": {}}}, auth={"token": {"access_token": "", "refresher_token": "", "context": {}}},
url=endpoint_url, url=endpoint_url,
request=request,
) )
# Set auth context on the wrapper function itself # Set auth context on the wrapper function itself
setattr(func, 'auth_context', auth_context) setattr(func, "auth_context", auth_context)
setattr(wrapper, 'auth_context', auth_context) setattr(wrapper, "auth_context", auth_context)
# Call the original endpoint function # Call the original endpoint function
if inspect.iscoroutinefunction(func): if inspect.iscoroutinefunction(func):
@ -105,10 +106,11 @@ class MiddlewareModule:
result = func(request, *args, **kwargs) result = func(request, *args, **kwargs)
# Set auth context on the wrapper function itself # Set auth context on the wrapper function itself
setattr(func, 'auth_context', auth_context) setattr(func, "auth_context", auth_context)
setattr(wrapper, 'auth_context', auth_context) setattr(wrapper, "auth_context", auth_context)
return result return result
return wrapper return wrapper

View File

@ -41,7 +41,7 @@ class TokenEventMiddleware:
Returns: Returns:
Tuple[str, list[str]]: The access token and a list of reachable event codes Tuple[str, list[str]]: The access token and a list of reachable event codes
""" """
# Get token context from request # Get token context from request
access_token = TokenService.get_access_token_from_request(request_from_scope) access_token = TokenService.get_access_token_from_request(request_from_scope)
if not access_token: if not access_token:
raise HTTPExceptionApi( raise HTTPExceptionApi(
@ -50,13 +50,19 @@ class TokenEventMiddleware:
loc=get_line_number_for_error(), loc=get_line_number_for_error(),
sys_msg="Token not found", sys_msg="Token not found",
) )
# Get token context from Redis by access token and collect reachable event codes # Get token context from Redis by access token and collect reachable event codes
token_context = TokenService.get_object_via_access_key(access_token=access_token) token_context = TokenService.get_object_via_access_key(
access_token=access_token
)
if token_context.is_employee: if token_context.is_employee:
reachable_event_codes: list[str] = token_context.selected_company.reachable_event_codes reachable_event_codes: list[str] = (
token_context.selected_company.reachable_event_codes
)
elif token_context.is_occupant: elif token_context.is_occupant:
reachable_event_codes: list[str] = token_context.selected_occupant.reachable_event_codes reachable_event_codes: list[str] = (
token_context.selected_occupant.reachable_event_codes
)
else: else:
raise HTTPExceptionApi( raise HTTPExceptionApi(
error_code="", error_code="",
@ -67,12 +73,15 @@ class TokenEventMiddleware:
return token_context, reachable_event_codes return token_context, reachable_event_codes
@staticmethod @staticmethod
def retrieve_intersected_event_code(request: Request, reachable_event_codes: list[str]) -> str: def retrieve_intersected_event_code(
request: Request, reachable_event_codes: list[str]
) -> str:
""" """
Match an endpoint with accessible events. Match an endpoint with accessible events.
Args: Args:
request: The endpoint to match request: The endpoint to match
reachable_event_codes: The list of event codes accessible to the user
Returns: Returns:
Dict containing the endpoint registration data Dict containing the endpoint registration data
@ -81,9 +90,7 @@ class TokenEventMiddleware:
endpoint_url = str(request.url.path) endpoint_url = str(request.url.path)
# Get the endpoint URL for matching with events # Get the endpoint URL for matching with events
function_codes_of_endpoint = RedisActions.get_json( function_codes_of_endpoint = RedisActions.get_json(
list_keys=[ list_keys=[RedisCategoryKeys.METHOD_FUNCTION_CODES, "*", endpoint_url]
RedisCategoryKeys.METHOD_FUNCTION_CODES, "*", endpoint_url
]
) )
function_code_list_of_event = function_codes_of_endpoint.first function_code_list_of_event = function_codes_of_endpoint.first
if not function_codes_of_endpoint.status: if not function_codes_of_endpoint.status:
@ -93,9 +100,11 @@ class TokenEventMiddleware:
loc=get_line_number_for_error(), loc=get_line_number_for_error(),
sys_msg="Function code not found", sys_msg="Function code not found",
) )
# Intersect function codes with user accers objects available event codes # Intersect function codes with user accers objects available event codes
intersected_code = list(set(function_code_list_of_event) & set(reachable_event_codes)) intersected_code = list(
set(function_code_list_of_event) & set(reachable_event_codes)
)
if not len(intersected_code) == 1: if not len(intersected_code) == 1:
raise HTTPExceptionApi( raise HTTPExceptionApi(
error_code="", error_code="",
@ -122,18 +131,23 @@ class TokenEventMiddleware:
@wraps(func) @wraps(func)
async def wrapper(request: Request, *args, **kwargs) -> Dict[str, Any]: async def wrapper(request: Request, *args, **kwargs) -> Dict[str, Any]:
# Get and validate token context from request # Get and validate token context from request
# token_context, reachable_event_codes = cls.retrieve_access_content(request) # token_context, reachable_event_codes = cls.retrieve_access_content(request)
token_context, reachable_event_codes = {"token": "context", "context": {}}, ["g1j8i6j7-9k4h-0h6l-4i3j-2j0k1k0j0i0k"] reachable_event_codes = ["g1j8i6j7-9k4h-0h6l-4i3j-2j0k1k0j0i0k"]
endpoint_url, reachable_event_code = cls.retrieve_intersected_event_code(request, reachable_event_codes) token_context = {"token": "context","context": {}}
event_context = EventContext(auth=token_context, code=reachable_event_code, url=endpoint_url) endpoint_url, reachable_event_code = cls.retrieve_intersected_event_code(
request, reachable_event_codes
)
event_context = EventContext(
auth=token_context, code=reachable_event_code, url=endpoint_url, request=request,
)
# Get auth context from the authenticated function's wrapper # Get auth context from the authenticated function's wrapper
if token_context is not None: if token_context is not None:
setattr(wrapper, 'event_context', event_context) setattr(wrapper, "event_context", event_context)
setattr(func, 'event_context', event_context) setattr(func, "event_context", event_context)
# Execute the authenticated function and get its result # Execute the authenticated function and get its result
if inspect.iscoroutinefunction(func): if inspect.iscoroutinefunction(func):
result = await func(request, *args, **kwargs) result = await func(request, *args, **kwargs)
@ -179,4 +193,4 @@ class TokenEventMiddleware:
# result = func(request, *args, **kwargs) # result = func(request, *args, **kwargs)
# return result # return result
# return wrapper # return wrapper

View File

@ -24,7 +24,10 @@ from ApiLayers.ApiValidations.Request import (
UpdateBuild, UpdateBuild,
) )
from ApiLayers.ApiValidations.Custom.token_objects import EmployeeTokenObject, OccupantTokenObject from ApiLayers.ApiValidations.Custom.token_objects import (
EmployeeTokenObject,
OccupantTokenObject,
)
from ApiLayers.LanguageModels.Database.building.build import ( from ApiLayers.LanguageModels.Database.building.build import (
BuildTypesLanguageModel, BuildTypesLanguageModel,
Part2EmployeeLanguageModel, Part2EmployeeLanguageModel,

View File

@ -17,7 +17,10 @@ from sqlalchemy import (
from sqlalchemy.orm import mapped_column, relationship, Mapped from sqlalchemy.orm import mapped_column, relationship, Mapped
from ApiLayers.ApiLibrary.date_time_actions.date_functions import system_arrow from ApiLayers.ApiLibrary.date_time_actions.date_functions import system_arrow
from ApiLayers.ApiLibrary.extensions.select import SelectAction, SelectActionWithEmployee from ApiLayers.ApiLibrary.extensions.select import (
SelectAction,
SelectActionWithEmployee,
)
from ApiLayers.AllConfigs.Token.config import Auth from ApiLayers.AllConfigs.Token.config import Auth
from ApiLayers.ApiServices.Login.user_login_handler import UserLoginModule from ApiLayers.ApiServices.Login.user_login_handler import UserLoginModule
@ -138,6 +141,24 @@ class Users(CrudCollection, UserLoginModule, SelectAction):
def is_employee(self): def is_employee(self):
return str(self.email).split("@")[1] == Auth.ACCESS_EMAIL_EXT return str(self.email).split("@")[1] == Auth.ACCESS_EMAIL_EXT
@property
def user_type(self):
return "Occupant" if self.is_occupant else "Employee"
@classmethod
def credentials(cls):
db_session = cls.new_session()
person_object: People = People.filter_by_one(db=db_session, system=True, id=cls.person_id).data
if person_object:
return {
"person_id": person_object.id,
"person_uu_id": str(person_object.uu_id),
}
return {
"person_id": None,
"person_uu_id": None,
}
@property @property
def password_expiry_ends(self): def password_expiry_ends(self):
"""Calculates the expiry end date based on expiry begins and expires day""" """Calculates the expiry end date based on expiry begins and expires day"""
@ -153,16 +174,6 @@ class Users(CrudCollection, UserLoginModule, SelectAction):
) )
) )
@property
def is_super_user(self):
"""Checks if the user is a superuser based on priority code"""
return getattr(self.priority, "priority_code", 0) == 78
@property
def is_user(self):
"""Checks if the user is a regular user based on priority code"""
return getattr(self.priority, "priority_code", 0) == 0
@classmethod @classmethod
def create_action(cls, create_user: InsertUsers, token_dict): def create_action(cls, create_user: InsertUsers, token_dict):
db_session = cls.new_session() db_session = cls.new_session()
@ -192,21 +203,7 @@ class Users(CrudCollection, UserLoginModule, SelectAction):
created_user.reset_password_token(found_user=created_user) created_user.reset_password_token(found_user=created_user)
return created_user return created_user
@classmethod
def credentials(cls):
db_session = cls.new_session()
person_object = People.filter_by_one(
db=db_session, system=True, id=cls.person_id
).data
if person_object:
return {
"person_id": person_object.id,
"person_uu_id": str(person_object.uu_id),
}
return {
"person_id": None,
"person_uu_id": None,
}
def get_employee_and_duty_details(self): def get_employee_and_duty_details(self):
from Schemas import Employees, Duties from Schemas import Employees, Duties

View File

@ -1,7 +1,9 @@
from sqlalchemy import String from sqlalchemy import String
from sqlalchemy.orm import mapped_column, Mapped from sqlalchemy.orm import mapped_column, Mapped
from ApiLayers.LanguageModels.Database.rules.rules import EndpointRestrictionLanguageModel from ApiLayers.LanguageModels.Database.rules.rules import (
EndpointRestrictionLanguageModel,
)
from Services.PostgresDb import CrudCollection from Services.PostgresDb import CrudCollection

View File

@ -12,7 +12,10 @@ from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
from ApiLayers.ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi from ApiLayers.ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
from ApiLayers.Middleware.auth_middleware import RequestTimingMiddleware, LoggerTimingMiddleware from ApiLayers.Middleware.auth_middleware import (
RequestTimingMiddleware,
LoggerTimingMiddleware,
)
def setup_cors_middleware(app: FastAPI) -> None: def setup_cors_middleware(app: FastAPI) -> None:
@ -55,7 +58,9 @@ def setup_exception_handlers(app: FastAPI) -> None:
Args: Args:
app: FastAPI application instance app: FastAPI application instance
""" """
from ApiLayers.ErrorHandlers.ErrorHandlers.api_exc_handler import HTTPExceptionApiHandler from ApiLayers.ErrorHandlers.ErrorHandlers.api_exc_handler import (
HTTPExceptionApiHandler,
)
custom_exception_handler = HTTPExceptionApiHandler(response_model=JSONResponse) custom_exception_handler = HTTPExceptionApiHandler(response_model=JSONResponse)
app.add_exception_handler( app.add_exception_handler(

View File

@ -1,4 +1,3 @@
class DefaultApiConfig: class DefaultApiConfig:
app: str app: str
host: str host: str
@ -9,12 +8,12 @@ class DefaultApiConfig:
@classmethod @classmethod
def as_dict(cls): def as_dict(cls):
return { return {
"app": cls.app, "app": cls.app,
"host": cls.host, "host": cls.host,
"port": int(cls.port), "port": int(cls.port),
"log_level": cls.log_level, "log_level": cls.log_level,
"reload": bool(cls.reload), "reload": bool(cls.reload),
} }
class ApiStatic: class ApiStatic:
@ -41,7 +40,9 @@ class ApiConfig(DefaultApiConfig):
# Application Information # Application Information
APP_NAME = "evyos-auth-api-gateway" APP_NAME = "evyos-auth-api-gateway"
TITLE = "WAG API Auth Api Gateway" TITLE = "WAG API Auth Api Gateway"
DESCRIPTION = "This api is serves as web auth api gateway only to evyos web services." DESCRIPTION = (
"This api is serves as web auth api gateway only to evyos web services."
)
APP_URL = "https://www.auth.eys.gen.tr" APP_URL = "https://www.auth.eys.gen.tr"
# Server Configuration # Server Configuration
@ -65,6 +66,6 @@ class MainConfig:
class LanguageConfig: class LanguageConfig:
SUPPORTED_LANGUAGES = ["en", "tr"] SUPPORTED_LANGUAGES = ["en", "tr"]
DEFAULT_LANGUAGE = "tr" DEFAULT_LANGUAGE = "tr"

View File

@ -2,10 +2,15 @@
Route configuration and factory module. Route configuration and factory module.
Handles dynamic route creation based on configurations. Handles dynamic route creation based on configurations.
""" """
from typing import Optional from typing import Optional
from Events.Engine.set_defaults.run import get_cluster_controller_group from Events.Engine.set_defaults.run import get_cluster_controller_group
from Events.Engine.set_defaults.setClusters import PrepareRouting, SetItems2Redis, PrepareEvents from Events.Engine.set_defaults.setClusters import (
PrepareRouting,
SetItems2Redis,
PrepareEvents,
)
routers: Optional[PrepareRouting] = None routers: Optional[PrepareRouting] = None

View File

@ -32,7 +32,11 @@ class OpenAPISchemaCreator:
""" """
self.app = app self.app = app
self.cluster = get_all_routers() self.cluster = get_all_routers()
self.safe_endpoint_list = self.cluster.safe_endpoints if hasattr(self.cluster, 'safe_endpoints') else [] self.safe_endpoint_list = (
self.cluster.safe_endpoints
if hasattr(self.cluster, "safe_endpoints")
else []
)
def _create_security_schemes(self) -> Dict[str, Any]: def _create_security_schemes(self) -> Dict[str, Any]:
""" """
@ -42,6 +46,7 @@ class OpenAPISchemaCreator:
Dict[str, Any]: Security scheme configurations Dict[str, Any]: Security scheme configurations
""" """
from ApiLayers.AllConfigs.Token.config import Auth from ApiLayers.AllConfigs.Token.config import Auth
return { return {
"BearerAuth": { "BearerAuth": {
"type": "apiKey", "type": "apiKey",
@ -191,12 +196,12 @@ class OpenAPISchemaCreator:
# Check if endpoint is in safe list # Check if endpoint is in safe list
endpoint_path = f"{path}:{method}" endpoint_path = f"{path}:{method}"
if endpoint_path not in [f"{e.URL}:{e.METHOD.lower()}" for e in self.safe_endpoint_list]: 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]: if "security" not in schema["paths"][path][method]:
schema["paths"][path][method]["security"] = [] schema["paths"][path][method]["security"] = []
schema["paths"][path][method]["security"].append( schema["paths"][path][method]["security"].append({"BearerAuth": []})
{"BearerAuth": []}
)
def create_schema(self) -> Dict[str, Any]: def create_schema(self) -> Dict[str, Any]:
""" """
@ -216,8 +221,10 @@ class OpenAPISchemaCreator:
if "components" not in openapi_schema: if "components" not in openapi_schema:
openapi_schema["components"] = {} openapi_schema["components"] = {}
openapi_schema["components"]["securitySchemes"] = self._create_security_schemes() openapi_schema["components"][
"securitySchemes"
] = self._create_security_schemes()
# Configure route security and responses # Configure route security and responses
for route in self.app.routes: for route in self.app.routes:
if isinstance(route, APIRoute) and route.include_in_schema: if isinstance(route, APIRoute) and route.include_in_schema:

View File

@ -12,7 +12,10 @@ from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
from ApiLayers.ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi from ApiLayers.ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
from ApiLayers.Middleware.auth_middleware import RequestTimingMiddleware, LoggerTimingMiddleware from ApiLayers.Middleware.auth_middleware import (
RequestTimingMiddleware,
LoggerTimingMiddleware,
)
def setup_cors_middleware(app: FastAPI) -> None: def setup_cors_middleware(app: FastAPI) -> None:
@ -55,7 +58,9 @@ def setup_exception_handlers(app: FastAPI) -> None:
Args: Args:
app: FastAPI application instance app: FastAPI application instance
""" """
from ApiLayers.ErrorHandlers.ErrorHandlers.api_exc_handler import HTTPExceptionApiHandler from ApiLayers.ErrorHandlers.ErrorHandlers.api_exc_handler import (
HTTPExceptionApiHandler,
)
custom_exception_handler = HTTPExceptionApiHandler(response_model=JSONResponse) custom_exception_handler = HTTPExceptionApiHandler(response_model=JSONResponse)
app.add_exception_handler( app.add_exception_handler(

View File

@ -1,4 +1,3 @@
class DefaultApiConfig: class DefaultApiConfig:
app: str app: str
host: str host: str
@ -9,12 +8,12 @@ class DefaultApiConfig:
@classmethod @classmethod
def as_dict(cls): def as_dict(cls):
return { return {
"app": cls.app, "app": cls.app,
"host": cls.host, "host": cls.host,
"port": int(cls.port), "port": int(cls.port),
"log_level": cls.log_level, "log_level": cls.log_level,
"reload": bool(cls.reload), "reload": bool(cls.reload),
} }
class ApiStatic: class ApiStatic:
@ -32,12 +31,13 @@ class ApiStatic:
return cls.BLACKLIST_LINK + record_id return cls.BLACKLIST_LINK + record_id
class ApiConfig(DefaultApiConfig): class ApiConfig(DefaultApiConfig):
# Api configuration # Api configuration
APP_NAME = "evyos-event-api-gateway" APP_NAME = "evyos-event-api-gateway"
TITLE = "WAG API Event Api Gateway" TITLE = "WAG API Event Api Gateway"
DESCRIPTION = "This api is serves as web event api gateway only to evyos web services." DESCRIPTION = (
"This api is serves as web event api gateway only to evyos web services."
)
APP_URL = "https://www.event.eys.gen.tr" APP_URL = "https://www.event.eys.gen.tr"
# Uvicorn server configuration # Uvicorn server configuration
@ -57,4 +57,3 @@ class MainConfig:
DEFAULT_TIMEZONE = "GMT+3" # Default timezone for the application DEFAULT_TIMEZONE = "GMT+3" # Default timezone for the application
SYSTEM_TIMEZONE = "GMT+0" # System timezone (used for internal operations) SYSTEM_TIMEZONE = "GMT+0" # System timezone (used for internal operations)
SUPPORTED_TIMEZONES = ["GMT+0", "GMT+3"] # List of supported timezones SUPPORTED_TIMEZONES = ["GMT+0", "GMT+3"] # List of supported timezones

View File

@ -5,7 +5,11 @@ Handles dynamic route creation based on configurations.
from fastapi import Request from fastapi import Request
from Events.Engine.set_defaults.run import get_cluster_controller_group from Events.Engine.set_defaults.run import get_cluster_controller_group
from Events.Engine.set_defaults.setClusters import PrepareRouting, SetItems2Redis, PrepareEvents from Events.Engine.set_defaults.setClusters import (
PrepareRouting,
SetItems2Redis,
PrepareEvents,
)
routers = None routers = None

View File

@ -32,7 +32,11 @@ class OpenAPISchemaCreator:
""" """
self.app = app self.app = app
self.cluster = get_all_routers() self.cluster = get_all_routers()
self.safe_endpoint_list = self.cluster.safe_endpoints if hasattr(self.cluster, 'safe_endpoints') else [] self.safe_endpoint_list = (
self.cluster.safe_endpoints
if hasattr(self.cluster, "safe_endpoints")
else []
)
def _create_security_schemes(self) -> Dict[str, Any]: def _create_security_schemes(self) -> Dict[str, Any]:
""" """
@ -42,6 +46,7 @@ class OpenAPISchemaCreator:
Dict[str, Any]: Security scheme configurations Dict[str, Any]: Security scheme configurations
""" """
from ApiLayers.AllConfigs.Token.config import Auth from ApiLayers.AllConfigs.Token.config import Auth
return { return {
"BearerAuth": { "BearerAuth": {
"type": "apiKey", "type": "apiKey",
@ -191,12 +196,12 @@ class OpenAPISchemaCreator:
# Check if endpoint is in safe list # Check if endpoint is in safe list
endpoint_path = f"{path}:{method}" endpoint_path = f"{path}:{method}"
if endpoint_path not in [f"{e.URL}:{e.METHOD.lower()}" for e in self.safe_endpoint_list]: 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]: if "security" not in schema["paths"][path][method]:
schema["paths"][path][method]["security"] = [] schema["paths"][path][method]["security"] = []
schema["paths"][path][method]["security"].append( schema["paths"][path][method]["security"].append({"BearerAuth": []})
{"BearerAuth": []}
)
def create_schema(self) -> Dict[str, Any]: def create_schema(self) -> Dict[str, Any]:
""" """
@ -216,8 +221,10 @@ class OpenAPISchemaCreator:
if "components" not in openapi_schema: if "components" not in openapi_schema:
openapi_schema["components"] = {} openapi_schema["components"] = {}
openapi_schema["components"]["securitySchemes"] = self._create_security_schemes() openapi_schema["components"][
"securitySchemes"
] = self._create_security_schemes()
# Configure route security and responses # Configure route security and responses
for route in self.app.routes: for route in self.app.routes:
if isinstance(route, APIRoute) and route.include_in_schema: if isinstance(route, APIRoute) and route.include_in_schema:

View File

@ -12,7 +12,10 @@ from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
from ApiLayers.ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi from ApiLayers.ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
from ApiLayers.Middleware.auth_middleware import RequestTimingMiddleware, LoggerTimingMiddleware from ApiLayers.Middleware.auth_middleware import (
RequestTimingMiddleware,
LoggerTimingMiddleware,
)
def setup_cors_middleware(app: FastAPI) -> None: def setup_cors_middleware(app: FastAPI) -> None:
@ -55,7 +58,9 @@ def setup_exception_handlers(app: FastAPI) -> None:
Args: Args:
app: FastAPI application instance app: FastAPI application instance
""" """
from ApiLayers.ErrorHandlers.ErrorHandlers.api_exc_handler import HTTPExceptionApiHandler from ApiLayers.ErrorHandlers.ErrorHandlers.api_exc_handler import (
HTTPExceptionApiHandler,
)
custom_exception_handler = HTTPExceptionApiHandler(response_model=JSONResponse) custom_exception_handler = HTTPExceptionApiHandler(response_model=JSONResponse)
app.add_exception_handler( app.add_exception_handler(

View File

@ -1,4 +1,3 @@
class DefaultApiConfig: class DefaultApiConfig:
app: str app: str
host: str host: str
@ -9,12 +8,12 @@ class DefaultApiConfig:
@classmethod @classmethod
def as_dict(cls): def as_dict(cls):
return { return {
"app": cls.app, "app": cls.app,
"host": cls.host, "host": cls.host,
"port": int(cls.port), "port": int(cls.port),
"log_level": cls.log_level, "log_level": cls.log_level,
"reload": bool(cls.reload), "reload": bool(cls.reload),
} }
class ApiStatic: class ApiStatic:
@ -36,7 +35,9 @@ class ApiConfig(DefaultApiConfig):
# Api configuration # Api configuration
APP_NAME = "evyos-validation-api-gateway" APP_NAME = "evyos-validation-api-gateway"
TITLE = "WAG API Validation Api Gateway" TITLE = "WAG API Validation Api Gateway"
DESCRIPTION = "This api is serves as web validation api gateway only to evyos web services." DESCRIPTION = (
"This api is serves as web validation api gateway only to evyos web services."
)
APP_URL = "https://www.validation.eys.gen.tr" APP_URL = "https://www.validation.eys.gen.tr"
# App configuration # App configuration
app = "app:app" app = "app:app"
@ -55,4 +56,3 @@ class MainConfig:
DEFAULT_TIMEZONE = "GMT+3" # Default timezone for the application DEFAULT_TIMEZONE = "GMT+3" # Default timezone for the application
SYSTEM_TIMEZONE = "GMT+0" # System timezone (used for internal operations) SYSTEM_TIMEZONE = "GMT+0" # System timezone (used for internal operations)
SUPPORTED_TIMEZONES = ["GMT+0", "GMT+3"] # List of supported timezones SUPPORTED_TIMEZONES = ["GMT+0", "GMT+3"] # List of supported timezones

View File

@ -29,5 +29,3 @@ def get_all_routers() -> PrepareRouting:
cluster_list = get_cluster_controller_group() cluster_list = get_cluster_controller_group()
prepare_routing = PrepareRouting(cluster_controller_group=cluster_list) prepare_routing = PrepareRouting(cluster_controller_group=cluster_list)
return prepare_routing return prepare_routing

View File

@ -32,7 +32,11 @@ class OpenAPISchemaCreator:
""" """
self.app = app self.app = app
self.cluster = get_all_routers() self.cluster = get_all_routers()
self.safe_endpoint_list = self.cluster.safe_endpoints if hasattr(self.cluster, 'safe_endpoints') else [] self.safe_endpoint_list = (
self.cluster.safe_endpoints
if hasattr(self.cluster, "safe_endpoints")
else []
)
def _create_security_schemes(self) -> Dict[str, Any]: def _create_security_schemes(self) -> Dict[str, Any]:
""" """
@ -42,6 +46,7 @@ class OpenAPISchemaCreator:
Dict[str, Any]: Security scheme configurations Dict[str, Any]: Security scheme configurations
""" """
from ApiLayers.AllConfigs.Token.config import Auth from ApiLayers.AllConfigs.Token.config import Auth
return { return {
"BearerAuth": { "BearerAuth": {
"type": "apiKey", "type": "apiKey",
@ -191,12 +196,12 @@ class OpenAPISchemaCreator:
# Check if endpoint is in safe list # Check if endpoint is in safe list
endpoint_path = f"{path}:{method}" endpoint_path = f"{path}:{method}"
if endpoint_path not in [f"{e.URL}:{e.METHOD.lower()}" for e in self.safe_endpoint_list]: 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]: if "security" not in schema["paths"][path][method]:
schema["paths"][path][method]["security"] = [] schema["paths"][path][method]["security"] = []
schema["paths"][path][method]["security"].append( schema["paths"][path][method]["security"].append({"BearerAuth": []})
{"BearerAuth": []}
)
def create_schema(self) -> Dict[str, Any]: def create_schema(self) -> Dict[str, Any]:
""" """
@ -216,8 +221,10 @@ class OpenAPISchemaCreator:
if "components" not in openapi_schema: if "components" not in openapi_schema:
openapi_schema["components"] = {} openapi_schema["components"] = {}
openapi_schema["components"]["securitySchemes"] = self._create_security_schemes() openapi_schema["components"][
"securitySchemes"
] = self._create_security_schemes()
# Configure route security and responses # Configure route security and responses
for route in self.app.routes: for route in self.app.routes:
if isinstance(route, APIRoute) and route.include_in_schema: if isinstance(route, APIRoute) and route.include_in_schema:

View File

@ -1,56 +1,39 @@
from Events.Engine.abstract_class import Event from Events.Engine.abstract_class import Event
from .models import ( from .models import AuthenticationRequestModels, AuthenticationResponseModels
LoginSuperUserRequestModel, from .function_handlers import AuthenticationFunctions
LoginSuperUserResponseModel,
SelectCompanyOrOccupantTypeSuperUserRequestModel,
SelectCompanyOrOccupantTypeSuperUserResponseModel,
EmployeeSelectionSuperUserRequestModel,
EmployeeSelectionSuperUserResponseModel,
OccupantSelectionSuperUserRequestModel,
OccupantSelectionSuperUserResponseModel,
)
from .function_handlers import (
authentication_login_with_domain_and_creds,
authentication_select_company_or_occupant_type,
authentication_check_token_is_valid,
authentication_refresh_user_info,
authentication_change_password,
authentication_create_password,
authentication_disconnect_user,
authentication_logout_user,
authentication_refresher_token,
authentication_forgot_password,
authentication_reset_password,
authentication_download_avatar,
)
# Auth Login # Auth Login
authentication_login_super_user_event = Event( authentication_login_super_user_event = Event(
name="authentication_login_super_user_event", name="authentication_login_super_user_event",
key="a5d2d0d1-3e9b-4b0f-8c7d-6d4a4b4c4d4e", key="a5d2d0d1-3e9b-4b0f-8c7d-6d4a4b4c4d4e",
request_validator=LoginSuperUserRequestModel, request_validator=AuthenticationRequestModels.LoginSuperUserRequestModel,
# response_validator=LoginSuperUserResponseModel, # response_validator=LoginSuperUserResponseModel,
description="Login super user", description="Login super user",
) )
authentication_login_super_user_event.endpoint_callable = ( authentication_login_super_user_event.endpoint_callable = (
authentication_login_with_domain_and_creds AuthenticationFunctions.authentication_login_with_domain_and_creds
) )
# Auth Select Company or Occupant Type # Auth Select Company or Occupant Type
authentication_select_company_or_occupant_type_super_user_event = Event( authentication_select_super_user_event = Event(
name="authentication_select_company_or_occupant_type_super_user_event", name="authentication_select_super_user_event",
key="a5d2d0d1-3e9b-4b0f-8c7d-6d4a4b4c4d4e", key="a5d2d0d1-3e9b-4b0f-8c7d-6d4a4b4c4d4e",
request_validator=SelectCompanyOrOccupantTypeSuperUserRequestModel, request_validator=AuthenticationRequestModels.SelectCompanyOrOccupantTypeSuperUserRequestModel,
# response_validator=SelectCompanyOrOccupantTypeSuperUserResponseModel, # response_validator=SelectCompanyOrOccupantTypeSuperUserResponseModel,
description="Select company or occupant type super user", description="Select company or occupant type super user",
) )
authentication_select_company_or_occupant_type_super_user_event.endpoint_callable = (
authentication_select_company_or_occupant_type
authentication_select_super_user_event.endpoint_callable = (
AuthenticationFunctions.authentication_select_company_or_occupant_type
) )
# Check Token Validity # Check Token Validity
authentication_check_token_event = Event( authentication_check_token_event = Event(
name="authentication_check_token_event", name="authentication_check_token_event",
@ -59,7 +42,12 @@ authentication_check_token_event = Event(
# response_validator=None, # TODO: Add response validator # response_validator=None, # TODO: Add response validator
description="Check if token is valid", description="Check if token is valid",
) )
authentication_check_token_event.endpoint_callable = authentication_check_token_is_valid
authentication_check_token_event.endpoint_callable = (
AuthenticationFunctions.authentication_check_token_is_valid
)
# Refresh User Info # Refresh User Info
authentication_refresh_user_info_event = Event( authentication_refresh_user_info_event = Event(
@ -69,10 +57,13 @@ authentication_refresh_user_info_event = Event(
# response_validator=None, # TODO: Add response validator # response_validator=None, # TODO: Add response validator
description="Refresh user information", description="Refresh user information",
) )
authentication_refresh_user_info_event.endpoint_callable = ( authentication_refresh_user_info_event.endpoint_callable = (
authentication_refresh_user_info AuthenticationFunctions.authentication_refresh_user_info
) )
# Change Password # Change Password
authentication_change_password_event = Event( authentication_change_password_event = Event(
name="authentication_change_password_event", name="authentication_change_password_event",
@ -81,7 +72,12 @@ authentication_change_password_event = Event(
# response_validator=None, # TODO: Add response validator # response_validator=None, # TODO: Add response validator
description="Change user password", description="Change user password",
) )
authentication_change_password_event.endpoint_callable = authentication_change_password
authentication_change_password_event.endpoint_callable = (
AuthenticationFunctions.authentication_change_password
)
# Create Password # Create Password
authentication_create_password_event = Event( authentication_create_password_event = Event(
@ -91,7 +87,12 @@ authentication_create_password_event = Event(
# response_validator=None, # TODO: Add response validator # response_validator=None, # TODO: Add response validator
description="Create new password", description="Create new password",
) )
authentication_create_password_event.endpoint_callable = authentication_create_password
authentication_create_password_event.endpoint_callable = (
AuthenticationFunctions.authentication_create_password
)
# Disconnect User # Disconnect User
authentication_disconnect_user_event = Event( authentication_disconnect_user_event = Event(
@ -101,7 +102,12 @@ authentication_disconnect_user_event = Event(
# response_validator=None, # TODO: Add response validator # response_validator=None, # TODO: Add response validator
description="Disconnect all user sessions", description="Disconnect all user sessions",
) )
authentication_disconnect_user_event.endpoint_callable = authentication_disconnect_user
authentication_disconnect_user_event.endpoint_callable = (
AuthenticationFunctions.authentication_disconnect_user
)
# Logout User # Logout User
authentication_logout_user_event = Event( authentication_logout_user_event = Event(
@ -111,7 +117,12 @@ authentication_logout_user_event = Event(
# response_validator=None, # TODO: Add response validator # response_validator=None, # TODO: Add response validator
description="Logout user session", description="Logout user session",
) )
authentication_logout_user_event.endpoint_callable = authentication_logout_user
authentication_logout_user_event.endpoint_callable = (
AuthenticationFunctions.authentication_logout_user
)
# Refresh Token # Refresh Token
authentication_refresher_token_event = Event( authentication_refresher_token_event = Event(
@ -121,7 +132,12 @@ authentication_refresher_token_event = Event(
# response_validator=None, # TODO: Add response validator # response_validator=None, # TODO: Add response validator
description="Refresh authentication token", description="Refresh authentication token",
) )
authentication_refresher_token_event.endpoint_callable = authentication_refresher_token
authentication_refresher_token_event.endpoint_callable = (
AuthenticationFunctions.authentication_refresher_token
)
# Forgot Password # Forgot Password
authentication_forgot_password_event = Event( authentication_forgot_password_event = Event(
@ -131,7 +147,12 @@ authentication_forgot_password_event = Event(
# response_validator=None, # TODO: Add response validator # response_validator=None, # TODO: Add response validator
description="Request password reset", description="Request password reset",
) )
authentication_forgot_password_event.endpoint_callable = authentication_forgot_password
authentication_forgot_password_event.endpoint_callable = (
AuthenticationFunctions.authentication_forgot_password
)
# Reset Password # Reset Password
authentication_reset_password_event = Event( authentication_reset_password_event = Event(
@ -141,7 +162,12 @@ authentication_reset_password_event = Event(
# response_validator=None, # TODO: Add response validator # response_validator=None, # TODO: Add response validator
description="Reset user password", description="Reset user password",
) )
authentication_reset_password_event.endpoint_callable = authentication_reset_password
authentication_reset_password_event.endpoint_callable = (
AuthenticationFunctions.authentication_reset_password
)
# Download Avatar # Download Avatar
authentication_download_avatar_event = Event( authentication_download_avatar_event = Event(
@ -151,4 +177,8 @@ authentication_download_avatar_event = Event(
# response_validator=None, # TODO: Add response validator # response_validator=None, # TODO: Add response validator
description="Download user avatar and profile info", description="Download user avatar and profile info",
) )
authentication_download_avatar_event.endpoint_callable = authentication_download_avatar
authentication_download_avatar_event.endpoint_callable = (
AuthenticationFunctions.authentication_download_avatar
)

View File

@ -1,19 +1,16 @@
""" """
Authentication related API endpoints. Authentication related API endpoints.
""" """
from typing import Any, Dict
from fastapi import Request
from typing import Union, Any, Dict from ApiLayers.Middleware import MiddlewareModule
from ApiLayers.ApiValidations.Custom.wrapper_contexts import AuthContext, EventContext
from ApiLayers.Middleware import MiddlewareModule, TokenEventMiddleware
from ApiLayers.ApiValidations.Request import EmployeeSelection, OccupantSelection
from Events.Engine.abstract_class import MethodToEvent from Events.Engine.abstract_class import MethodToEvent
from Events.base_request_model import EndpointBaseRequestModel from Events.base_request_model import EndpointBaseRequestModel, ContextRetrievers
from .api_events import ( from .api_events import (
authentication_login_super_user_event, authentication_login_super_user_event,
authentication_select_company_or_occupant_type_super_user_event, authentication_select_super_user_event,
authentication_check_token_event, authentication_check_token_event,
authentication_refresh_user_info_event, authentication_refresh_user_info_event,
authentication_change_password_event, authentication_change_password_event,
@ -26,12 +23,6 @@ from .api_events import (
authentication_download_avatar_event, authentication_download_avatar_event,
) )
from fastapi import Request
# Type aliases for common types
TokenDictType = Union["EmployeeTokenObject", "OccupantTokenObject"]
AuthenticationLoginEventMethods = MethodToEvent( AuthenticationLoginEventMethods = MethodToEvent(
name="AuthenticationLoginEventMethods", name="AuthenticationLoginEventMethods",
@ -48,20 +39,24 @@ AuthenticationLoginEventMethods = MethodToEvent(
def authentication_login_with_domain_and_creds_endpoint( def authentication_login_with_domain_and_creds_endpoint(
request: Request, request: Request, data: EndpointBaseRequestModel,
data: EndpointBaseRequestModel,
) -> Dict[str, Any]: ) -> Dict[str, Any]:
event_2_catch = AuthenticationLoginEventMethods.retrieve_event(event_function_code=f"{authentication_login_super_user_event.key}") event_2_catch = AuthenticationLoginEventMethods.retrieve_event(
event_function_code=f"{authentication_login_super_user_event.key}"
)
data = event_2_catch.REQUEST_VALIDATOR(**data.data) data = event_2_catch.REQUEST_VALIDATOR(**data.data)
return event_2_catch.endpoint_callable(request=request, data=data) return event_2_catch.endpoint_callable(request=request, data=data)
AuthenticationLoginEventMethods.endpoint_callable = authentication_login_with_domain_and_creds_endpoint AuthenticationLoginEventMethods.endpoint_callable = (
authentication_login_with_domain_and_creds_endpoint
)
AuthenticationSelectEventMethods = MethodToEvent( AuthenticationSelectEventMethods = MethodToEvent(
name="AuthenticationSelectEventMethods", name="AuthenticationSelectEventMethods",
events={ events={
authentication_select_company_or_occupant_type_super_user_event.key: authentication_select_company_or_occupant_type_super_user_event, authentication_select_super_user_event.key: authentication_select_super_user_event,
}, },
decorators_list=[MiddlewareModule.auth_required], decorators_list=[MiddlewareModule.auth_required],
headers=[], headers=[],
@ -72,28 +67,27 @@ AuthenticationSelectEventMethods = MethodToEvent(
description="Select company or occupant type", description="Select company or occupant type",
) )
def authentication_select_company_or_occupant_type(
request: Request, def authentication_select_company_or_occupant_type(data: EndpointBaseRequestModel) -> Dict[str, Any]:
data: EndpointBaseRequestModel,
) -> Dict[str, Any]:
""" """
Select company or occupant type. Select company or occupant type.
""" """
auth_context = authentication_select_company_or_occupant_type.auth_context context_retriever = ContextRetrievers(func=authentication_select_company_or_occupant_type)
function = AuthenticationSelectEventMethods.retrieve_event( function = AuthenticationSelectEventMethods.retrieve_event(
event_function_code=f"{authentication_select_company_or_occupant_type_super_user_event.key}" event_function_code=f"{authentication_select_super_user_event.key}"
) )
function.endpoint_callable.auth_context = auth_context setattr(function.endpoint_callable, context_retriever.key, context_retriever.context)
return function.endpoint_callable(request=request, data=data) return function.endpoint_callable(data=data)
AuthenticationSelectEventMethods.endpoint_callable = authentication_select_company_or_occupant_type AuthenticationSelectEventMethods.endpoint_callable = (
authentication_select_company_or_occupant_type
)
AuthenticationCheckTokenEventMethods = MethodToEvent( AuthenticationCheckTokenEventMethods = MethodToEvent(
name="AuthenticationCheckTokenEventMethods", name="AuthenticationCheckTokenEventMethods",
events={ events={authentication_check_token_event.key: authentication_check_token_event},
authentication_check_token_event.key: authentication_check_token_event
},
headers=[], headers=[],
errors=[], errors=[],
decorators_list=[MiddlewareModule.auth_required], decorators_list=[MiddlewareModule.auth_required],
@ -103,14 +97,20 @@ AuthenticationCheckTokenEventMethods = MethodToEvent(
description="Check if access token is valid for user", description="Check if access token is valid for user",
) )
def authentication_check_token_is_valid(request: Request):
def authentication_check_token_is_valid():
context_retriever = ContextRetrievers(func=authentication_check_token_is_valid)
function = AuthenticationCheckTokenEventMethods.retrieve_event( function = AuthenticationCheckTokenEventMethods.retrieve_event(
event_function_code=f"{authentication_check_token_event.key}" event_function_code=f"{authentication_check_token_event.key}"
) )
return function.endpoint_callable(request=request) setattr(function.endpoint_callable, context_retriever.key, context_retriever.context)
return function.endpoint_callable()
AuthenticationCheckTokenEventMethods.endpoint_callable = authentication_check_token_is_valid AuthenticationCheckTokenEventMethods.endpoint_callable = (
authentication_check_token_is_valid
)
AuthenticationRefreshEventMethods = MethodToEvent( AuthenticationRefreshEventMethods = MethodToEvent(
name="AuthenticationRefreshEventMethods", name="AuthenticationRefreshEventMethods",
@ -127,16 +127,18 @@ AuthenticationRefreshEventMethods = MethodToEvent(
) )
def authentication_refresh_user_info(request: Request): def authentication_refresh_user_info():
token_dict = authentication_refresh_user_info.auth context_retriever = ContextRetrievers(func=authentication_refresh_user_info)
function = AuthenticationRefreshEventMethods.retrieve_event( function = AuthenticationRefreshEventMethods.retrieve_event(
event_function_code=f"{authentication_refresh_user_info_event.key}" event_function_code=f"{authentication_refresh_user_info_event.key}"
) )
return function.endpoint_callable(request=request, token_dict=token_dict) setattr(function.endpoint_callable, context_retriever.key, context_retriever.context)
return function.endpoint_callable()
AuthenticationRefreshEventMethods.endpoint_callable = authentication_refresh_user_info AuthenticationRefreshEventMethods.endpoint_callable = authentication_refresh_user_info
AuthenticationChangePasswordEventMethods = MethodToEvent( AuthenticationChangePasswordEventMethods = MethodToEvent(
name="AuthenticationChangePasswordEventMethods", name="AuthenticationChangePasswordEventMethods",
events={ events={
@ -151,21 +153,23 @@ AuthenticationChangePasswordEventMethods = MethodToEvent(
description="Change password with access token", description="Change password with access token",
) )
def authentication_change_password_event_callable(request: Request, data: EndpointBaseRequestModel):
token_dict = authentication_change_password_event_callable.auth def authentication_change_password_event_callable(data: EndpointBaseRequestModel):
context_retriever = ContextRetrievers(func=authentication_change_password_event_callable)
function = AuthenticationChangePasswordEventMethods.retrieve_event( function = AuthenticationChangePasswordEventMethods.retrieve_event(
event_function_code=f"{authentication_change_password_event.key}" event_function_code=f"{authentication_change_password_event.key}"
) )
return function.endpoint_callable(data=data, token_dict=token_dict) setattr(function.endpoint_callable, context_retriever.key, context_retriever.context)
return function.endpoint_callable(data=data)
AuthenticationChangePasswordEventMethods.endpoint_callable = authentication_change_password_event_callable AuthenticationChangePasswordEventMethods.endpoint_callable = (
authentication_change_password_event_callable
)
AuthenticationCreatePasswordEventMethods = MethodToEvent( AuthenticationCreatePasswordEventMethods = MethodToEvent(
name="AuthenticationCreatePasswordEventMethods", name="AuthenticationCreatePasswordEventMethods",
events={ events={authentication_create_password_event: authentication_create_password_event},
authentication_create_password_event: authentication_create_password_event
},
headers=[], headers=[],
errors=[], errors=[],
url="/create-password", url="/create-password",
@ -174,14 +178,20 @@ AuthenticationCreatePasswordEventMethods = MethodToEvent(
description="Create password with password reset token requested via email", description="Create password with password reset token requested via email",
) )
def authentication_create_password(data: EndpointBaseRequestModel): def authentication_create_password(data: EndpointBaseRequestModel):
context_retriever = ContextRetrievers(func=authentication_create_password)
function = AuthenticationCreatePasswordEventMethods.retrieve_event( function = AuthenticationCreatePasswordEventMethods.retrieve_event(
event_function_code=f"{authentication_create_password_event.key}" event_function_code=f"{authentication_create_password_event.key}"
) )
setattr(function.endpoint_callable, context_retriever.key, context_retriever.context)
return function.endpoint_callable(data=data) return function.endpoint_callable(data=data)
AuthenticationCreatePasswordEventMethods.endpoint_callable = authentication_create_password AuthenticationCreatePasswordEventMethods.endpoint_callable = (
authentication_create_password
)
AuthenticationDisconnectUserEventMethods = MethodToEvent( AuthenticationDisconnectUserEventMethods = MethodToEvent(
name="AuthenticationDisconnectUserEventMethods", name="AuthenticationDisconnectUserEventMethods",
@ -197,22 +207,22 @@ AuthenticationDisconnectUserEventMethods = MethodToEvent(
description="Disconnect all sessions of user in access token", description="Disconnect all sessions of user in access token",
) )
def authentication_disconnect_user(request: Request, data: EndpointBaseRequestModel):
token_dict = authentication_disconnect_user.auth def authentication_disconnect_user(data: EndpointBaseRequestModel):
context_retriever = ContextRetrievers(func=authentication_disconnect_user)
function = AuthenticationDisconnectUserEventMethods.retrieve_event( function = AuthenticationDisconnectUserEventMethods.retrieve_event(
event_function_code=f"{authentication_disconnect_user_event.key}" event_function_code=f"{authentication_disconnect_user_event.key}"
) )
return function.endpoint_callable(data=data, token_dict=token_dict) setattr(function.endpoint_callable, context_retriever.key, context_retriever.context)
return function.endpoint_callable(data=data)
AuthenticationLogoutEventMethods = MethodToEvent( AuthenticationLogoutEventMethods = MethodToEvent(
name="AuthenticationLogoutEventMethods", name="AuthenticationLogoutEventMethods",
events={ events={authentication_logout_user_event.key: authentication_logout_user_event},
authentication_logout_user_event.key: authentication_logout_user_event
},
headers=[], headers=[],
errors=[], errors=[],
decorators_list=[TokenEventMiddleware.event_required], decorators_list=[MiddlewareModule.auth_required],
url="/logout", url="/logout",
method="POST", method="POST",
summary="Logout user", summary="Logout user",
@ -220,12 +230,13 @@ AuthenticationLogoutEventMethods = MethodToEvent(
) )
def authentication_logout_user(request: Request, data: EndpointBaseRequestModel): def authentication_logout_user(data: EndpointBaseRequestModel):
event_context: EventContext = getattr(authentication_logout_user, "event_context", None) context_retriever = ContextRetrievers(func=authentication_logout_user)
print('event_context', event_context) function = AuthenticationLogoutEventMethods.retrieve_event(
function = AuthenticationLogoutEventMethods.retrieve_event(event_function_code=f"{event_context.code}") event_function_code=f"{authentication_logout_user_event.key}"
function.endpoint_callable.event_context = event_context )
return function.endpoint_callable(request=request, data=data) setattr(function.endpoint_callable, context_retriever.key, context_retriever.context)
return function.endpoint_callable(data=data)
AuthenticationLogoutEventMethods.endpoint_callable = authentication_logout_user AuthenticationLogoutEventMethods.endpoint_callable = authentication_logout_user
@ -246,16 +257,18 @@ AuthenticationRefreshTokenEventMethods = MethodToEvent(
) )
def authentication_refresher_token(request: Request, data: EndpointBaseRequestModel): def authentication_refresher_token(data: EndpointBaseRequestModel):
auth_context: AuthContext = getattr(authentication_refresher_token, "auth_context", None) context_retriever = ContextRetrievers(func=authentication_refresher_token)
function = AuthenticationRefreshTokenEventMethods.retrieve_event( function = AuthenticationRefreshTokenEventMethods.retrieve_event(
event_function_code=f"{authentication_refresher_token_event.key}" event_function_code=f"{authentication_refresher_token_event.key}"
) )
function.endpoint_callable.auth_context = auth_context setattr(function.endpoint_callable, context_retriever.key, context_retriever.context)
return function.endpoint_callable(data=data, request=request) return function.endpoint_callable(data=data)
AuthenticationRefreshTokenEventMethods.endpoint_callable = authentication_refresher_token AuthenticationRefreshTokenEventMethods.endpoint_callable = (
authentication_refresher_token
)
AuthenticationForgotPasswordEventMethods = MethodToEvent( AuthenticationForgotPasswordEventMethods = MethodToEvent(
@ -272,15 +285,18 @@ AuthenticationForgotPasswordEventMethods = MethodToEvent(
) )
def authentication_forgot_password(request: Request, data: EndpointBaseRequestModel): def authentication_forgot_password(data: EndpointBaseRequestModel):
token_dict = authentication_forgot_password.auth context_retriever = ContextRetrievers(func=authentication_forgot_password)
function = AuthenticationForgotPasswordEventMethods.retrieve_event( function = AuthenticationForgotPasswordEventMethods.retrieve_event(
event_function_code=f"{authentication_forgot_password_event.key}" event_function_code=f"{authentication_forgot_password_event.key}"
) )
return function.endpoint_callable(data=data, token_dict=token_dict) setattr(function.endpoint_callable, context_retriever.key, context_retriever.context)
return function.endpoint_callable(data=data)
AuthenticationForgotPasswordEventMethods.endpoint_callable = authentication_forgot_password AuthenticationForgotPasswordEventMethods.endpoint_callable = (
authentication_forgot_password
)
AuthenticationResetPasswordEventMethods = MethodToEvent( AuthenticationResetPasswordEventMethods = MethodToEvent(
@ -299,14 +315,18 @@ AuthenticationResetPasswordEventMethods = MethodToEvent(
def authentication_reset_password(data: EndpointBaseRequestModel): def authentication_reset_password(data: EndpointBaseRequestModel):
# token_dict = authentication_reset_password.auth context_retriever = ContextRetrievers(func=authentication_reset_password)
function = AuthenticationResetPasswordEventMethods.retrieve_event( function = AuthenticationResetPasswordEventMethods.retrieve_event(
event_function_code=f"{authentication_reset_password_event.key}" event_function_code=f"{authentication_reset_password_event.key}"
) )
setattr(function.endpoint_callable, context_retriever.key, context_retriever.context)
return function.endpoint_callable(data=data) return function.endpoint_callable(data=data)
AuthenticationResetPasswordEventMethods.endpoint_callable = authentication_reset_password AuthenticationResetPasswordEventMethods.endpoint_callable = (
authentication_reset_password
)
AuthenticationDownloadAvatarEventMethods = MethodToEvent( AuthenticationDownloadAvatarEventMethods = MethodToEvent(
name="AuthenticationDownloadAvatarEventMethods", name="AuthenticationDownloadAvatarEventMethods",
@ -315,7 +335,7 @@ AuthenticationDownloadAvatarEventMethods = MethodToEvent(
}, },
headers=[], headers=[],
errors=[], errors=[],
decorators_list=[], decorators_list=[MiddlewareModule.auth_required],
url="/download-avatar", url="/download-avatar",
method="POST", method="POST",
summary="Download avatar", summary="Download avatar",
@ -323,13 +343,15 @@ AuthenticationDownloadAvatarEventMethods = MethodToEvent(
) )
@MiddlewareModule.auth_required def authentication_download_avatar():
def authentication_download_avatar(request: Request): context_retriever = ContextRetrievers(func=authentication_download_avatar)
token_dict = authentication_download_avatar.auth
function = AuthenticationDownloadAvatarEventMethods.retrieve_event( function = AuthenticationDownloadAvatarEventMethods.retrieve_event(
event_function_code=f"{authentication_download_avatar_event.key}" event_function_code=f"{authentication_download_avatar_event.key}"
) )
return function.endpoint_callable(token_dict=token_dict) setattr(function.endpoint_callable, context_retriever.key, context_retriever.context)
return function.endpoint_callable()
AuthenticationDownloadAvatarEventMethods.endpoint_callable = authentication_download_avatar AuthenticationDownloadAvatarEventMethods.endpoint_callable = (
authentication_download_avatar
)

View File

@ -1,11 +1,11 @@
from typing import Any, TYPE_CHECKING, Union, Dict from typing import Any
from fastapi import Request
from ApiLayers.ApiLibrary.common.line_number import get_line_number_for_error from ApiLayers.ApiLibrary.common.line_number import get_line_number_for_error
from ApiLayers.ApiServices.Login.user_login_handler import UserLoginModule from ApiLayers.ApiServices.Login.user_login_handler import UserLoginModule
from ApiLayers.ApiServices.Token.token_handler import TokenService from ApiLayers.ApiServices.Token.token_handler import TokenService
from ApiLayers.ApiValidations.Custom.token_objects import CompanyToken, OccupantToken from ApiLayers.ApiValidations.Custom.token_objects import CompanyToken, OccupantToken
from ApiLayers.ApiValidations.Custom.wrapper_contexts import AuthContext, EventContext from ApiLayers.ApiValidations.Response.default_response import EndpointSuccessResponse
from ApiLayers.ErrorHandlers import HTTPExceptionApi from ApiLayers.ErrorHandlers import HTTPExceptionApi
from ApiLayers.Schemas import ( from ApiLayers.Schemas import (
BuildLivingSpace, BuildLivingSpace,
@ -22,462 +22,452 @@ from ApiLayers.Schemas import (
OccupantTypes, OccupantTypes,
Users, Users,
) )
from ApiLayers.ApiValidations.Response.default_response import EndpointSuccessResponse from Events.base_request_model import ContextRetrievers, TokenDictType
from fastapi import Request
# Type aliases for common types class Handlers:
TokenDictType = Union["EmployeeTokenObject", "OccupantTokenObject"] """Class for handling authentication functions"""
@classmethod # Requires no auth context
def authentication_login_with_domain_and_creds(request: Request, data: Any): def handle_employee_selection(cls, request: Request, data: Any, token_dict: TokenDictType):
""" Users.set_user_define_properties(token=token_dict)
Authenticate user with domain and credentials. db = Users.new_session()
if data.company_uu_id not in token_dict.companies_uu_id_list:
Args: raise HTTPExceptionApi(
request: FastAPI request object error_code="HTTP_400_BAD_REQUEST",
data: Request body containing login credentials lang=token_dict.lang,
{ loc=get_line_number_for_error(),
"domain": "evyos.com.tr", sys_msg="Company not found in token",
"access_key": "karatay.berkay.sup@evyos.com.tr", )
"password": "string", selected_company: Companies = Companies.filter_one(
"remember_me": false Companies.uu_id == data.company_uu_id,
} db=db,
Returns:
SuccessResponse containing authentication token and user info
"""
# Get token from login module
user_login_module = UserLoginModule(request=request)
token = user_login_module.login_user_via_credentials(access_data=data)
# Return response with token and headers
user_login_module.language = "tr"
success_response = EndpointSuccessResponse(
code="LoginSuccess", lang=user_login_module.language
)
return success_response.as_dict(
data={
"access_token": token.get("access_token"),
"refresh_token": token.get("refresher_token"),
"access_object": {"user_type": token.get("user_type"), "companies_list": token.get("companies_list")},
"user": token.get("user"),
}
)
# return {
# "completed": True,
# "message": "User is logged in successfully",
# "access_token": token.get("access_token"),
# "refresh_token": token.get("refresher_token"),
# "access_object": {
# "user_type": token.get("user_type"), "companies_list": token.get("companies_list")
# },
# "user": token.get("user"),
# }
def handle_employee_selection(request: Request, data: Any, token_dict: TokenDictType):
Users.set_user_define_properties(token=token_dict)
db_session = Users.new_session()
if data.company_uu_id not in token_dict.companies_uu_id_list:
raise HTTPExceptionApi(
error_code="HTTP_400_BAD_REQUEST",
lang=token_dict.lang,
loc=get_line_number_for_error(),
sys_msg="Company not found in token",
)
selected_company = Companies.filter_one(
Companies.uu_id == data.company_uu_id,
db=db_session,
).first
if not selected_company:
raise HTTPExceptionApi(
error_code="HTTP_400_BAD_REQUEST",
lang=token_dict.lang,
loc=get_line_number_for_error(),
sys_msg="Company not found in token",
)
# Get department IDs for the company
department_ids = [
dept.id
for dept in Departments.filter_all(
Departments.company_id == selected_company.id,
db=db_session,
).data ).data
] if not selected_company:
raise HTTPExceptionApi(
error_code="HTTP_400_BAD_REQUEST",
lang=token_dict.lang,
loc=get_line_number_for_error(),
sys_msg="Company not found in token",
)
# Get duties IDs for the company # Get department IDs for the company
duties_ids = [ department_ids = [
duty.id dept.id
for duty in Duties.filter_all( for dept in Departments.filter_all(
Duties.company_id == selected_company.id, db=db_session Departments.company_id == selected_company.id,
db=db,
).data
]
# Get duties IDs for the company
duties_ids = [
duty.id
for duty in Duties.filter_all(
Duties.company_id == selected_company.id, db=db
).data
]
# Get staff IDs
staff_ids = [
staff.id
for staff in Staff.filter_all(Staff.duties_id.in_(duties_ids), db=db).data
]
# Get employee
employee: Employees = Employees.filter_one(
Employees.people_id == token_dict.person_id,
Employees.staff_id.in_(staff_ids),
db=db,
).data ).data
]
# Get staff IDs if not employee:
staff_ids = [ raise HTTPExceptionApi(
staff.id error_code="HTTP_400_BAD_REQUEST",
for staff in Staff.filter_all( lang=token_dict.lang,
Staff.duties_id.in_(duties_ids), db=db_session loc=get_line_number_for_error(),
sys_msg="Employee not found in token",
)
# Get reachable events
reachable_event_codes = Event2Employee.get_event_codes(employee_id=employee.id)
reachable_event_endpoints = Event2Employee.get_event_endpoints(
employee_id=employee.id
)
# Get staff and duties
staff = Staff.filter_one(Staff.id == employee.staff_id, db=db).data
duties = Duties.filter_one(Duties.id == staff.duties_id, db=db).data
department = Departments.filter_one(
Departments.id == duties.department_id, db=db
).data ).data
]
# Get employee # Get bulk duty
employee = Employees.filter_one( bulk_id = Duty.filter_by_one(system=True, duty_code="BULK", db=db).data
Employees.people_id == token_dict.person_id, bulk_duty_id = Duties.filter_by_one(
Employees.staff_id.in_(staff_ids), company_id=selected_company.id,
db=db_session, duties_id=bulk_id.id,
).first **Duties.valid_record_dict,
db=db,
).data
if not employee: # Create company token
raise HTTPExceptionApi( company_token = CompanyToken(
error_code="HTTP_400_BAD_REQUEST", company_uu_id=selected_company.uu_id.__str__(),
lang=token_dict.lang, company_id=selected_company.id,
loc=get_line_number_for_error(), department_id=department.id,
sys_msg="Employee not found in token", department_uu_id=department.uu_id.__str__(),
duty_id=duties.id,
duty_uu_id=duties.uu_id.__str__(),
bulk_duties_id=bulk_duty_id.id,
staff_id=staff.id,
staff_uu_id=staff.uu_id.__str__(),
employee_id=employee.id,
employee_uu_id=employee.uu_id.__str__(),
reachable_event_codes=reachable_event_codes,
reachable_event_endpoints=reachable_event_endpoints,
) )
# Get reachable events try: # Update Redis
reachable_event_codes = Event2Employee.get_event_codes(employee_id=employee.id) return TokenService.update_token_at_redis(
reachable_event_endpoints = Event2Employee.get_event_endpoints( request=request, add_payload=company_token
employee_id=employee.id )
) except Exception as e:
raise HTTPExceptionApi(
error_code="",
lang="en",
loc=get_line_number_for_error(),
sys_msg=f"{e}",
)
# Get staff and duties @classmethod # Requires no auth context
staff = Staff.filter_one(Staff.id == employee.staff_id, db=db_session).data def handle_occupant_selection(cls, request: Request, data: Any, token_dict: TokenDictType):
duties = Duties.filter_one(Duties.id == staff.duties_id, db=db_session).data """Handle occupant type selection"""
department = Departments.filter_one( Users.set_user_define_properties(token=token_dict)
Departments.id == duties.department_id, db=db_session db = BuildLivingSpace.new_session()
).data # Get selected occupant type
selected_build_living_space: BuildLivingSpace = BuildLivingSpace.filter_one(
BuildLivingSpace.uu_id == data.build_living_space_uu_id,
db=db,
).data
if not selected_build_living_space:
raise HTTPExceptionApi(
error_code="HTTP_400_BAD_REQUEST",
lang=token_dict.lang,
loc=get_line_number_for_error(),
sys_msg="Selected occupant type not found",
)
# Get bulk duty # Get reachable events
bulk_id = Duty.filter_by_one(system=True, duty_code="BULK", db=db_session).data reachable_event_codes = Event2Occupant.get_event_codes(
bulk_duty_id = Duties.filter_by_one( build_living_space_id=selected_build_living_space.id
company_id=selected_company.id,
duties_id=bulk_id.id,
**Duties.valid_record_dict,
db=db_session,
).data
# Create company token
company_token = CompanyToken(
company_uu_id=selected_company.uu_id.__str__(),
company_id=selected_company.id,
department_id=department.id,
department_uu_id=department.uu_id.__str__(),
duty_id=duties.id,
duty_uu_id=duties.uu_id.__str__(),
bulk_duties_id=bulk_duty_id.id,
staff_id=staff.id,
staff_uu_id=staff.uu_id.__str__(),
employee_id=employee.id,
employee_uu_id=employee.uu_id.__str__(),
reachable_event_codes=reachable_event_codes,
reachable_event_endpoints=reachable_event_endpoints,
)
try: # Update Redis
update_token = TokenService.update_token_at_redis(
request=request, add_payload=company_token
) )
return update_token reachable_event_endpoints = Event2Occupant.get_event_endpoints(
except Exception as e: build_living_space_id=selected_build_living_space.id
raise HTTPExceptionApi( )
error_code="", occupant_type = OccupantTypes.filter_one(
lang="en", OccupantTypes.id == selected_build_living_space.occupant_type_id,
loc=get_line_number_for_error(), db=db,
sys_msg=f"{e}", system=True,
).data
build_part = BuildParts.filter_one(
BuildParts.id == selected_build_living_space.build_parts_id,
db=db,
).data
build = BuildParts.filter_one(
BuildParts.id == build_part.build_id,
db=db,
).data
responsible_employee = Employees.filter_one(
Employees.id == build_part.responsible_employee_id,
db=db,
).data
related_company = RelationshipEmployee2Build.filter_one(
RelationshipEmployee2Build.member_id == build.id,
db=db,
).data
# Get company
company_related = Companies.filter_one(
Companies.id == related_company.company_id,
db=db,
).data
# Create occupant token
occupant_token = OccupantToken(
living_space_id=selected_build_living_space.id,
living_space_uu_id=selected_build_living_space.uu_id.__str__(),
occupant_type_id=occupant_type.id,
occupant_type_uu_id=occupant_type.uu_id.__str__(),
occupant_type=occupant_type.occupant_type,
build_id=build.id,
build_uuid=build.uu_id.__str__(),
build_part_id=build_part.id,
build_part_uuid=build_part.uu_id.__str__(),
responsible_employee_id=responsible_employee.id,
responsible_employee_uuid=responsible_employee.uu_id.__str__(),
responsible_company_id=company_related.id,
responsible_company_uuid=company_related.uu_id.__str__(),
reachable_event_codes=reachable_event_codes,
reachable_event_endpoints=reachable_event_endpoints,
) )
try: # Update Redis
def handle_occupant_selection(request: Request, data: Any, token_dict: TokenDictType): return TokenService.update_token_at_redis(
"""Handle occupant type selection""" request=request, add_payload=occupant_token
db = BuildLivingSpace.new_session() )
# Get selected occupant type except Exception as e:
selected_build_living_space = BuildLivingSpace.filter_one( raise HTTPExceptionApi(
BuildLivingSpace.uu_id == data.build_living_space_uu_id, error_code="",
db=db, lang="en",
).data loc=get_line_number_for_error(),
if not selected_build_living_space: sys_msg=f"{e}",
raise HTTPExceptionApi( )
error_code="HTTP_400_BAD_REQUEST",
lang=token_dict.lang,
loc=get_line_number_for_error(),
sys_msg="Selected occupant type not found",
)
# Get reachable events
reachable_event_codes = Event2Occupant.get_event_codes(
build_living_space_id=selected_build_living_space.id
)
reachable_event_endpoints = Event2Occupant.get_event_endpoints(
build_living_space_id=selected_build_living_space.id
)
occupant_type = OccupantTypes.filter_one(
OccupantTypes.id == selected_build_living_space.occupant_type_id,
db=db,
system=True,
).data
build_part = BuildParts.filter_one(
BuildParts.id == selected_build_living_space.build_parts_id,
db=db,
).data
build = BuildParts.filter_one(
BuildParts.id == build_part.build_id,
db=db,
).data
responsible_employee = Employees.filter_one(
Employees.id == build_part.responsible_employee_id,
db=db,
).data
related_company = RelationshipEmployee2Build.filter_one(
RelationshipEmployee2Build.member_id == build.id,
db=db,
).data
# Get company
company_related = Companies.filter_one(
Companies.id == related_company.company_id,
db=db,
).data
# Create occupant token
occupant_token = OccupantToken(
living_space_id=selected_build_living_space.id,
living_space_uu_id=selected_build_living_space.uu_id.__str__(),
occupant_type_id=occupant_type.id,
occupant_type_uu_id=occupant_type.uu_id.__str__(),
occupant_type=occupant_type.occupant_type,
build_id=build.id,
build_uuid=build.uu_id.__str__(),
build_part_id=build_part.id,
build_part_uuid=build_part.uu_id.__str__(),
responsible_employee_id=responsible_employee.id,
responsible_employee_uuid=responsible_employee.uu_id.__str__(),
responsible_company_id=company_related.id,
responsible_company_uuid=company_related.uu_id.__str__(),
reachable_event_codes=reachable_event_codes,
reachable_event_endpoints=reachable_event_endpoints,
)
try: # Update Redis
update_token = TokenService.update_token_at_redis(
request=request, add_payload=occupant_token
)
return update_token
except Exception as e:
raise HTTPExceptionApi(
error_code="",
lang="en",
loc=get_line_number_for_error(),
sys_msg=f"{e}",
)
def authentication_select_company_or_occupant_type(request: Request, data: Any): class AuthenticationFunctions:
"""Handle selection of company or occupant type""" """Class for handling authentication functions"""
token_dict: TokenDictType = authentication_select_company_or_occupant_type.auth_context
if token_dict.is_employee:
if handle_employee_selection(data, token_dict, request):
return {"selected_occupant": None, "selected_company": data.company_uu_id}
elif token_dict.is_occupant:
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}
@classmethod # Requires auth context
def authentication_select_company_or_occupant_type(cls, data: Any):
"""Handle selection of company or occupant type"""
context_retriever = ContextRetrievers(func=cls.authentication_select_company_or_occupant_type)
if context_retriever.token.is_employee:
if Handlers.handle_employee_selection(
request=context_retriever.request, data=data, token_dict=context_retriever.token
):
return {
"completed": True, "selected": data.company_uu_id, **context_retriever.base,
}
elif context_retriever.token.is_occupant:
if Handlers.handle_occupant_selection(
request=context_retriever.request, data=data, token_dict=context_retriever.token
):
return {
"completed": True, "selected": data.build_living_space_uu_id, **context_retriever.base,
}
return {"completed": False, "selected": None, **context_retriever.base}
def authentication_check_token_is_valid(request: Request, data: Any): @classmethod # Requires no auth context
"""Check if token is valid for user""" def authentication_login_with_domain_and_creds(cls, request: Request, data: Any):
# try: """
# if RedisActions.get_object_via_access_key(request=request): Authenticate user with domain and credentials.
# return ResponseHandler.success("Access Token is valid")
# except HTTPException:
# return ResponseHandler.unauthorized("Access Token is NOT valid")
return
Args:
request: FastAPI request object
data: Request body containing login credentials
{
"domain": "evyos.com.tr",
"access_key": "karatay.berkay.sup@evyos.com.tr",
"password": "string",
"remember_me": false
}
Returns:
SuccessResponse containing authentication token and user info
"""
def authentication_refresh_user_info(request: Request, token_dict: TokenDictType, data: Any): # Get token from login module
"""Refresh user info using access token""" user_login_module = UserLoginModule(request=request)
# try: user_login_module.login_user_via_credentials(access_data=data)
# access_token = request.headers.get(Auth.ACCESS_TOKEN_TAG) user_login_module.language = "tr"
# if not access_token:
# return ResponseHandler.unauthorized()
# found_user = Users.filter_one(Users.uu_id == token_dict.user_uu_id).data # Return response with token and headers
# if not found_user: return EndpointSuccessResponse(
# return ResponseHandler.not_found("User not found") code="LOGIN_SUCCESS", lang=user_login_module.language
# user_token = UsersTokens.filter_one( ).as_dict(data=user_login_module.as_dict)
# UsersTokens.domain == found_user.domain_name,
# UsersTokens.user_id == found_user.id,
# UsersTokens.token_type == "RememberMe",
# ).data
# response_data = {
# "access_token": access_token,
# "refresh_token": getattr(user_token, "token", None),
# "user": found_user.get_dict(),
# }
# return ResponseHandler.success(
# "User info refreshed successfully",
# data=response_data,
# )
# except Exception as e:
# return ResponseHandler.error(str(e))
return
@classmethod # Requires not auth context
def authentication_check_token_is_valid(cls, data: Any):
"""Check if token is valid for user"""
# try:
# if RedisActions.get_object_via_access_key(request=request):
# return ResponseHandler.success("Access Token is valid")
# except HTTPException:
# return ResponseHandler.unauthorized("Access Token is NOT valid")
return
def authentication_change_password(request: Request, token_dict: TokenDictType, data: Any): @classmethod # Requires not auth context
"""Change password with access token""" def authentication_refresh_user_info(cls, data: Any):
# try: """Refresh user info using access token"""
# if not isinstance(token_dict, EmployeeTokenObject): # try:
# return ResponseHandler.unauthorized("Only employees can change password") # access_token = request.headers.get(Auth.ACCESS_TOKEN_TAG)
# if not access_token:
# return ResponseHandler.unauthorized()
# found_user = Users.filter_one(Users.uu_id == token_dict.user_uu_id).data # found_user = Users.filter_one(Users.uu_id == token_dict.user_uu_id).data
# if not found_user: # if not found_user:
# return ResponseHandler.not_found("User not found") # return ResponseHandler.not_found("User not found")
# user_token = UsersTokens.filter_one(
# UsersTokens.domain == found_user.domain_name,
# UsersTokens.user_id == found_user.id,
# UsersTokens.token_type == "RememberMe",
# ).data
# response_data = {
# "access_token": access_token,
# "refresh_token": getattr(user_token, "token", None),
# "user": found_user.get_dict(),
# }
# return ResponseHandler.success(
# "User info refreshed successfully",
# data=response_data,
# )
# except Exception as e:
# return ResponseHandler.error(str(e))
return
# if not found_user.check_password(data.old_password): @classmethod # Requires no auth context
# return ResponseHandler.unauthorized("Old password is incorrect") def authentication_change_password(cls, data: Any):
"""Change password with access token"""
# try:
# if not isinstance(token_dict, EmployeeTokenObject):
# return ResponseHandler.unauthorized("Only employees can change password")
# found_user.set_password(data.new_password) # found_user = Users.filter_one(Users.uu_id == token_dict.user_uu_id).data
# return ResponseHandler.success("Password changed successfully") # if not found_user:
# except Exception as e: # return ResponseHandler.not_found("User not found")
# return ResponseHandler.error(str(e))
return
# if not found_user.check_password(data.old_password):
# return ResponseHandler.unauthorized("Old password is incorrect")
def authentication_create_password(request: Request, data: Any): # found_user.set_password(data.new_password)
"""Create password with password reset token requested via email""" # return ResponseHandler.success("Password changed successfully")
# if not data.re_password == data.password: # except Exception as e:
# raise HTTPException(status_code=status.HTTP_406_NOT_ACCEPTABLE, detail="Password must match") # return ResponseHandler.error(str(e))
# if found_user := Users.filter_one(Users.password_token == data.password_token).data: return
# found_user.create_password(found_user=found_user, password=data.password)
# found_user.password_token = ""
# found_user.save()
# return ResponseHandler.success("Password is created successfully", data=found_user.get_dict())
# return ResponseHandler.not_found("Record not found")
return
@classmethod # Requires not auth context
def authentication_create_password(cls, 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")
# if found_user := Users.filter_one(Users.password_token == data.password_token).data:
# found_user.create_password(found_user=found_user, password=data.password)
# found_user.password_token = ""
# found_user.save()
# return ResponseHandler.success("Password is created successfully", data=found_user.get_dict())
# return ResponseHandler.not_found("Record not found")
return
def authentication_disconnect_user(request: Request, token_dict: TokenDictType, data: Any): @classmethod # Requires auth context
"""Disconnect all sessions of user in access token""" def authentication_disconnect_user(cls, data: Any):
# found_user = Users.filter_one(Users.uu_id == token_dict.user_uu_id).data """Disconnect all sessions of user in access token"""
# if not found_user: # found_user = Users.filter_one(Users.uu_id == token_dict.user_uu_id).data
# return ResponseHandler.not_found("User not found") # if not found_user:
# if already_tokens := RedisActions.get_object_via_user_uu_id(user_id=str(found_user.uu_id)): # return ResponseHandler.not_found("User not found")
# for key, token_user in already_tokens.items(): # if already_tokens := RedisActions.get_object_via_user_uu_id(user_id=str(found_user.uu_id)):
# RedisActions.delete(key) # for key, token_user in already_tokens.items():
# selected_user = Users.filter_one(Users.uu_id == token_user.get("uu_id")).data # RedisActions.delete(key)
# selected_user.remove_refresher_token(domain=data.domain, disconnect=True) # selected_user = Users.filter_one(Users.uu_id == token_user.get("uu_id")).data
# return ResponseHandler.success("All sessions are disconnected", data=selected_user.get_dict()) # selected_user.remove_refresher_token(domain=data.domain, disconnect=True)
# return ResponseHandler.not_found("Invalid data") # return ResponseHandler.success("All sessions are disconnected", data=selected_user.get_dict())
return # return ResponseHandler.not_found("Invalid data")
return
@classmethod # Requires auth context
def authentication_logout_user(cls, 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):
# for key in already_tokens:
# token_user = RedisActions.get_json(key)
# if token_user.get("domain") == data.domain:
# RedisActions.delete(key)
# selected_user = Users.filter_one(Users.uu_id == token_user.get("uu_id")).data
# 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")
context_retriever = ContextRetrievers(func=cls.authentication_logout_user)
return context_retriever.base
def authentication_logout_user(request: Request, data: Any): @classmethod # Requires not auth context
"""Logout only single session of user which domain is provided""" def authentication_refresher_token(cls, data: Any):
# token_user = None """Refresh access token with refresher token"""
# if already_tokens := RedisActions.get_object_via_access_key(request=request): # token_refresher = UsersTokens.filter_by_one(
# for key in already_tokens: # token=data.refresh_token,
# token_user = RedisActions.get_json(key) # domain=data.domain,
# if token_user.get("domain") == data.domain: # **UsersTokens.valid_record_dict,
# RedisActions.delete(key) # ).data
# selected_user = Users.filter_one(Users.uu_id == token_user.get("uu_id")).data # if not token_refresher:
# selected_user.remove_refresher_token(domain=data.domain) # return ResponseHandler.not_found("Invalid data")
# return ResponseHandler.success("Session is logged out", data=token_user) # if found_user := Users.filter_one(Users.id == token_refresher.user_id).data:
# return ResponseHandler.not_found("Logout is not successfully completed") # access_key = AuthActions.save_access_token_to_redis(
# request=request, found_user=found_user, domain=data.domain
# )
# found_user.last_agent = request.headers.get("User-Agent", None)
# found_user.last_platform = request.headers.get("Origin", None)
# found_user.last_remote_addr = getattr(request, "remote_addr", None) or request.headers.get("X-Forwarded-For", None)
# found_user.last_seen = str(system_arrow.now())
# response_data = {
# "access_token": access_key,
# "refresh_token": data.refresh_token,
# }
# return ResponseHandler.success("User is logged in successfully via refresher token", data=response_data)
# return ResponseHandler.not_found("Invalid data")
context_retriever = ContextRetrievers(func=cls.authentication_refresher_token)
return context_retriever.base
event_context: EventContext = getattr(authentication_logout_user, "event_context", None) @classmethod # Requires not auth context
return event_context.model_dump() def authentication_forgot_password(cls, 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)
# forgot_link = ApiStatic.forgot_link(forgot_key=forgot_key)
# send_email_completed = send_email(
# subject=f"Dear {found_user.user_tag}, your forgot password link has been sent.",
# receivers=[str(found_user.email)],
# html=change_your_password_template(user_name=found_user.user_tag, forgot_link=forgot_link),
# )
# if not send_email_completed:
# raise HTTPException(status_code=400, detail="Email can not be sent. Try again later")
# found_user.password_token = forgot_key
# found_user.password_token_is_valid = str(system_arrow.shift(days=1))
# found_user.save()
# return ResponseHandler.success("Password is change link is sent to your email or phone", data={})
return
@classmethod # Requires not auth context
def authentication_reset_password(cls, data: Any):
"""Reset password with forgot password token"""
# from sqlalchemy import or_
# found_user = Users.query.filter(
# or_(
# Users.email == str(data.access_key).lower(),
# Users.phone_number == str(data.access_key).replace(" ", ""),
# ),
# ).first()
# if not found_user:
# raise HTTPException(
# status_code=status.HTTP_400_BAD_REQUEST,
# detail="Given access key or domain is not matching with the any user record.",
# )
# reset_password_token = found_user.reset_password_token(found_user=found_user)
# send_email_completed = send_email(
# subject=f"Dear {found_user.user_tag}, a password reset request has been received.",
# receivers=[str(found_user.email)],
# html=change_your_password_template(
# user_name=found_user.user_tag,
# forgot_link=ApiStatic.forgot_link(forgot_key=reset_password_token),
# ),
# )
# if not send_email_completed:
# raise found_user.raise_http_exception(status_code=400, message="Email can not be sent. Try again later")
# return ResponseHandler.success("Password change link is sent to your email or phone", data=found_user.get_dict())
return
def authentication_refresher_token(request: Request, data: Any): @classmethod # Requires not auth context
"""Refresh access token with refresher token""" def authentication_download_avatar(cls, data: Any):
# token_refresher = UsersTokens.filter_by_one( """Download avatar icon and profile info of user"""
# token=data.refresh_token, # if found_user := Users.filter_one(Users.id == token_dict.user_id).data:
# domain=data.domain, # expired_starts = str(system_arrow.now() - system_arrow.get(str(found_user.expiry_ends)))
# **UsersTokens.valid_record_dict, # expired_int = (system_arrow.now() - system_arrow.get(str(found_user.expiry_ends))).days
# ).data # user_info = {
# if not token_refresher: # "lang": token_dict.lang,
# return ResponseHandler.not_found("Invalid data") # "full_name": found_user.person.full_name,
# if found_user := Users.filter_one(Users.id == token_refresher.user_id).data: # "avatar": found_user.avatar,
# access_key = AuthActions.save_access_token_to_redis( # "remember_me": found_user.remember_me,
# request=request, found_user=found_user, domain=data.domain # "expiry_ends": str(found_user.expiry_ends),
# ) # "expired_str": expired_starts,
# found_user.last_agent = request.headers.get("User-Agent", None) # "expired_int": int(expired_int),
# found_user.last_platform = request.headers.get("Origin", None) # }
# found_user.last_remote_addr = getattr(request, "remote_addr", None) or request.headers.get("X-Forwarded-For", None) # return ResponseHandler.success("Avatar and profile is shared via user credentials", data=user_info)
# found_user.last_seen = str(system_arrow.now()) # return ResponseHandler.not_found("Invalid data")
# response_data = { return
# "access_token": access_key,
# "refresh_token": data.refresh_token,
# }
# return ResponseHandler.success("User is logged in successfully via refresher token", data=response_data)
# return ResponseHandler.not_found("Invalid data")
auth_context: AuthContext = getattr(authentication_refresher_token, "auth_context", None)
return auth_context.model_dump()
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)
# forgot_link = ApiStatic.forgot_link(forgot_key=forgot_key)
# send_email_completed = send_email(
# subject=f"Dear {found_user.user_tag}, your forgot password link has been sent.",
# receivers=[str(found_user.email)],
# html=change_your_password_template(user_name=found_user.user_tag, forgot_link=forgot_link),
# )
# if not send_email_completed:
# raise HTTPException(status_code=400, detail="Email can not be sent. Try again later")
# found_user.password_token = forgot_key
# found_user.password_token_is_valid = str(system_arrow.shift(days=1))
# found_user.save()
# return ResponseHandler.success("Password is change link is sent to your email or phone", data={})
return
def authentication_reset_password(request: Request, data: Any):
"""Reset password with forgot password token"""
# from sqlalchemy import or_
# found_user = Users.query.filter(
# or_(
# Users.email == str(data.access_key).lower(),
# Users.phone_number == str(data.access_key).replace(" ", ""),
# ),
# ).first()
# if not found_user:
# raise HTTPException(
# status_code=status.HTTP_400_BAD_REQUEST,
# detail="Given access key or domain is not matching with the any user record.",
# )
# reset_password_token = found_user.reset_password_token(found_user=found_user)
# send_email_completed = send_email(
# subject=f"Dear {found_user.user_tag}, a password reset request has been received.",
# receivers=[str(found_user.email)],
# html=change_your_password_template(
# user_name=found_user.user_tag,
# forgot_link=ApiStatic.forgot_link(forgot_key=reset_password_token),
# ),
# )
# if not send_email_completed:
# raise found_user.raise_http_exception(status_code=400, message="Email can not be sent. Try again later")
# return ResponseHandler.success("Password change link is sent to your email or phone", data=found_user.get_dict())
return
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)))
# expired_int = (system_arrow.now() - system_arrow.get(str(found_user.expiry_ends))).days
# user_info = {
# "lang": token_dict.lang,
# "full_name": found_user.person.full_name,
# "avatar": found_user.avatar,
# "remember_me": found_user.remember_me,
# "expiry_ends": str(found_user.expiry_ends),
# "expired_str": expired_starts,
# "expired_int": int(expired_int),
# }
# return ResponseHandler.success("Avatar and profile is shared via user credentials", data=user_info)
# return ResponseHandler.not_found("Invalid data")
return

View File

@ -1,7 +1,6 @@
from pydantic import BaseModel from pydantic import BaseModel
from ApiLayers.ApiValidations.Request import ( from ApiLayers.ApiValidations.Request import Login
Login,
)
class LoginSuperUserRequestModel(Login): class LoginSuperUserRequestModel(Login):
pass pass
@ -33,3 +32,21 @@ class OccupantSelectionSuperUserRequestModel(BaseModel):
class OccupantSelectionSuperUserResponseModel(BaseModel): class OccupantSelectionSuperUserResponseModel(BaseModel):
pass pass
class AuthenticationRequestModels:
LoginSuperUserRequestModel = LoginSuperUserRequestModel
SelectCompanyOrOccupantTypeSuperUserRequestModel = (
SelectCompanyOrOccupantTypeSuperUserRequestModel
)
EmployeeSelectionSuperUserRequestModel = EmployeeSelectionSuperUserRequestModel
OccupantSelectionSuperUserRequestModel = OccupantSelectionSuperUserRequestModel
class AuthenticationResponseModels:
LoginSuperUserResponseModel = LoginSuperUserResponseModel
SelectCompanyOrOccupantTypeSuperUserResponseModel = (
SelectCompanyOrOccupantTypeSuperUserResponseModel
)
EmployeeSelectionSuperUserResponseModel = EmployeeSelectionSuperUserResponseModel
OccupantSelectionSuperUserResponseModel = OccupantSelectionSuperUserResponseModel

View File

@ -2,6 +2,4 @@
Events package initialization. Events package initialization.
""" """
__all__ = []
__all__ = [
]

View File

@ -10,4 +10,3 @@ def retrieve_cluster_by_name(cluster_name: str):
for module in events_list: for module in events_list:
if hasattr(module, cluster_name, None): if hasattr(module, cluster_name, None):
return getattr(module, cluster_name, None) return getattr(module, cluster_name, None)

View File

@ -62,7 +62,7 @@ class Event:
return self.NAME return self.NAME
@property @property
def key(self): def key(self) -> str:
return str(self.KEY_) return str(self.KEY_)
@abstractmethod @abstractmethod
@ -156,8 +156,8 @@ class CategoryCluster:
PREFIX: str PREFIX: str
PAGEINFO: PageInfo PAGEINFO: PageInfo
DESCRIPTION: str DESCRIPTION: str
ENDPOINTS: dict[str, MethodToEvent] # {"MethodToEvent": MethodToEvent, ...} ENDPOINTS: dict[str, MethodToEvent] # {"MethodToEvent": MethodToEvent, ...}
SUBCATEGORY: Optional[List["CategoryCluster"]] # [CategoryCluster, ...] SUBCATEGORY: Optional[List["CategoryCluster"]] # [CategoryCluster, ...]
INCLUDE_IN_SCHEMA: Optional[bool] = True INCLUDE_IN_SCHEMA: Optional[bool] = True
def __init__( def __init__(
@ -189,7 +189,9 @@ class CategoryCluster:
RedisCategoryKeys.CLUSTER_2_METHOD_EVENT RedisCategoryKeys.CLUSTER_2_METHOD_EVENT
Returns the class name and function codes for the class. Returns the class name and function codes for the class.
""" """
dict_cluster_2_method, list_endpoints = {}, [i.name for i in self.ENDPOINTS.values()] dict_cluster_2_method, list_endpoints = {}, [
i.name for i in self.ENDPOINTS.values()
]
for endpoint_name in list_endpoints: for endpoint_name in list_endpoints:
dict_cluster_2_method[endpoint_name] = self.name dict_cluster_2_method[endpoint_name] = self.name
dict_cluster_2_method[self.name] = list_endpoints dict_cluster_2_method[self.name] = list_endpoints
@ -201,7 +203,9 @@ class CategoryCluster:
""" """
all_function_codes = [] all_function_codes = []
for event_method in self.ENDPOINTS.values(): for event_method in self.ENDPOINTS.values():
all_function_codes.extend([str(event_key) for event_key in event_method.EVENTS.keys()]) all_function_codes.extend(
[str(event_key) for event_key in event_method.EVENTS.keys()]
)
return all_function_codes return all_function_codes
def retrieve_redis_value(self) -> Dict: def retrieve_redis_value(self) -> Dict:

View File

@ -23,14 +23,17 @@ class CategoryClusterController:
{ "category_cluster_name": "category_cluster_module" } { "category_cluster_name": "category_cluster_module" }
""" """
if not hasattr(category_clusters, "__all__"): if not hasattr(category_clusters, "__all__"):
raise ValueError(f"Given module {str(category_clusters)} does not have __all__ attribute") 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__]: for iter_module in [str(item) for item in category_clusters.__all__]:
# CategoryCluster which represent api routers for each category # CategoryCluster which represent api routers for each category
cls.imports_dict.append( cls.imports_dict.append(
CategoryBulk( CategoryBulk(
category_cluster=getattr(category_clusters, iter_module, None), category_cluster=getattr(category_clusters, iter_module, None),
name=iter_module name=iter_module,
)) )
)
@classmethod @classmethod
def as_dict(cls): def as_dict(cls):
@ -39,4 +42,5 @@ class CategoryClusterController:
to_dict[cluster.name] = cluster.category_cluster to_dict[cluster.name] = cluster.category_cluster
return to_dict return to_dict
cluster_controller = CategoryClusterController()
cluster_controller = CategoryClusterController()

View File

@ -35,24 +35,32 @@ class DecoratorModule:
""" """
decorators = [] decorators = []
current_func = func current_func = func
original_qualname = getattr(func, '__qualname__', '') original_qualname = getattr(func, "__qualname__", "")
while hasattr(current_func, '__wrapped__'): while hasattr(current_func, "__wrapped__"):
if hasattr(current_func, '__closure__') and current_func.__closure__: if hasattr(current_func, "__closure__") and current_func.__closure__:
for cell in current_func.__closure__: for cell in current_func.__closure__:
decorator = cell.cell_contents decorator = cell.cell_contents
# Only add if it's a callable and not the original function # Only add if it's a callable and not the original function
if callable(decorator) and getattr(decorator, '__qualname__', '') != original_qualname: if (
callable(decorator)
and getattr(decorator, "__qualname__", "") != original_qualname
):
decorators.append(decorator) decorators.append(decorator)
current_func = current_func.__wrapped__ current_func = current_func.__wrapped__
return list(dict.fromkeys(decorators)) # Remove duplicates while preserving order return list(
dict.fromkeys(decorators)
) # Remove duplicates while preserving order
@staticmethod @staticmethod
def get_actual_decorators(method_endpoint): def get_actual_decorators(method_endpoint):
original_qualname = getattr(method_endpoint.endpoint_callable, '__qualname__', '') original_qualname = getattr(
method_endpoint.endpoint_callable, "__qualname__", ""
)
actual_decorators = [ actual_decorators = [
d for d in method_endpoint.DECORATORS_LIST or [] d
if callable(d) and getattr(d, '__qualname__', '') != original_qualname for d in method_endpoint.DECORATORS_LIST or []
if callable(d) and getattr(d, "__qualname__", "") != original_qualname
] ]
return actual_decorators return actual_decorators
@ -68,17 +76,27 @@ class DecoratorModule:
try: try:
function_callable = decorator(function_callable) function_callable = decorator(function_callable)
except Exception as e: except Exception as e:
print(f"Warning: Failed to apply decorator {decorator.__qualname__}: {str(e)}") print(
f"Warning: Failed to apply decorator {decorator.__qualname__}: {str(e)}"
)
method_endpoint.endpoint_callable = function_callable method_endpoint.endpoint_callable = function_callable
# Get the final list of applied decorators (for debugging) # Get the final list of applied decorators (for debugging)
applied_decorators = cls.get_all_decorators(method_endpoint.endpoint_callable) applied_decorators = cls.get_all_decorators(method_endpoint.endpoint_callable)
applied_decorators_qualname = [getattr(d, '__qualname__', str(d)) for d in applied_decorators] applied_decorators_qualname = [
getattr(d, "__qualname__", str(d)) for d in applied_decorators
]
if applied_decorators: if applied_decorators:
print(f"Applied decorators for {method_endpoint.name}:", applied_decorators_qualname) print(
f"Applied decorators for {method_endpoint.name}:",
applied_decorators_qualname,
)
return applied_decorators_qualname return applied_decorators_qualname
@classmethod @classmethod
def list_qualname(cls, method_endpoint_list): def list_qualname(cls, method_endpoint_list):
return [getattr(method_endpoint, '__qualname__', '') for method_endpoint in method_endpoint_list] return [
getattr(method_endpoint, "__qualname__", "")
for method_endpoint in method_endpoint_list
]

View File

@ -9,8 +9,6 @@ def get_cluster_controller_group():
return cluster_controller return cluster_controller
""" """
prepare_routing = PrepareRouting(cluster_controller_group=cluster_controller) prepare_routing = PrepareRouting(cluster_controller_group=cluster_controller)
prepare_events = PrepareEvents(cluster_controller_group=cluster_controller) prepare_events = PrepareEvents(cluster_controller_group=cluster_controller)

View File

@ -2,7 +2,7 @@ from typing import Any
from ApiLayers.ApiServices.Cluster.create_router import ( from ApiLayers.ApiServices.Cluster.create_router import (
CreateRouterFromCluster, CreateRouterFromCluster,
CreateEndpointFromCluster CreateEndpointFromCluster,
) )
from Events.Engine.abstract_class import CategoryCluster from Events.Engine.abstract_class import CategoryCluster
from Services.Redis.Actions.actions import RedisActions from Services.Redis.Actions.actions import RedisActions
@ -83,19 +83,27 @@ class PrepareEvents(DecoratorModule):
# [SAVE]REDIS => MENU_FIRST_LAYER = [ClusterToMethod, ...] # [SAVE]REDIS => MENU_FIRST_LAYER = [ClusterToMethod, ...]
self.valid_redis_items.MENU_FIRST_LAYER_VALUE.add(cluster.name) self.valid_redis_items.MENU_FIRST_LAYER_VALUE.add(cluster.name)
# [SAVE]REDIS => CLUSTER_INDEX = {ClusterToMethod: [MethodEvent, ...], "MethodEvent": "ClusterToMethod"} # [SAVE]REDIS => CLUSTER_INDEX = {ClusterToMethod: [MethodEvent, ...], "MethodEvent": "ClusterToMethod"}
self.valid_redis_items.CLUSTER_INDEX_VALUE.update(cluster.get_redis_cluster_index_value()) self.valid_redis_items.CLUSTER_INDEX_VALUE.update(
cluster.get_redis_cluster_index_value()
)
# [SAVE]REDIS => CLUSTER_FUNCTION_CODES = {"ClusterToMethod"} : [FUNCTION_CODE, ...]} # [SAVE]REDIS => CLUSTER_FUNCTION_CODES = {"ClusterToMethod"} : [FUNCTION_CODE, ...]}
self.valid_redis_items.CLUSTER_FUNCTION_CODES_VALUE = { 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()) f"{self.valid_redis_items.CLUSTER_FUNCTION_CODES_KEY}:{cluster.name}": tuple(
cluster.retrieve_all_function_codes()
)
} }
for method_endpoint in list(cluster.ENDPOINTS.values()): for method_endpoint in list(cluster.ENDPOINTS.values()):
# [SAVE]REDIS => ENDPOINT2CLASS = {MethodEvent: Endpoint("/.../.../..."), ...} # [SAVE]REDIS => ENDPOINT2CLASS = {MethodEvent: Endpoint("/.../.../..."), ...}
self.valid_redis_items.ENDPOINT2CLASS_VALUE.update( self.valid_redis_items.ENDPOINT2CLASS_VALUE.update(
{f"{cluster.name}:{method_endpoint.name}": f"{cluster.PREFIX}{method_endpoint.URL}"} {
f"{cluster.name}:{method_endpoint.name}": f"{cluster.PREFIX}{method_endpoint.URL}"
}
) )
self.valid_redis_items.ENDPOINT2CLASS_VALUE.update( self.valid_redis_items.ENDPOINT2CLASS_VALUE.update(
{f"{cluster.PREFIX}{method_endpoint.URL}" :f"{cluster.name}:{method_endpoint.name}"} {
f"{cluster.PREFIX}{method_endpoint.URL}": f"{cluster.name}:{method_endpoint.name}"
}
) )
# [SAVE]REDIS => METHOD_FUNCTION_CODES:MethodEvent:Endpoint = [FUNCTION_CODE, ...] # [SAVE]REDIS => METHOD_FUNCTION_CODES:MethodEvent:Endpoint = [FUNCTION_CODE, ...]
self.valid_redis_items.METHOD_FUNCTION_CODES_VALUE.update( self.valid_redis_items.METHOD_FUNCTION_CODES_VALUE.update(
@ -116,8 +124,12 @@ class SetItems2Redis:
def set_items(self): def set_items(self):
from ApiLayers.AllConfigs.Redis.configs import RedisCategoryKeys from ApiLayers.AllConfigs.Redis.configs import RedisCategoryKeys
dict_prep = self.prepare_events.valid_redis_items.as_dict dict_prep = self.prepare_events.valid_redis_items.as_dict
for redis_values_to_delete, redis_key_type in RedisCategoryKeys.__annotations__.items(): for (
redis_values_to_delete,
redis_key_type,
) in RedisCategoryKeys.__annotations__.items():
if isinstance(redis_key_type, str): if isinstance(redis_key_type, str):
continue continue
RedisActions.delete(list_keys=[f"{redis_values_to_delete}*"]) RedisActions.delete(list_keys=[f"{redis_values_to_delete}*"])
@ -125,19 +137,23 @@ class SetItems2Redis:
# Save MENU_FIRST_LAYER to Redis # Save MENU_FIRST_LAYER to Redis
redis_list = RedisList(redis_key=RedisCategoryKeys.MENU_FIRST_LAYER) redis_list = RedisList(redis_key=RedisCategoryKeys.MENU_FIRST_LAYER)
RedisActions.set_json( RedisActions.set_json(
list_keys=redis_list.to_list(), value=dict_prep.get(RedisCategoryKeys.MENU_FIRST_LAYER) 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" self.std_out += f"{RedisCategoryKeys.MENU_FIRST_LAYER}: {dict_prep.get(RedisCategoryKeys.MENU_FIRST_LAYER)}\n"
# Save CLUSTER_INDEX to Redis # Save CLUSTER_INDEX to Redis
redis_list = RedisList(redis_key=RedisCategoryKeys.CLUSTER_INDEX) redis_list = RedisList(redis_key=RedisCategoryKeys.CLUSTER_INDEX)
RedisActions.set_json( RedisActions.set_json(
list_keys=redis_list.to_list(), value=dict_prep.get(RedisCategoryKeys.CLUSTER_INDEX) 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" 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 # 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(): for redis_key, redis_value in dict_prep.get(
RedisCategoryKeys.CLUSTER_FUNCTION_CODES
).items():
redis_list = RedisList(redis_key=redis_key) redis_list = RedisList(redis_key=redis_key)
RedisActions.set_json( RedisActions.set_json(
list_keys=redis_list.to_list(), value=list(redis_value) list_keys=redis_list.to_list(), value=list(redis_value)
@ -145,7 +161,9 @@ class SetItems2Redis:
self.std_out += f"\n{RedisCategoryKeys.CLUSTER_FUNCTION_CODES}: {dict_prep.get(RedisCategoryKeys.CLUSTER_FUNCTION_CODES)}\n" 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 # 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(): for redis_key, redis_value in dict_prep.get(
RedisCategoryKeys.METHOD_FUNCTION_CODES
).items():
redis_list = RedisList(redis_key=redis_key) redis_list = RedisList(redis_key=redis_key)
RedisActions.set_json( RedisActions.set_json(
list_keys=redis_list.to_list(), value=list(redis_value) list_keys=redis_list.to_list(), value=list(redis_value)
@ -153,19 +171,22 @@ class SetItems2Redis:
self.std_out += f"\n{RedisCategoryKeys.METHOD_FUNCTION_CODES}: {dict_prep.get(RedisCategoryKeys.METHOD_FUNCTION_CODES)}\n" 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 # Save ENDPOINT2CLASS to Redis by iterating over the dict
for redis_key, redis_value in dict_prep.get(RedisCategoryKeys.ENDPOINT2CLASS).items(): for redis_key, redis_value in dict_prep.get(
redis_list = RedisList(redis_key=f"{RedisCategoryKeys.ENDPOINT2CLASS}:{redis_key}\n") RedisCategoryKeys.ENDPOINT2CLASS
RedisActions.set_json( ).items():
list_keys=redis_list.to_list(), value=redis_value 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" self.std_out += f"\n{RedisCategoryKeys.ENDPOINT2CLASS}: {dict_prep.get(RedisCategoryKeys.ENDPOINT2CLASS)}\n"
RedisActions.set_json( RedisActions.set_json(
list_keys=[f"{RedisCategoryKeys.REBUILD}:*"], value={ list_keys=[f"{RedisCategoryKeys.REBUILD}:*"],
value={
f"{RedisCategoryKeys.MENU_FIRST_LAYER}": True, f"{RedisCategoryKeys.MENU_FIRST_LAYER}": True,
f"{RedisCategoryKeys.CLUSTER_INDEX}": True, f"{RedisCategoryKeys.CLUSTER_INDEX}": True,
f"{RedisCategoryKeys.CLUSTER_FUNCTION_CODES}": True, f"{RedisCategoryKeys.CLUSTER_FUNCTION_CODES}": True,
f"{RedisCategoryKeys.METHOD_FUNCTION_CODES}": True, f"{RedisCategoryKeys.METHOD_FUNCTION_CODES}": True,
f"{RedisCategoryKeys.ENDPOINT2CLASS}": True, f"{RedisCategoryKeys.ENDPOINT2CLASS}": True,
} },
) )

View File

@ -5,11 +5,19 @@ This module provides base request models that can be used across different endpo
to ensure consistent request handling and validation. to ensure consistent request handling and validation.
""" """
from typing import Dict, Any, TypeVar from typing import Union, Optional, Any
from pydantic import BaseModel, Field, ConfigDict from pydantic import BaseModel, Field
from ApiLayers.ApiValidations.Custom.token_objects import (
EmployeeTokenObject,
OccupantTokenObject,
)
from ApiLayers.ApiValidations.Custom.wrapper_contexts import AuthContext, EventContext
T = TypeVar("T") TokenDictType = Union[
EmployeeTokenObject, OccupantTokenObject
] # Type aliases for common types
class EndpointBaseRequestModel(BaseModel): class EndpointBaseRequestModel(BaseModel):
@ -17,35 +25,63 @@ class EndpointBaseRequestModel(BaseModel):
data: dict = Field(..., description="Data to be sent with the request") data: dict = Field(..., description="Data to be sent with the request")
class Config: class Config:
json_schema_extra = { json_schema_extra = {"data": {"key": "value"}}
"data": {
"key": "value",
}
}
class SuccessResponse(BaseModel): class ContextRetrievers:
"""Standard success response model.""" """Utility class to retrieve context from functions."""
data: Dict[str, Any] = Field( is_auth: bool = False
..., is_event: bool = False
example={ key_: str = ""
"id": "123",
"username": "john.doe",
"email": "john@example.com",
"role": "user",
},
)
model_config = ConfigDict( def __init__(self, func):
json_schema_extra={ self.func = func
"example": { if hasattr(self.func, "auth_context"):
"data": { self.is_auth = True
"id": "123", self.key_ = "auth_context"
"username": "john.doe", elif hasattr(self.func, "event_context"):
"email": "john@example.com", self.is_event = hasattr(self.func, "event_context")
"role": "user", self.key_ = "event_context"
},
} @property
} def key(self) -> Union[str, None]:
) """Retrieve key context from a function."""
return self.key_
@property
def context(self) -> Union[AuthContext, EventContext, None]:
"""Retrieve authentication or event context from a function."""
if self.is_auth:
return getattr(self.func, "auth_context", None)
elif self.is_event:
return getattr(self.func, "event_context", None)
return None
@property
def request(self) -> Union[Any, None]:
"""Retrieve request context from a function."""
return getattr(self.context, "request", None)
@property
def token(self) -> TokenDictType:
"""Retrieve token context from a function."""
if self.is_auth or self.is_event:
return getattr(self.context, "auth", None)
@property
def url(self) -> Union[str, None]:
"""Retrieve URL context from a function."""
return getattr(self.context, "url", None)
@property
def code(self) -> Union[str, None]:
"""Retrieve code context from a function."""
if self.is_event:
return getattr(self.context, "code", None)
return None
@property
def base(self) -> Optional[dict[str, Any]]:
"""Retrieve base request model from a function."""
return getattr(self.context, "base", None)

View File

@ -125,7 +125,9 @@ class QueryModel(ArgumentModel):
if not expired: if not expired:
args = cls.get_not_expired_query_arg(args) args = cls.get_not_expired_query_arg(args)
query = cls._query(db=db).filter(*args) query = cls._query(db=db).filter(*args)
return PostgresResponse(pre_query=cls._query(db=db), query=query, is_array=False) return PostgresResponse(
pre_query=cls._query(db=db), query=query, is_array=False
)
@classmethod @classmethod
def filter_all_system( def filter_all_system(

View File

@ -26,7 +26,9 @@ class BasicMixin(Base, BaseAlchemyModel):
__repr__ = ReprMixin.__repr__ __repr__ = ReprMixin.__repr__
class CrudMixin(BasicMixin, CRUDModel, SerializeMixin, ReprMixin, SmartQueryMixin, QueryModel ): class CrudMixin(
BasicMixin, CRUDModel, SerializeMixin, ReprMixin, SmartQueryMixin, QueryModel
):
""" """
Base mixin providing CRUD operations and common fields for PostgreSQL models. Base mixin providing CRUD operations and common fields for PostgreSQL models.