language models and set defaults are updated

This commit is contained in:
2025-01-28 17:11:59 +03:00
parent c0bd9c1685
commit 5d3f946642
34 changed files with 638 additions and 126 deletions

View File

@@ -16,15 +16,19 @@ class WagRedis:
)
# VALIDATION_USER: str = "VALIDATION_USER"
class RedisValidationKeys:
ENDPOINTS: str = "ENDPOINTS"
VALIDATIONS: str = "VALIDATIONS"
HEADERS: str = "HEADERS"
ERRORCODES: str = "ERRORCODES"
RESPONSES: str = "RESPONSES"
REQUESTS: str = "REQUESTS"
RESPONSE: str = "RESPONSE"
LANGUAGE_MODELS: str = "LANGUAGE_MODELS"
STATIC: str = "STATIC"
DYNAMIC: str = "DYNAMIC"
# REQUEST: str = "REQUEST"
# VALIDATION_USER: str = "VALIDATION_USER"
class RedisAuthKeys:
AUTH: str = "AUTH"

View File

@@ -17,3 +17,9 @@ class MainConfig:
DEFAULT_TIMEZONE = "GMT+3" # Default timezone for the application
SYSTEM_TIMEZONE = "GMT+0" # System timezone (used for internal operations)
SUPPORTED_TIMEZONES = ["GMT+0", "GMT+3"] # List of supported timezones
class LanguageConfig:
SUPPORTED_LANGUAGES = ["en", "tr"]
DEFAULT_LANGUAGE = "tr"

View File

@@ -50,6 +50,7 @@ class UserLoginModule:
def login_user_via_credentials(self, access_data: "Login") -> None:
from ApiLayers.ApiServices.Token.token_handler import TokenService
from ApiLayers.Schemas import Users
"""
Login the user via the credentials.
"""
@@ -65,12 +66,17 @@ class UserLoginModule:
)
# Check if the password is correct
if PasswordModule.check_password(
domain=access_data.domain, id_=found_user.uu_id,
password=access_data.password, password_hashed=found_user.hash_password,
domain=access_data.domain,
id_=found_user.uu_id,
password=access_data.password,
password_hashed=found_user.hash_password,
):
# Set the access token to the redis
token_response = TokenService.set_access_token_to_redis(
request=self.request, user=found_user, domain=access_data.domain, remember=access_data.remember_me,
request=self.request,
user=found_user,
domain=access_data.domain,
remember=access_data.remember_me,
)
# Set the user and token information to the instance
self.user = found_user.get_dict()
@@ -78,7 +84,7 @@ class UserLoginModule:
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", {})
"selection_list": token_response.get("selection_list", {}),
}
return None
raise HTTPExceptionApi(

View File

@@ -285,10 +285,14 @@ class TokenService:
cls.remove_token_with_domain(user=user, domain=domain)
Users.client_arrow = DateTimeLocal(is_client=True, timezone=user.local_timezone)
login_dict, db_session = {}, UsersTokens.new_session()
if user.is_occupant: # Handle login based on user type
login_dict = cls.do_occupant_login(request=request, user=user, domain=domain)
if user.is_occupant: # Handle login based on user type
login_dict = cls.do_occupant_login(
request=request, user=user, domain=domain
)
elif user.is_employee:
login_dict = cls.do_employee_login(request=request, user=user, domain=domain)
login_dict = cls.do_employee_login(
request=request, user=user, domain=domain
)
# Handle remember me functionality
if remember:

View File

@@ -14,14 +14,18 @@ class BaseEndpointResponse:
from Services.Redis import RedisActions
from ApiLayers.AllConfigs.Redis.configs import RedisValidationKeys
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_key = (
f"{RedisValidationKeys.LANGUAGE_MODELS}:{RedisValidationKeys.RESPONSES}"
)
language_model = RedisActions.get_json(
list_keys=[language_model_key, self.code, self.lang]
)
if language_model.status:
return language_model.first.as_dict
return {"message": f"{self.code} -> Language model not found"}
class EndpointSuccessResponse(BaseEndpointResponse): # 200 OK
class EndpointSuccessResponse(BaseEndpointResponse): # 200 OK
def as_dict(self, data: Optional[dict] = None):
return JSONResponse(
@@ -30,7 +34,7 @@ class EndpointSuccessResponse(BaseEndpointResponse): # 200 OK
)
class EndpointCreatedResponse(BaseEndpointResponse): # 201 Created
class EndpointCreatedResponse(BaseEndpointResponse): # 201 Created
def as_dict(self, data: Optional[dict] = None):
return JSONResponse(
@@ -39,7 +43,7 @@ class EndpointCreatedResponse(BaseEndpointResponse): # 201 Create
)
class EndpointAcceptedResponse(BaseEndpointResponse): # 202 Accepted
class EndpointAcceptedResponse(BaseEndpointResponse): # 202 Accepted
def as_dict(self, data: Optional[dict] = None):
return JSONResponse(
@@ -48,7 +52,7 @@ class EndpointAcceptedResponse(BaseEndpointResponse): # 202 Accep
)
class EndpointNotModifiedResponse(BaseEndpointResponse): # 304 Not Modified
class EndpointNotModifiedResponse(BaseEndpointResponse): # 304 Not Modified
def as_dict(self):
return JSONResponse(
@@ -57,7 +61,7 @@ class EndpointNotModifiedResponse(BaseEndpointResponse): # 304 Not
)
class EndpointBadRequestResponse(BaseEndpointResponse): # 400 Bad Request
class EndpointBadRequestResponse(BaseEndpointResponse): # 400 Bad Request
def as_dict(self, data: Optional[dict] = None):
return JSONResponse(
@@ -66,7 +70,7 @@ class EndpointBadRequestResponse(BaseEndpointResponse): # 400 Bad R
)
class EndpointUnauthorizedResponse(BaseEndpointResponse): # 401 Unauthorized
class EndpointUnauthorizedResponse(BaseEndpointResponse): # 401 Unauthorized
def as_dict(self):
return JSONResponse(
@@ -75,7 +79,7 @@ class EndpointUnauthorizedResponse(BaseEndpointResponse): # 401 Unaut
)
class EndpointForbiddenResponse(BaseEndpointResponse): # 403 Forbidden
class EndpointForbiddenResponse(BaseEndpointResponse): # 403 Forbidden
def as_dict(self):
return JSONResponse(
@@ -84,7 +88,7 @@ class EndpointForbiddenResponse(BaseEndpointResponse): # 403 Forbi
)
class EndpointNotFoundResponse(BaseEndpointResponse): # 404 Not Found
class EndpointNotFoundResponse(BaseEndpointResponse): # 404 Not Found
def as_dict(self):
return JSONResponse(
@@ -93,7 +97,7 @@ class EndpointNotFoundResponse(BaseEndpointResponse): # 404 Not F
)
class EndpointMethodNotAllowedResponse(BaseEndpointResponse): # 405 Method Not Allowed
class EndpointMethodNotAllowedResponse(BaseEndpointResponse): # 405 Method Not Allowed
def as_dict(self):
return JSONResponse(
@@ -102,7 +106,7 @@ class EndpointMethodNotAllowedResponse(BaseEndpointResponse): # 405 Metho
)
class EndpointNotAcceptableResponse(BaseEndpointResponse): # 406 Not Acceptable
class EndpointNotAcceptableResponse(BaseEndpointResponse): # 406 Not Acceptable
def as_dict(self):
return JSONResponse(
@@ -111,7 +115,7 @@ class EndpointNotAcceptableResponse(BaseEndpointResponse): # 406 Not A
)
class EndpointConflictResponse(BaseEndpointResponse): # 409 Conflict
class EndpointConflictResponse(BaseEndpointResponse): # 409 Conflict
def as_dict(self):
return JSONResponse(
@@ -120,7 +124,9 @@ class EndpointConflictResponse(BaseEndpointResponse): # 409 Confli
)
class EndpointUnprocessableEntityResponse(BaseEndpointResponse): # 422 Unprocessable Entity
class EndpointUnprocessableEntityResponse(
BaseEndpointResponse
): # 422 Unprocessable Entity
def as_dict(self, data: Optional[dict] = None):
return JSONResponse(
@@ -129,7 +135,7 @@ class EndpointUnprocessableEntityResponse(BaseEndpointResponse): # 422 Unpro
)
class EndpointTooManyRequestsResponse(BaseEndpointResponse): # 429 Too Many Requests
class EndpointTooManyRequestsResponse(BaseEndpointResponse): # 429 Too Many Requests
def __init__(self, retry_after: int, lang: str, code: str):
super().__init__(lang=lang, code=code)
@@ -143,7 +149,7 @@ class EndpointTooManyRequestsResponse(BaseEndpointResponse): # 429 Too M
)
class EndpointInternalErrorResponse(BaseEndpointResponse): # 500 Internal Server Error
class EndpointInternalErrorResponse(BaseEndpointResponse): # 500 Internal Server Error
def as_dict(self):
return JSONResponse(

View File

@@ -4,7 +4,9 @@ from pydantic import ValidationError
from fastapi import Request, WebSocket, status
from fastapi.responses import Response, JSONResponse
from ApiLayers.LanguageModels.Errors.merge_all_error_languages import MergedErrorLanguageModels
from ApiLayers.LanguageModels.Errors.merge_all_error_languages import (
MergedErrorLanguageModels,
)
from ApiLayers.ErrorHandlers.Exceptions.api_exc import HTTPExceptionApi
from ApiLayers.ErrorHandlers.bases import BaseErrorModelClass
@@ -20,13 +22,19 @@ def validation_exception_handler(request, exc: ValidationError) -> JSONResponse:
"""
validation_messages, validation_list = exc.errors() or [], []
for validation in validation_messages:
validation_list.append({
"type": dict(validation).get("type"),
"location": dict(validation).get("loc"),
"message": dict(validation).get("msg"), # todo change message with language message
"input": dict(validation).get("input"),
})
error_response_dict = dict(message=validation_list, request=str(request.url.path), title=exc.title)
validation_list.append(
{
"type": dict(validation).get("type"),
"location": dict(validation).get("loc"),
"message": dict(validation).get(
"msg"
), # todo change message with language message
"input": dict(validation).get("input"),
}
)
error_response_dict = dict(
message=validation_list, request=str(request.url.path), title=exc.title
)
return JSONResponse(
content=error_response_dict, status_code=status.HTTP_422_UNPROCESSABLE_ENTITY
)
@@ -46,6 +54,7 @@ class HTTPExceptionApiHandler:
@staticmethod
def retrieve_error_message(exc: HTTPExceptionApi, error_languages) -> str:
from ApiLayers.ErrorHandlers import DEFAULT_ERROR
return error_languages.get(str(exc.error_code).upper(), DEFAULT_ERROR)
async def handle_exception(

View File

@@ -0,0 +1,4 @@
from .defualt_error import default_errors
all_errors_list = [default_errors]

View File

@@ -0,0 +1,98 @@
default_errors = {
"NOT_CREATED": {
"tr": {
"message": "Kayıt oluşturulamadı. Lütfen tekrar deneyiniz.",
},
"en": {
"message": "Record could not be created. Please try again.",
},
},
"NOT_DELETED": {
"tr": {
"message": "Kayıt silinemedi. Lütfen tekrar deneyiniz.",
},
"en": {
"message": "Record could not be deleted. Please try again.",
},
},
"NOT_UPDATED": {
"tr": {
"message": "Kayıt güncellenemedi. Lütfen tekrar deneyiniz.",
},
"en": {
"message": "Record could not be updated. Please try again.",
},
},
"NOT_LISTED": {
"tr": {
"message": "Kayıt listelenemedi. Lütfen tekrar deneyiniz.",
},
"en": {
"message": "Record could not be listed. Please try again.",
},
},
"NOT_FOUND": {
"tr": {
"message": "Kayıt bulunamadı. Lütfen tekrar deneyiniz.",
},
"en": {
"message": "Record could not be found. Please try again.",
},
},
"ALREADY_EXISTS": {
"tr": {
"message": "Kayıt zaten mevcut. Lütfen tekrar deneyiniz.",
},
"en": {
"message": "Record already exists. Please try again.",
},
},
"IS_NOT_CONFIRMED": {
"tr": {
"message": "Kayıt onaylanmadı. Lütfen tekrar deneyiniz.",
},
"en": {
"message": "Record is not confirmed. Please try again.",
},
},
"NOT_AUTHORIZED": {
"tr": {
"message": "Yetkisiz kullanıcı. Lütfen tekrar deneyiniz.",
},
"en": {
"message": "Unauthorized user. Please try again.",
},
},
"NOT_VALID": {
"tr": {
"message": "Geçersiz veri. Lütfen tekrar deneyiniz.",
},
"en": {
"message": "Invalid data. Please try again.",
},
},
"NOT_ACCEPTABLE": {
"tr": {
"message": "Geçersiz veri. Lütfen tekrar deneyiniz.",
},
"en": {
"message": "Invalid data. Please try again.",
},
},
"INVALID_DATA": {
"tr": {
"message": "Geçersiz veri. Lütfen tekrar deneyiniz.",
},
"en": {
"message": "Invalid data. Please try again.",
},
},
"UNKNOWN_ERROR": {
"tr": {
"message": "Bilinmeyen bir hata oluştu. Lütfen tekrar deneyiniz.",
},
"en": {
"message": "An unknown error occured. Please try again.",
},
},
}

View File

@@ -0,0 +1,17 @@
from typing import Dict
LoginRequestLanguageModel: Dict[str, Dict[str, str]] = {
"tr": {
"domain": "Domain",
"access_key": "Erişim Anahtarı",
"password": "Parola",
"remember_me": "Beni Hatırla",
},
"en": {
"domain": "Domain",
"access_key": "Access Key",
"password": "Password",
"remember_me": "Remember Me",
},
}

View File

@@ -0,0 +1,5 @@
from .Auth.login import LoginRequestLanguageModel
__all__ = [
"LoginRequestLanguageModel"
]

View File

@@ -0,0 +1,3 @@
from .authentication.auth import authResponses
all_response_list = [authResponses]

View File

@@ -0,0 +1,18 @@
authResponses = {
"LOGIN_SELECT": {
"tr": {
"message": "Şirket/Görev başarılı bir şekilde seçildi.",
},
"en": {
"message": "Company/Duty selected successfully.",
},
},
"LOGIN_SUCCESS": {
"tr": {
"message": "Giriş başırı ile tamamlandı. Devam etmek için bir şirket/görev seçiniz.",
},
"en": {
"message": "Login successful. Please select an company/duty to continue.",
},
},
}

View File

@@ -0,0 +1,10 @@
responses = {
"LOGIN_SELECT": {
"tr": {
"": "",
},
"en": {
"": "",
},
},
}

View File

@@ -0,0 +1,144 @@
from ApiLayers.AllConfigs.Redis.configs import RedisValidationKeys
from ApiLayers.AllConfigs.main import LanguageConfig
from Events.Engine.set_defaults.category_cluster_models import CategoryClusterController
from Services.Redis.Actions.actions import RedisActions
class SetDefaultLanguageModelsRedis:
std_out: str = ""
def __init__(
self,
set_response_languages_list: list[dict],
set_errors_languages_list: list[dict],
):
self.responses_list: list[dict] = set_response_languages_list
self.errors_list: list[dict] = set_errors_languages_list
def __str__(self):
return f"\nPrepareLanguageModels:\n\n{self.std_out}"
def set_all(self):
# RedisActions.delete(list_keys=["*"])
RedisActions.delete(list_keys=[f"{RedisValidationKeys.LANGUAGE_MODELS}:*"])
for response in self.responses_list:
for lang in list(LanguageConfig.SUPPORTED_LANGUAGES):
for code, dict_to_set in response.items():
# [SAVE]REDIS => LANGUAGE_MODELS:STATIC:RESPONSES:{ResponseCode}:tr = {...}
redis_key = f"{RedisValidationKeys.LANGUAGE_MODELS}:{RedisValidationKeys.STATIC}"
set_key = f"{redis_key}:{RedisValidationKeys.RESPONSES}:{code}:{lang}"
RedisActions.set_json(list_keys=[set_key], value=dict_to_set)
self.std_out += f"Language Response Models are set to Redis\n"
for response in self.errors_list:
for lang in list(LanguageConfig.SUPPORTED_LANGUAGES):
for code, dict_to_set in response.items():
# [SAVE]REDIS => LANGUAGE_MODELS:STATIC:ERRORCODES:{ErrorCode}:en = {...}
redis_key = f"{RedisValidationKeys.LANGUAGE_MODELS}:{RedisValidationKeys.STATIC}"
set_key = f"{redis_key}:{code}:{lang}"
RedisActions.set_json(list_keys=[set_key], value=dict_to_set)
self.std_out += f"Language Error Models are set to Redis\n"
class SetClusterLanguageModelsRedis:
std_out: str = ""
events_lm_dict: dict[str, dict[str, dict]] = {}
events_rq_dict: dict[str, dict[str, dict]] = {}
events_rs_dict: dict[str, dict[str, dict]] = {}
def __init__(self, cluster_controller_group: CategoryClusterController):
self.cluster_controller_group = cluster_controller_group
def __str__(self):
return f"\nPrepareLanguageModels:\n\n{self.std_out}"
@staticmethod
def merge_language_dicts(list_of_lang_models: list[dict]):
"""
Merges the language models of the events to a single dictionary.
"""
merged_lang_models: dict[str, dict] = {}
for lang_model in list_of_lang_models:
for lang in list(LanguageConfig.SUPPORTED_LANGUAGES):
if not lang_model.get(lang, None):
raise ValueError(f"Language model for {lang} not found in {lang_model}")
if lang not in merged_lang_models:
merged_lang_models[lang] = lang_model[lang]
else:
merged_lang_models[lang].update(lang_model[lang])
return merged_lang_models
def set_models_from_cluster(self):
# iterate(ClusterToMethod) to set all models by pairing function codes
for cluster_control in self.cluster_controller_group.imports:
self.std_out += f"Setting models from cluster : {cluster_control.name}\n"
for endpoint in cluster_control.category_cluster.ENDPOINTS.values():
for key_event, event in endpoint.EVENTS.items():
merged_language_dict = self.merge_language_dicts(event.LANGUAGE_MODELS)
request_validation = getattr(event.REQUEST_VALIDATOR, 'model_fields', None)
response_validation = getattr(event.RESPONSE_VALIDATOR, 'model_fields', None)
objects_missing = bool(request_validation) and bool(response_validation) and bool(merged_language_dict)
if not objects_missing:
continue
if merged_language_dict:
self.events_lm_dict[key_event] = merged_language_dict
if request_validation:
self.events_rq_dict[key_event] = request_validation
if response_validation:
self.events_rs_dict[key_event] = response_validation
self.std_out += f"Request/Response/Language validation model is set {key_event}\n"
def set_all(self):
# Set all language models from cluster list by pairing event code and models
self.set_models_from_cluster()
if self.events_lm_dict and self.events_rq_dict:
"""
[SAVE]REDIS => LANGUAGE_MODELS:DYNAMIC:HEADERS:REQUEST:{FunctionCode}:tr = {...}
Get Request BaseModel pydantic model_fields of each event and set headers which are included in model_fields
"""
for lang in list(LanguageConfig.SUPPORTED_LANGUAGES): # Iterate(languages ["tr", "en"])
for key_field in self.events_rq_dict.keys(): # Iterate(function_code)
request_model = self.events_rq_dict[key_field]
if not request_model:
self.std_out += f"Request validation model not found for {key_field}\n"
continue
if key_field not in self.events_rq_dict or key_field not in self.events_lm_dict:
self.std_out += f"Request language model not found for {key_field}\n"
continue
value_to_set = {}
redis_key = f"{RedisValidationKeys.LANGUAGE_MODELS}:{RedisValidationKeys.DYNAMIC}"
set_key = f"{redis_key}:{key_field}:{lang}"
for key in request_model.keys():
value_to_set[key] = self.events_lm_dict[key_field][lang][key]
RedisActions.set_json(list_keys=[set_key], value=value_to_set)
self.std_out += f"Language Request Headers are set to Redis\n"
if self.events_lm_dict and self.events_rs_dict:
"""
[SAVE]REDIS => LANGUAGE_MODELS:DYNAMIC:HEADERS:RESPONSE:{FunctionCode}:en = {...}
Get Response BaseModel pydantic model_fields of each event and set headers which are included in model_fields
"""
for lang in list(LanguageConfig.SUPPORTED_LANGUAGES): # Iterate(languages ["tr", "en"])
for key_field in self.events_rs_dict.keys(): # Iterate(function_code)
response_model = self.events_rs_dict[key_field]
if not response_model:
self.std_out += f"Response validation model not found for {key_field}\n"
continue
if key_field not in self.events_rs_dict or key_field not in self.events_lm_dict:
self.std_out += f"Response language model not found for {key_field}\n"
continue
value_to_set = {}
redis_key = f"{RedisValidationKeys.LANGUAGE_MODELS}:{RedisValidationKeys.DYNAMIC}"
set_key = f"{redis_key}:{key_field}:{lang}"
for key in response_model.keys():
value_to_set[key] = self.events_lm_dict[key_field][lang][key]
RedisActions.set_json(list_keys=[set_key], value=value_to_set)
self.std_out += f"Language Response Headers are set to Redis\n"

View File

@@ -87,7 +87,9 @@ class MiddlewareModule:
# Get and validate token context from request
endpoint_url = str(request.url.path)
token_context = cls.get_user_from_request(request=request)
auth_context = AuthContext(auth=token_context, url=endpoint_url, request=request)
auth_context = AuthContext(
auth=token_context, url=endpoint_url, request=request
)
# Set auth context on the wrapper function itself
setattr(func, "auth_context", auth_context)

View File

@@ -135,12 +135,15 @@ class TokenEventMiddleware:
# Get and validate token context from request
# token_context, reachable_event_codes = cls.retrieve_access_content(request)
reachable_event_codes = ["g1j8i6j7-9k4h-0h6l-4i3j-2j0k1k0j0i0k"]
token_context = {"token": "context","context": {}}
token_context = {"token": "context", "context": {}}
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,
auth=token_context,
code=reachable_event_code,
url=endpoint_url,
request=request,
)
# Get auth context from the authenticated function's wrapper

View File

@@ -313,6 +313,7 @@ class Event2Employee(CrudCollection):
# return [event.endpoint_name for event in endpoint_restrictions]
#
class Event2Occupant(CrudCollection):
"""
Occupant2Event class based on declarative_base and BaseMixin via session

View File

@@ -148,7 +148,9 @@ class Users(CrudCollection, UserLoginModule, SelectAction):
@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
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,