validations and dockerfiles are updated

This commit is contained in:
2025-01-10 12:40:52 +03:00
parent f4f9e584ff
commit 4eb95e4d9c
107 changed files with 400185 additions and 1338 deletions

View File

@@ -1,24 +1,8 @@
import json
import typing
from api_services.redis.conn import redis_cli
class RedisResponse:
def __init__(
self, status: bool, message: str, data: dict = None, error: str = None
):
self.status = status
self.message = message
self.data = data
self.error = error
def as_dict(self):
return {
"status": self.status,
"message": self.message,
"data": self.data,
"error": self.error,
}
from api_library.date_time_actions.date_functions import system_arrow
from api_objects import OccupantTokenObject, EmployeeTokenObject
class RedisActions:
@@ -63,6 +47,42 @@ class RedisActions:
error=str(e),
)
@classmethod
def get_with_regex(cls, value_regex):
try:
already_tokens = redis_cli.scan_iter(match=str(value_regex))
for already_token in already_tokens:
return RedisResponse(
status=True,
message="Single value is retrieved successfully.",
data=json.loads(redis_cli.get(already_token)),
)
except Exception as e:
return RedisResponse(
status=False,
message="Values are not listed successfully.",
error=str(e),
)
@classmethod
def list_all(cls, value_regex):
try:
already_tokens = redis_cli.scan_iter(match=str(value_regex))
already_tokens_list = {}
for already_token in already_tokens:
already_tokens_list[already_token.decode()] = json.loads(redis_cli.get(already_token))
return RedisResponse(
status=True,
message="Values are listed successfully.",
data=already_tokens_list,
)
except Exception as e:
return RedisResponse(
status=False,
message="Values are not listed successfully.",
error=str(e),
)
@classmethod
def set_replace_all(cls, value, value_regex):
try:
@@ -159,84 +179,218 @@ class RedisActions:
error=str(e),
)
@classmethod
def set_json_with_expiry(cls, name, value, **expiry_kwargs):
"""Set JSON value with expiry time
Example: set_json_with_expiry('key', value, hours=1, minutes=30)
"""
try:
search_name = str(name) if isinstance(name, str) else name.decode()
expiry_time = system_arrow.get_expiry_time(**expiry_kwargs)
seconds_until_expiry = int(expiry_time.timestamp() - system_arrow.now().timestamp())
redis_cli.setex(
name=search_name,
time=seconds_until_expiry,
value=json.dumps({
'value': value,
'expires_at': expiry_time.timestamp()
})
)
return RedisResponse(
status=True,
message="Value is set successfully with expiry.",
data={'value': value, 'expires_at': expiry_time.timestamp()},
)
except Exception as e:
return RedisResponse(
status=False,
message="Value is not set successfully.",
error=str(e),
)
# def get_object_via_access_key(
# request,
# ):
#
# if not hasattr(request, "headers"):
# raise redis_imports.exceptions(
# status_code=401,
# detail=dict(
# message="Headers are not found in request. Invalid request object."
# ),
# )
# if not request.headers.get(redis_imports.ACCESS_TOKEN_TAG):
# raise redis_imports.exceptions(
# status_code=401,
# detail=dict(message="Unauthorized user, please login..."),
# )
# already_tokens = redis_cli.scan_iter(
# match=str(request.headers.get(redis_imports.ACCESS_TOKEN_TAG) + ":*")
# )
# if already_tokens := list(already_tokens):
# try:
# if redis_object := json.loads(
# redis_cli.get(already_tokens[0].decode()) or {}
# ):
# if redis_object.get("user_type") == 1:
# if not redis_object.get("selected_company", None):
# redis_object["selected_company"] = None
# return redis_imports.EmployeeTokenObject(**redis_object)
# elif redis_object.get("user_type") == 2:
# if not redis_object.get("selected_occupant", None):
# redis_object["selected_occupant"] = None
# return redis_imports.OccupantTokenObject(**redis_object)
# raise redis_imports.exceptions(
# status_code=401,
# detail=dict(
# message="User type is not found in the token object. Please reach to your administrator."
# ),
# )
# except Exception as e:
# raise redis_imports.exceptions(
# status_code=500,
# detail={
# "message": "Redis Service raised an exception.",
# "error": str(e),
# },
# )
#
# raise redis_imports.exceptions(
# status_code=redis_imports.status.HTTP_401_UNAUTHORIZED,
# detail="Invalid credentials. Please login again.",
# )
#
#
# def get_object_via_user_uu_id(user_id: str) -> typing.Union[dict, None]:
# already_tokens = redis_cli.scan_iter(match=str("*:" + str(user_id)))
# already_tokens_list, already_tokens_dict = [], {}
# for already_token in already_tokens:
# redis_object = json.loads(redis_cli.get(already_token) or {})
# already_tokens_list.append(redis_object)
# already_tokens_dict[already_token.decode()] = redis_object
# return already_tokens_dict
#
#
# def save_object_to_redis(
# access_token, model_object, redis_imports: RedisImports
# ) -> bool:
# try:
# if redis_cli.set(
# name=str(access_token) + ":" + str(model_object.user_uu_id),
# value=model_object.model_dump_json(),
# ):
# return access_token
# except Exception as e:
# print("Save Object to Redis Error: ", e)
# raise redis_imports.exceptions(
# status_code=redis_imports.status.HTTP_503_SERVICE_UNAVAILABLE,
# detail=dict(
# message="Headers are not found in request. Invalid request object. Redis Error: Token is not saved."
# ),
# )
@classmethod
def get_json_if_valid(cls, name):
"""Get JSON value if not expired"""
try:
search_name = str(name) if isinstance(name, str) else name.decode()
result = redis_cli.get(name=search_name)
if not result:
return RedisResponse(
status=False,
message="Key not found.",
)
data = json.loads(result)
if system_arrow.is_expired(data.get('expires_at')):
redis_cli.delete(search_name)
return RedisResponse(
status=False,
message="Cache expired.",
)
return RedisResponse(
status=True,
message="Value retrieved successfully.",
data=data['value'],
)
except Exception as e:
return RedisResponse(
status=False,
message="Error retrieving value.",
error=str(e),
)
@classmethod
def cache_with_timezone(cls, name, value, timezone=None, **expiry_kwargs):
"""Cache value with timezone-aware key"""
try:
dt = DateTimeLocal(timezone=timezone) if timezone else system_arrow
cache_key = dt.get_cache_key(name)
return cls.set_json_with_expiry(cache_key, value, **expiry_kwargs)
except Exception as e:
return RedisResponse(
status=False,
message="Error caching with timezone.",
error=str(e),
)
@classmethod
def save_object_to_redis(cls, access_token, model_object, expiry_minutes: int = 30):
"""Save object to Redis with expiry time
Args:
access_token: The access token to use as key prefix
model_object: The model object to save (must have user_uu_id attribute and model_dump_json method)
expiry_minutes: Minutes until the token expires (default: 30)
Returns:
str: The access token if successful
Raises:
Exception: If saving fails
"""
try:
key = f"{access_token}:{model_object.user_uu_id}"
expiry_time = system_arrow.get_expiry_time(minutes=expiry_minutes)
seconds_until_expiry = max(1, int(expiry_time.timestamp() - system_arrow.now().timestamp()))
# Add expiry time to the model data
model_data = json.loads(model_object.model_dump_json())
model_data['expires_at'] = expiry_time.timestamp()
if redis_cli.setex(
name=key,
time=seconds_until_expiry,
value=json.dumps(model_data)
):
return access_token
except Exception as e:
raise Exception(
f"Failed to save object to Redis. Error: {str(e)}"
)
raise Exception("Failed to save token to Redis")
@classmethod
def get_object_via_access_key(cls, request):
"""Get object from Redis using access key from request headers
Args:
request: The request object containing headers
Returns:
Union[EmployeeTokenObject, OccupantTokenObject]: The token object
Raises:
Exception: If retrieval fails or token is invalid
"""
from api_configs.configs import Auth
from api_library.date_time_actions.date_functions import system_arrow
if not hasattr(request, "headers"):
raise Exception("Headers not found in request")
access_token = request.headers.get(Auth.ACCESS_TOKEN_TAG)
if not access_token:
raise Exception("Unauthorized user, please login")
# Scan for matching tokens
token_pattern = f"{access_token}:*"
matching_tokens = list(redis_cli.scan_iter(match=token_pattern))
if not matching_tokens:
raise Exception("Invalid credentials. Please login again")
try:
# Check if token has expired in Redis
token_key = matching_tokens[0]
ttl = redis_cli.ttl(token_key)
if ttl <= 0:
redis_cli.delete(token_key)
raise Exception("Token expired. Please login again")
# Get the token data
token_data = json.loads(redis_cli.get(token_key) or '{}')
# Return appropriate token object based on user type
if token_data.get("user_type") == 1: # Employee
if not token_data.get("selected_company"):
token_data["selected_company"] = None
return EmployeeTokenObject(**token_data)
elif token_data.get("user_type") == 2: # Occupant
if not token_data.get("selected_occupant"):
token_data["selected_occupant"] = None
return OccupantTokenObject(**token_data)
raise Exception("Invalid user type in token")
except Exception as e:
raise Exception(f"Failed to retrieve token: {str(e)}")
@classmethod
def get_object_via_user_uu_id(cls, user_id: str) -> typing.Union[dict, None]:
"""Get all objects for a user by UUID
Args:
user_id: The user UUID to search for
Returns:
dict: Dictionary of token keys and their corresponding objects
"""
token_pattern = f"*:{str(user_id)}"
matching_tokens = redis_cli.scan_iter(match=token_pattern)
tokens_dict = {}
for token_key in matching_tokens:
token_data = json.loads(redis_cli.get(token_key) or '{}')
# Skip expired tokens and clean them up
if system_arrow.is_expired(token_data.get('expires_at')):
redis_cli.delete(token_key)
continue
tokens_dict[token_key.decode()] = token_data
return tokens_dict
class RedisResponse:
def __init__(
self, status: bool, message: str, data: typing.Union[dict | list] = None, error: str = None
):
self.status = status
self.message = message
self.data = data
if isinstance(data, dict):
self.data_type = "dict"
elif isinstance(data, list):
self.data_type = "list"
elif data is None:
self.data_type = None
self.error = error
def as_dict(self):
return {
"status": self.status,
"message": self.message,
"data": self.data,
"data_type": self.data_type,
"error": self.error,
}