Spaces:
Running on Zero
Running on Zero
| """User manager — handles guest sessions, authentication, and profiles.""" | |
| import json | |
| import hashlib | |
| import secrets | |
| import logging | |
| from datetime import datetime, timedelta | |
| from typing import Optional | |
| from database.repositories import UserRepo, SettingsRepo | |
| from database import engine as db_engine | |
| logger = logging.getLogger("synapse.users") | |
| class UserManager: | |
| """Manages user accounts and sessions.""" | |
| def __init__(self): | |
| self._guest_sessions: dict[str, dict] = {} | |
| async def get_or_create_guest(self, session_id: str = None) -> dict: | |
| if not session_id: | |
| session_id = f"guest_{secrets.token_hex(8)}" | |
| if session_id in self._guest_sessions: | |
| return self._guest_sessions[session_id] | |
| user = await UserRepo.get_by_username(session_id) | |
| if not user: | |
| user = await UserRepo.create( | |
| username=session_id, | |
| display_name="Guest", | |
| ) | |
| self._guest_sessions[session_id] = user | |
| return user | |
| async def register(self, username: str, display_name: str = None, | |
| email: str = None, password: str = None) -> dict: | |
| existing = await UserRepo.get_by_username(username) | |
| if existing: | |
| raise ValueError("Username already exists") | |
| user = await UserRepo.create( | |
| username=username, | |
| display_name=display_name or username, | |
| email=email, | |
| ) | |
| if password: | |
| from database import engine | |
| pw_hash = hashlib.sha256(password.encode()).hexdigest() | |
| await SettingsRepo.set(user["id"], "password_hash", pw_hash) | |
| return user | |
| async def authenticate(self, username: str, password: str) -> Optional[dict]: | |
| user = await UserRepo.get_by_username(username) | |
| if not user: | |
| return None | |
| stored_hash = await SettingsRepo.get(user["id"], "password_hash") | |
| if not stored_hash: | |
| return None | |
| pw_hash = hashlib.sha256(password.encode()).hexdigest() | |
| if pw_hash != stored_hash: | |
| return None | |
| return user | |
| async def get_profile(self, user_id: str) -> Optional[dict]: | |
| return await UserRepo.get_by_id(user_id) | |
| async def update_profile(self, user_id: str, **kwargs) -> None: | |
| user = await UserRepo.get_by_id(user_id) | |
| if not user: | |
| return | |
| prefs = json.loads(user.get("preferences", "{}")) | |
| prefs.update(kwargs) | |
| await UserRepo.update_preferences(user_id, prefs) | |
| async def get_settings(self, user_id: str) -> dict: | |
| return await SettingsRepo.get_all(user_id) | |
| async def set_setting(self, user_id: str, key: str, value: str) -> None: | |
| await SettingsRepo.set(user_id, key, value) | |
| async def get_setting(self, user_id: str, key: str) -> Optional[str]: | |
| return await SettingsRepo.get(user_id, key) | |
| user_manager = UserManager() | |