When an Admin user logs in, display a centered dialog allowing them to
select which user identity to use for the session. The Admin adopts the
selected user's permissions and operates as that user throughout the session.
Changes:
- Add UserSelectionDialog class in gui/user_selection_dialog.py
- Add SessionManager.switch_user() method to switch user identity
- Add SessionManager.get_original_admin() method to retrieve original admin
- Update MainWindow status bar to show when Admin operates as another user
- Display format: "当前用户: {username} ({type}) - 以 {admin_username} 身份登录"
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
188 lines
5.1 KiB
Python
188 lines
5.1 KiB
Python
"""
|
|
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)
|