211 lines
6.4 KiB
Python
211 lines
6.4 KiB
Python
import enum
|
|
|
|
from typing import Optional, Union, Dict, Any, List
|
|
from pydantic import BaseModel
|
|
from Controllers.Redis.database import RedisActions
|
|
from ..config import api_config
|
|
|
|
|
|
class UserType(enum.Enum):
|
|
|
|
employee = 1
|
|
occupant = 2
|
|
|
|
|
|
class Credentials(BaseModel):
|
|
|
|
person_id: int
|
|
person_name: str
|
|
|
|
|
|
class ApplicationToken(BaseModel):
|
|
# Application Token Object -> is the main object for the user
|
|
|
|
user_type: int = UserType.occupant.value
|
|
credential_token: str = ""
|
|
|
|
user_uu_id: str
|
|
user_id: int
|
|
|
|
person_id: int
|
|
person_uu_id: str
|
|
|
|
request: Optional[dict] = None # Request Info of Client
|
|
expires_at: Optional[float] = None # Expiry timestamp
|
|
|
|
|
|
class OccupantToken(BaseModel):
|
|
|
|
# Selection of the occupant type for a build part is made by the user
|
|
|
|
living_space_id: int # Internal use
|
|
living_space_uu_id: str # Outer use
|
|
|
|
occupant_type_id: int
|
|
occupant_type_uu_id: str
|
|
occupant_type: str
|
|
|
|
build_id: int
|
|
build_uuid: str
|
|
build_part_id: int
|
|
build_part_uuid: str
|
|
|
|
responsible_company_id: Optional[int] = None
|
|
responsible_company_uuid: Optional[str] = None
|
|
responsible_employee_id: Optional[int] = None
|
|
responsible_employee_uuid: Optional[str] = None
|
|
|
|
reachable_event_codes: Optional[dict[str, list[str]]] = (
|
|
None # ID list of reachable modules
|
|
)
|
|
reachable_app_codes: Optional[dict[str, list[str]]] = (
|
|
None # ID list of reachable modules
|
|
)
|
|
|
|
|
|
class CompanyToken(BaseModel):
|
|
|
|
# Selection of the company for an employee is made by the user
|
|
company_id: int
|
|
company_uu_id: str
|
|
|
|
department_id: int # ID list of departments
|
|
department_uu_id: str # ID list of departments
|
|
|
|
duty_id: int
|
|
duty_uu_id: str
|
|
|
|
staff_id: int
|
|
staff_uu_id: str
|
|
|
|
employee_id: int
|
|
employee_uu_id: str
|
|
|
|
bulk_duties_id: int
|
|
|
|
reachable_event_codes: Optional[dict[str, list[str]]] = (
|
|
None # ID list of reachable modules
|
|
)
|
|
reachable_app_codes: Optional[dict[str, list[str]]] = (
|
|
None # ID list of reachable modules
|
|
)
|
|
|
|
|
|
class OccupantTokenObject(ApplicationToken):
|
|
# Occupant Token Object -> Requires selection of the occupant type for a specific build part
|
|
|
|
available_occupants: dict = None
|
|
selected_occupant: Optional[OccupantToken] = None # Selected Occupant Type
|
|
|
|
@property
|
|
def is_employee(self) -> bool:
|
|
return False
|
|
|
|
@property
|
|
def is_occupant(self) -> bool:
|
|
return True
|
|
|
|
|
|
class EmployeeTokenObject(ApplicationToken):
|
|
# Full hierarchy Employee[staff_id] -> Staff -> Duty -> Department -> Company
|
|
|
|
companies_id_list: List[int] # List of company objects
|
|
companies_uu_id_list: List[str] # List of company objects
|
|
|
|
duty_id_list: List[int] # List of duty objects
|
|
duty_uu_id_list: List[str] # List of duty objects
|
|
|
|
selected_company: Optional[CompanyToken] = None # Selected Company Object
|
|
|
|
@property
|
|
def is_employee(self) -> bool:
|
|
return True
|
|
|
|
@property
|
|
def is_occupant(self) -> bool:
|
|
return False
|
|
|
|
|
|
TokenDictType = Union[EmployeeTokenObject, OccupantTokenObject]
|
|
|
|
|
|
class TokenProvider:
|
|
|
|
AUTH_KEY: str = api_config.ACCESS_TOKEN_TAG
|
|
AUTH_TOKEN: str = "AUTH_TOKEN"
|
|
|
|
@classmethod
|
|
def process_redis_object(cls, redis_object: Dict[str, Any]) -> TokenDictType:
|
|
"""
|
|
Process Redis object and return appropriate token object.
|
|
"""
|
|
if not redis_object.get("selected_company"):
|
|
redis_object["selected_company"] = None
|
|
if not redis_object.get("selected_occupant"):
|
|
redis_object["selected_occupant"] = None
|
|
if redis_object.get("user_type") == UserType.employee.value:
|
|
return EmployeeTokenObject(**redis_object)
|
|
elif redis_object.get("user_type") == UserType.occupant.value:
|
|
return OccupantTokenObject(**redis_object)
|
|
raise ValueError("Invalid user type")
|
|
|
|
@classmethod
|
|
def get_dict_from_redis(
|
|
cls, token: Optional[str] = None, user_uu_id: Optional[str] = None
|
|
) -> Union[TokenDictType, List[TokenDictType]]:
|
|
"""
|
|
Retrieve token object from Redis using token and user_uu_id
|
|
"""
|
|
token_to_use, user_uu_id_to_use = token or "*", user_uu_id or "*"
|
|
list_of_token_dict, auth_key_list = [], [
|
|
cls.AUTH_TOKEN,
|
|
token_to_use,
|
|
user_uu_id_to_use,
|
|
]
|
|
if token:
|
|
result = RedisActions.get_json(list_keys=auth_key_list, limit=1)
|
|
if first_record := result.first:
|
|
return cls.process_redis_object(first_record)
|
|
elif user_uu_id:
|
|
result = RedisActions.get_json(list_keys=auth_key_list)
|
|
if all_records := result.all:
|
|
for all_record in all_records:
|
|
list_of_token_dict.append(cls.process_redis_object(all_record))
|
|
return list_of_token_dict
|
|
raise ValueError(
|
|
"Token not found in Redis. Please check the token or user_uu_id."
|
|
)
|
|
|
|
@classmethod
|
|
def retrieve_application_codes(
|
|
cls, page_url: str, tokens: Union[TokenDictType, List[TokenDictType]]
|
|
):
|
|
if isinstance(tokens, TokenDictType):
|
|
if application_codes := tokens.reachable_app_codes.get(page_url, None):
|
|
return application_codes
|
|
elif isinstance(tokens, list):
|
|
retrieved_event_apps = []
|
|
for token in tokens:
|
|
if application_codes := token.reachable_app_codes.get(page_url, None):
|
|
retrieved_event_apps.append(application_codes)
|
|
return retrieved_event_apps
|
|
raise ValueError("Invalid token type or no application codes found.")
|
|
|
|
@classmethod
|
|
def retrieve_event_codes(
|
|
cls, endpoint_code: str, tokens: Union[TokenDictType, List[TokenDictType]]
|
|
):
|
|
if isinstance(tokens, TokenDictType):
|
|
if event_codes := tokens.reachable_event_codes.get(endpoint_code, None):
|
|
return event_codes
|
|
elif isinstance(tokens, List):
|
|
retrieved_event_codes = []
|
|
for token in tokens:
|
|
if isinstance(token, TokenDictType):
|
|
if event_codes := token.reachable_event_codes.get(
|
|
endpoint_code, None
|
|
):
|
|
retrieved_event_codes.append(event_codes)
|
|
return retrieved_event_codes
|
|
raise ValueError("Invalid token type or no event codes found.")
|