Coverage for src / local_deep_research / database / session_passwords.py: 91%
23 statements
« prev ^ index » next coverage.py v7.12.0, created at 2026-01-11 00:51 +0000
« prev ^ index » next coverage.py v7.12.0, created at 2026-01-11 00:51 +0000
1"""
2Session-based password storage for metrics access.
4This module provides a way to temporarily store passwords in memory
5for the duration of a user's session, allowing background threads
6to access encrypted databases for metrics writing.
8SECURITY NOTES:
91. Passwords are only stored in memory, never on disk
102. Passwords are stored in plain text in memory (encryption removed as it
11 provided no real security benefit - see issue #593)
123. Passwords are automatically cleared on logout
134. This is only used for metrics/logging, not user data access
14"""
16from typing import Optional
18from loguru import logger
20from .credential_store_base import CredentialStoreBase
23class SessionPasswordStore(CredentialStoreBase):
24 """
25 Stores passwords temporarily for active sessions.
26 Used to allow background threads to write metrics to encrypted databases.
27 """
29 def __init__(self, ttl_hours: int = 24):
30 """
31 Initialize the session password store.
33 Args:
34 ttl_hours: How long to keep passwords (default 24 hours)
35 """
36 super().__init__(ttl_hours * 3600) # Convert to seconds
38 def store_session_password(
39 self, username: str, session_id: str, password: str
40 ) -> None:
41 """
42 Store a password for an active session.
44 Args:
45 username: The username
46 session_id: The Flask session ID
47 password: The password to store
48 """
49 key = f"{username}:{session_id}"
50 self._store_credentials(
51 key, {"username": username, "password": password}
52 )
53 logger.debug(f"Stored session password for {username}")
55 def get_session_password(
56 self, username: str, session_id: str
57 ) -> Optional[str]:
58 """
59 Retrieve a password for an active session.
61 Args:
62 username: The username
63 session_id: The Flask session ID
65 Returns:
66 The decrypted password or None if not found/expired
67 """
68 key = f"{username}:{session_id}"
69 result = self._retrieve_credentials(key, remove=False)
70 return result[1] if result else None
72 def clear_session(self, username: str, session_id: str) -> None:
73 """
74 Clear password for a specific session (on logout).
76 Args:
77 username: The username
78 session_id: The Flask session ID
79 """
80 key = f"{username}:{session_id}"
81 self.clear_entry(key)
82 logger.debug(f"Cleared session password for {username}")
84 # Implement abstract methods for compatibility
85 def store(self, username: str, session_id: str, password: str) -> None:
86 """Alias for store_session_password."""
87 self.store_session_password(username, session_id, password)
89 def retrieve(self, username: str, session_id: str) -> Optional[str]:
90 """Alias for get_session_password."""
91 return self.get_session_password(username, session_id)
94# Global instance
95session_password_store = SessionPasswordStore()