updated Query options

This commit is contained in:
2025-01-30 14:24:42 +03:00
parent 822e4155a1
commit b664f64eb4
35 changed files with 852 additions and 589 deletions

View File

@@ -18,8 +18,6 @@ class WagRedis:
)
class RedisValidationKeys:
ENDPOINTS: str = "ENDPOINTS"
VALIDATIONS: str = "VALIDATIONS"
@@ -51,17 +49,29 @@ class RedisCategoryKeys:
PAGE_MAPPER: str = "PAGE_MAPPER"
MENU_MAPPER: str = "MENU_MAPPER"
class RedisValidationKeysAction:
# LANGUAGE_MODELS:DYNAMIC:VALIDATIONS:
dynamic_validation_key: str = f"{RedisValidationKeys.LANGUAGE_MODELS}:{RedisValidationKeys.DYNAMIC}:{RedisValidationKeys.VALIDATIONS}"
dynamic_validation_key: str = (
f"{RedisValidationKeys.LANGUAGE_MODELS}:{RedisValidationKeys.DYNAMIC}:{RedisValidationKeys.VALIDATIONS}"
)
# LANGUAGE_MODELS:DYNAMIC:HEADERS:REQUEST
dynamic_header_request_key: str = f"{RedisValidationKeys.LANGUAGE_MODELS}:{RedisValidationKeys.DYNAMIC}:{RedisValidationKeys.HEADERS}:{RedisValidationKeys.REQUESTS}"
dynamic_header_request_key: str = (
f"{RedisValidationKeys.LANGUAGE_MODELS}:{RedisValidationKeys.DYNAMIC}:{RedisValidationKeys.HEADERS}:{RedisValidationKeys.REQUESTS}"
)
# LANGUAGE_MODELS:DYNAMIC:HEADERS:RESPONSE
dynamic_header_response_key: str = f"{RedisValidationKeys.LANGUAGE_MODELS}:{RedisValidationKeys.DYNAMIC}:{RedisValidationKeys.HEADERS}:{RedisValidationKeys.RESPONSES}"
dynamic_header_response_key: str = (
f"{RedisValidationKeys.LANGUAGE_MODELS}:{RedisValidationKeys.DYNAMIC}:{RedisValidationKeys.HEADERS}:{RedisValidationKeys.RESPONSES}"
)
# LANGUAGE_MODELS:STATIC:ERRORCODES:
static_error_code_key: str = f"{RedisValidationKeys.LANGUAGE_MODELS}:{RedisValidationKeys.STATIC}:{RedisValidationKeys.ERRORCODES}"
static_error_code_key: str = (
f"{RedisValidationKeys.LANGUAGE_MODELS}:{RedisValidationKeys.STATIC}:{RedisValidationKeys.ERRORCODES}"
)
# LANGUAGE_MODELS:STATIC:RESPONSES:
static_response_key: str = f"{RedisValidationKeys.LANGUAGE_MODELS}:{RedisValidationKeys.STATIC}:{RedisValidationKeys.RESPONSES}"
static_response_key: str = (
f"{RedisValidationKeys.LANGUAGE_MODELS}:{RedisValidationKeys.STATIC}:{RedisValidationKeys.RESPONSES}"
)
# LANGUAGE_MODELS:STATIC:REQUESTS:
static_request_key: str = f"{RedisValidationKeys.LANGUAGE_MODELS}:{RedisValidationKeys.STATIC}:{RedisValidationKeys.REQUESTS}"
static_request_key: str = (
f"{RedisValidationKeys.LANGUAGE_MODELS}:{RedisValidationKeys.STATIC}:{RedisValidationKeys.REQUESTS}"
)

View File

@@ -9,7 +9,7 @@ from ApiLayers.ApiLibrary.common.line_number import get_line_number_for_error
from ApiLayers.ApiLibrary.date_time_actions.date_functions import DateTimeLocal
from ApiLayers.ApiLibrary.token.password_module import PasswordModule
from ApiLayers.ErrorHandlers import HTTPExceptionApi
from ApiLayers.Schemas.identity.identity import UsersTokens, People
from ApiLayers.ApiValidations.Custom.token_objects import (
EmployeeTokenObject,
OccupantTokenObject,
@@ -37,6 +37,7 @@ from Services.Redis import RedisActions, AccessToken
if TYPE_CHECKING:
from fastapi import Request
T = TypeVar("T", EmployeeTokenObject, OccupantTokenObject)
@@ -55,6 +56,85 @@ class TokenService:
"""Get all tokens for a user from Redis."""
return RedisActions.get_json(list_keys=[f"*:{str(user.uu_id)}"])
@classmethod
def do_employee_login(
cls, request: "Request", user: Users, domain: str
) -> Dict[str, Any]:
"""Handle employee login process and return login information."""
from ApiLayers.Schemas.identity.identity import UsersTokens, People
db_session = Employees.new_session()
list_employee = Employees.filter_all(
Employees.people_id == user.person_id, db=db_session
).data
companies_uu_id_list: List[str] = []
companies_id_list: List[int] = []
companies_list: List[Dict[str, Any]] = []
duty_uu_id_list: List[str] = []
duty_id_list: List[int] = []
for employee in list_employee:
staff = Staff.filter_one(Staff.id == employee.staff_id, db=db_session).data
if duties := Duties.filter_one(
Duties.id == staff.duties_id, db=db_session
).data:
if duty_found := Duty.filter_by_one(
id=duties.duties_id, db=db_session
).data:
duty_uu_id_list.append(str(duty_found.uu_id))
duty_id_list.append(duty_found.id)
department = Departments.filter_one(
Departments.id == duties.department_id, db=db_session
).data
if company := Companies.filter_one(
Companies.id == department.company_id, db=db_session
).data:
companies_uu_id_list.append(str(company.uu_id))
companies_id_list.append(company.id)
company_address = Addresses.filter_by_one(
id=company.official_address_id, db=db_session
).data
companies_list.append(
{
"uu_id": str(company.uu_id),
"public_name": company.public_name,
"company_type": company.company_type,
"company_address": company_address,
}
)
person = People.filter_one(People.id == user.person_id, db=db_session).data
model_value = EmployeeTokenObject(
domain=domain,
user_type=UserType.employee.value,
user_uu_id=str(user.uu_id),
credentials=user.credentials(),
user_id=user.id,
person_id=person.id,
person_uu_id=str(person.uu_id),
full_name=person.full_name,
request=dict(request.headers),
companies_uu_id_list=companies_uu_id_list,
companies_id_list=companies_id_list,
duty_uu_id_list=duty_uu_id_list,
duty_id_list=duty_id_list,
timezone=user.local_timezone or "GMT+0",
lang="tr",
).model_dump()
if access_token := cls.set_object_to_redis(user, model_value):
return {
"access_token": access_token,
"user_type": UserType.employee.name,
"selection_list": companies_list,
}
raise HTTPExceptionApi(
error_code="",
lang="en",
loc=get_line_number_for_error(),
sys_msg="Creating Token failed...",
)
@classmethod
def do_occupant_login(
cls, request: "Request", user: Users, domain: str
@@ -113,14 +193,17 @@ class TokenService:
}
else:
occupants_selection_dict[build_key]["occupants"].append(occupant_data)
person = user.person
model_value = OccupantTokenObject(
domain=domain,
user_type=UserType.occupant.value,
user_uu_id=str(user.uu_id),
credentials=user.credentials(),
user_id=user.id,
person_id=user.person_id,
person_uu_id=str(user.person.uu_id),
person_id=person.id,
person_uu_id=str(person.uu_id),
full_name=person.full_name,
request=dict(request.headers),
available_occupants=occupants_selection_dict,
timezone=user.local_timezone or "GMT+0",
@@ -180,84 +263,6 @@ class TokenService:
sys_msg="Saving Token failed...",
)
@classmethod
def do_employee_login(
cls, request: "Request", user: Users, domain: str
) -> Dict[str, Any]:
"""Handle employee login process and return login information."""
db_session = Employees.new_session()
list_employee = Employees.filter_all(
Employees.people_id == user.person_id, db=db_session
).data
companies_uu_id_list: List[str] = []
companies_id_list: List[int] = []
companies_list: List[Dict[str, Any]] = []
duty_uu_id_list: List[str] = []
duty_id_list: List[int] = []
for employee in list_employee:
staff = Staff.filter_one(Staff.id == employee.staff_id, db=db_session).data
if duties := Duties.filter_one(
Duties.id == staff.duties_id, db=db_session
).data:
if duty_found := Duty.filter_by_one(
id=duties.duties_id, db=db_session
).data:
duty_uu_id_list.append(str(duty_found.uu_id))
duty_id_list.append(duty_found.id)
department = Departments.filter_one(
Departments.id == duties.department_id, db=db_session
).data
if company := Companies.filter_one(
Companies.id == department.company_id, db=db_session
).data:
companies_uu_id_list.append(str(company.uu_id))
companies_id_list.append(company.id)
company_address = Addresses.filter_by_one(
id=company.official_address_id, db=db_session
).data
companies_list.append(
{
"uu_id": str(company.uu_id),
"public_name": company.public_name,
"company_type": company.company_type,
"company_address": company_address,
}
)
person = People.filter_one(People.id == user.person_id, db=db_session).data
model_value = EmployeeTokenObject(
domain=domain,
user_type=UserType.employee.value,
user_uu_id=str(user.uu_id),
credentials=user.credentials(),
user_id=user.id,
person_id=person.id,
person_uu_id=str(person.uu_id),
request=dict(request.headers),
companies_uu_id_list=companies_uu_id_list,
companies_id_list=companies_id_list,
duty_uu_id_list=duty_uu_id_list,
duty_id_list=duty_id_list,
timezone=user.local_timezone or "GMT+0",
lang="tr",
).model_dump()
if access_token := cls.set_object_to_redis(user, model_value):
return {
"access_token": access_token,
"user_type": UserType.employee.name,
"selection_list": companies_list,
}
raise HTTPExceptionApi(
error_code="",
lang="en",
loc=get_line_number_for_error(),
sys_msg="Creating Token failed...",
)
@classmethod
def remove_token_with_domain(cls, user: Users, domain: str) -> None:
"""Remove all tokens for a user with specific domain."""
@@ -282,6 +287,8 @@ class TokenService:
) -> Dict[str, Any]:
"""Set access token to redis and handle user session."""
from ApiLayers.AllConfigs.Token.config import Auth
from ApiLayers.Schemas.identity.identity import UsersTokens, People
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()
@@ -309,9 +316,13 @@ class TokenService:
users_token.token = users_token_created
users_token.save(db=db_session)
else:
if arrow.now() > arrow.get(str(users_token.expires_at)): # Check if token is expired
if arrow.now() > arrow.get(
str(users_token.expires_at)
): # Check if token is expired
users_token.token = users_token_created
users_token.expires_at = str(arrow.now().datetime + Auth.TOKEN_EXPIRE_DAY_1)
users_token.expires_at = str(
arrow.now().datetime + Auth.TOKEN_EXPIRE_DAY_1
)
users_token.save(db=db_session)
else:
login_dict["refresh_token"] = users_token.token

View File

@@ -33,6 +33,7 @@ class ApplicationToken(BaseModel):
person_id: int
person_uu_id: str
full_name: Optional[str] = None
request: Optional[dict] = None # Request Info of Client
expires_at: Optional[float] = None # Expiry timestamp

View File

@@ -51,7 +51,9 @@ class CreatePassword(BaseModelRegular, CreatePasswordValidation):
class OccupantSelection(BaseModel):
build_living_space_uu_id: str = Field(..., example="987fcdeb-51a2-43e7-9876-543210987654")
build_living_space_uu_id: str = Field(
..., example="987fcdeb-51a2-43e7-9876-543210987654"
)
model_config = ConfigDict(
json_schema_extra={

View File

@@ -5,9 +5,8 @@ from ApiLayers.ApiValidations.handler import BaseModelRegular
class ListOptions(BaseModelRegular):
page: Optional[int] = 1
size: Optional[int] = 10
order_field: Optional[str] = "id"
order_type: Optional[str] = "asc"
include_joins: Optional[list] = None
order_field: Optional[list[str]] = None
order_type: Optional[list[str]] = None
query: Optional[dict] = None

View File

@@ -2,7 +2,9 @@ from typing import Optional
from fastapi import status
from fastapi.responses import JSONResponse
from ApiLayers.LanguageModels.set_defaults.static_validation_retriever import StaticValidationRetriever
from ApiLayers.LanguageModels.set_defaults.static_validation_retriever import (
StaticValidationRetriever,
)
class BaseEndpointResponse(StaticValidationRetriever):

View File

@@ -26,4 +26,4 @@ SelectRequestLanguageModel: Dict[str, Dict[str, str]] = {
"company_uu_id": "Company UU ID",
"build_living_space_uu_id": "Build Living Space UU ID",
},
}
}

View File

@@ -1,5 +1,3 @@
authResponses = {
"LOGIN_SELECT": {
"tr": {
@@ -96,5 +94,5 @@ authResponses = {
"en": {
"message": "Token successfully refreshed.",
},
}
},
}

View File

@@ -1,4 +1,7 @@
from ApiLayers.AllConfigs.Redis.configs import RedisValidationKeysAction, RedisValidationKeys
from ApiLayers.AllConfigs.Redis.configs import (
RedisValidationKeysAction,
RedisValidationKeys,
)
from ApiLayers.AllConfigs.main import LanguageConfig
from Events.Engine.set_defaults.category_cluster_models import CategoryClusterController
from Services.Redis.Actions.actions import RedisActions
@@ -28,7 +31,9 @@ class SetDefaultLanguageModelsRedis:
for lang in list(LanguageConfig.SUPPORTED_LANGUAGES):
for code, dict_to_set in response.items():
# [SAVE]REDIS => LANGUAGE_MODELS:STATIC:RESPONSES:{ResponseCode}:tr = {...}
set_key = f"{RedisValidationKeysAction.static_response_key}:{code}:{lang}"
set_key = (
f"{RedisValidationKeysAction.static_response_key}:{code}:{lang}"
)
RedisActions.set_json(list_keys=[set_key], value=dict_to_set[lang])
self.std_out += f"Language Response Models are set to Redis\n"
@@ -81,10 +86,18 @@ class SetClusterLanguageModelsRedis:
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(merged_language_dict)
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(
merged_language_dict
)
if not objects_missing:
continue
if merged_language_dict:
@@ -105,17 +118,23 @@ class SetClusterLanguageModelsRedis:
[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 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"
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 are missing {key_field}\n"
self.std_out += (
f"Request language model are missing {key_field}\n"
)
continue
value_to_set = {}
@@ -130,17 +149,23 @@ class SetClusterLanguageModelsRedis:
[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 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"
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 are missing {key_field}\n"
self.std_out += (
f"Response language model are missing {key_field}\n"
)
continue
value_to_set = {}

View File

@@ -15,9 +15,12 @@ class StaticValidationRetriever:
@property
def response(self) -> Optional[dict]:
language_model = RedisActions.get_json(
list_keys=[RedisValidationKeysAction.static_response_key, self.code, self.lang]
list_keys=[
RedisValidationKeysAction.static_response_key,
self.code,
self.lang,
]
)
if language_model.status:
return language_model.first
return {"message": f"{self.code} -> Language model not found"}

View File

@@ -16,7 +16,7 @@ from sqlalchemy import (
from sqlalchemy.orm import mapped_column, relationship, Mapped
from Services.PostgresDb import CrudCollection
from config import ApiStatic
# from config import ApiStatic
from ApiLayers.ApiLibrary.date_time_actions.date_functions import system_arrow
from ApiLayers.ApiLibrary.extensions.select import (
@@ -24,7 +24,7 @@ from ApiLayers.ApiLibrary.extensions.select import (
SelectActionWithEmployee,
)
from ApiLayers.AllConfigs.Token.config import Auth
from ApiLayers.ApiServices.Login.user_login_handler import UserLoginModule
from ApiLayers.ApiValidations.Request import InsertUsers, InsertPerson
from ApiLayers.LanguageModels.Database.identity.identity import (
UsersTokensLanguageModel,
@@ -66,7 +66,7 @@ class UsersTokens(CrudCollection):
# users = relationship("Users", back_populates="tokens", foreign_keys=[user_id])
class Users(CrudCollection, UserLoginModule, SelectAction):
class Users(CrudCollection, SelectAction):
"""
Application User frame to connect to API with assigned token-based HTTP connection
"""