73 lines
2.1 KiB
Python
73 lines
2.1 KiB
Python
from __future__ import annotations
|
|
|
|
import hashlib
|
|
from typing import Any
|
|
|
|
DEFAULT_PROFILE_ID = "default"
|
|
PROFILE_SESSION_TIMEOUT_SEC = 1800
|
|
|
|
|
|
def normalize_profile_id(value: Any) -> str:
|
|
profile_id = str(value or "").strip()
|
|
return profile_id if profile_id else DEFAULT_PROFILE_ID
|
|
|
|
|
|
def _profile_key(value: Any) -> str:
|
|
return normalize_profile_id(value).casefold()
|
|
|
|
|
|
def normalize_pin(value: Any) -> str | None:
|
|
pin = str(value or "").strip()
|
|
if not pin:
|
|
return None
|
|
if not pin.isdigit():
|
|
return None
|
|
if len(pin) < 4 or len(pin) > 6:
|
|
return None
|
|
return pin
|
|
|
|
|
|
def hash_profile_pin(profile_id: str, pin: str) -> str:
|
|
digest_input = f"{_profile_key(profile_id)}:{pin}"
|
|
return hashlib.sha256(digest_input.encode("utf-8")).hexdigest()
|
|
|
|
|
|
def first_query_param_value(query_params: Any, key: str) -> str | None:
|
|
raw = query_params.get(key)
|
|
if raw is None:
|
|
return None
|
|
if isinstance(raw, list):
|
|
return str(raw[0]) if raw else None
|
|
return str(raw)
|
|
|
|
|
|
def is_truthy_flag(value: Any) -> bool:
|
|
normalized = str(value or "").strip().lower()
|
|
return normalized in {"1", "true", "yes", "y", "on"}
|
|
|
|
|
|
def resolve_login_profile(session_profile: Any, query_profile: Any) -> str | None:
|
|
if str(session_profile or "").strip():
|
|
return normalize_profile_id(session_profile)
|
|
if str(query_profile or "").strip():
|
|
return normalize_profile_id(query_profile)
|
|
return None
|
|
|
|
|
|
def find_existing_profile_id(profile_id: Any, available_profiles: set[str]) -> str | None:
|
|
requested_key = _profile_key(profile_id)
|
|
for existing in available_profiles:
|
|
if _profile_key(existing) == requested_key:
|
|
return existing
|
|
return None
|
|
|
|
|
|
def profile_exists(profile_id: Any, available_profiles: set[str]) -> bool:
|
|
return find_existing_profile_id(profile_id, available_profiles) is not None
|
|
|
|
|
|
def is_profile_session_expired(last_active: Any, now_epoch: float, timeout_sec: int = PROFILE_SESSION_TIMEOUT_SEC) -> bool:
|
|
if not isinstance(last_active, (int, float)):
|
|
return False
|
|
return (now_epoch - float(last_active)) > timeout_sec
|