""" Session Manager - Singleton pattern for managing authenticated user session """ from typing import Optional, Dict, Any class SessionManager: """ Singleton session manager to maintain authenticated user state throughout the application lifecycle. """ _instance = None def __new__(cls): """Implement singleton pattern""" if cls._instance is None: cls._instance = super(SessionManager, cls).__new__(cls) cls._instance._initialized = False return cls._instance def __init__(self): """Initialize the session manager (only once)""" if self._initialized: return self._current_user = None # {username, user_type} self._initialized = True @classmethod def get_instance(cls) -> "SessionManager": """ Get the singleton instance of SessionManager Returns: The singleton SessionManager instance """ if cls._instance is None: cls._instance = cls() return cls._instance def login(self, username: str, password: str) -> bool: """ Authenticate and login a user Args: username: The username to authenticate password: The password to verify Returns: True if login successful, False otherwise """ from db.bip_users_dao import BIPUsersDAO dao = BIPUsersDAO() user_info = dao.authenticate(username, password) if user_info: self._current_user = { "username": user_info["username"], "user_type": user_info["user_type"], } return True return False def login_by_computer_name(self) -> bool: """ Attempt silent login using computer name Returns: True if login successful, False otherwise """ import socket from db.bip_users_dao import BIPUsersDAO computer_name = socket.gethostname() dao = BIPUsersDAO() user_info = dao.authenticate_by_computer_name(computer_name) if user_info: self._current_user = { "username": user_info["username"], "user_type": user_info["user_type"], } return True return False def logout(self): """Logout the current user and clear session""" self._current_user = None def is_authenticated(self) -> bool: """ Check if a user is currently authenticated Returns: True if user is logged in, False otherwise """ return self._current_user is not None def is_admin(self) -> bool: """ Check if the current user is an admin Returns: True if current user is admin, False otherwise """ if not self._current_user: return False return self._current_user.get("user_type") == "Admin" def is_guest(self) -> bool: """ Check if the current user is a guest Returns: True if current user is guest, False otherwise """ if not self._current_user: return False return self._current_user.get("user_type") == "Guest" def get_username(self) -> Optional[str]: """ Get the current username Returns: Current username if authenticated, None otherwise """ if not self._current_user: return None return self._current_user.get("username") def get_user_type(self) -> Optional[str]: """ Get the current user type Returns: Current user type if authenticated, None otherwise """ if not self._current_user: return None return self._current_user.get("user_type") def get_user_info(self) -> Optional[dict]: """ Get all current user information Returns: Dict with username and user_type if authenticated, None otherwise """ return self._current_user def switch_user(self, user_info: Dict[str, Any]) -> bool: """ Switch to a different user (Admin only feature) This allows an Admin user to operate as a different user with that user's permissions. Args: user_info: Dict with {id, username, user_type} Returns: True if switch successful """ if not self._current_user: return False # Store original admin user for reference if not hasattr(self, "_original_admin_user"): self._original_admin_user = self._current_user.copy() self._current_user = { "username": user_info["username"], "user_type": user_info["user_type"], } return True def get_original_admin(self) -> Optional[Dict[str, Any]]: """ Get the original Admin user before any user switch Returns: Original admin user dict if a switch occurred, None otherwise """ return getattr(self, "_original_admin_user", None)