Make sessions persistent across server reboots

- Added sessions table to database for persistent session storage
- Modified SessionManager to use database instead of in-memory storage
- Added database functions for session management
- Remember me functionality now works across server reboots
parent 3a865ff1
......@@ -21,47 +21,33 @@ Authentication and session management for Video AI.
import time
import secrets
from typing import Optional, Dict, Any
from .database import authenticate_user, validate_api_token
from .database import authenticate_user, validate_api_token, create_persistent_session, get_persistent_session, destroy_persistent_session
class SessionManager:
"""Simple session manager using in-memory storage."""
"""Session manager using persistent database storage."""
def __init__(self):
self.sessions: Dict[str, Dict[str, Any]] = {}
self.session_timeout = 3600 # 1 hour
def create_session(self, user: Dict[str, Any]) -> str:
"""Create a new session for user."""
session_id = secrets.token_hex(32)
self.sessions[session_id] = {
'user': user,
'created_at': time.time(),
'last_activity': time.time()
}
return session_id
"""Create a new persistent session for user."""
return create_persistent_session(user['id'])
def get_session(self, session_id: str) -> Optional[Dict[str, Any]]:
"""Get session data."""
if session_id in self.sessions:
session = self.sessions[session_id]
if time.time() - session['last_activity'] > self.session_timeout:
# Session expired
del self.sessions[session_id]
return None
session['last_activity'] = time.time()
return session
return None
"""Get session data from database."""
return get_persistent_session(session_id)
def destroy_session(self, session_id: str) -> None:
"""Destroy session."""
if session_id in self.sessions:
del self.sessions[session_id]
"""Destroy persistent session."""
destroy_persistent_session(session_id)
def get_user_from_session(self, session_id: str) -> Optional[Dict[str, Any]]:
"""Get user from session."""
"""Get user from persistent session."""
session = self.get_session(session_id)
return session['user'] if session else None
if session:
return session['user']
return None
# Global session manager instance
......
......@@ -345,6 +345,28 @@ def init_db(conn) -> None:
)
''')
# Sessions table for persistent sessions
if config['type'] == 'mysql':
cursor.execute('''
CREATE TABLE IF NOT EXISTS sessions (
session_id VARCHAR(255) PRIMARY KEY,
user_id INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_activity TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
''')
else:
cursor.execute('''
CREATE TABLE IF NOT EXISTS sessions (
session_id TEXT PRIMARY KEY,
user_id INTEGER NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_activity TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users (id)
)
''')
# Remember tokens table
if config['type'] == 'mysql':
cursor.execute('''
......@@ -1314,4 +1336,77 @@ def delete_expired_remember_tokens() -> None:
cursor = conn.cursor()
cursor.execute('DELETE FROM remember_tokens WHERE expires_at <= ?', (int(time.time()),))
conn.commit()
conn.close()
# Session management functions
def create_persistent_session(user_id: int) -> str:
"""Create a persistent session in database."""
import secrets
session_id = secrets.token_hex(32)
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute('INSERT INTO sessions (session_id, user_id) VALUES (?, ?)', (session_id, user_id))
conn.commit()
conn.close()
return session_id
def get_persistent_session(session_id: str) -> Optional[Dict[str, Any]]:
"""Get persistent session from database."""
import time
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute('''
SELECT s.session_id, s.user_id, s.created_at, s.last_activity, u.id, u.username, u.email, u.role, u.active
FROM sessions s
JOIN users u ON s.user_id = u.id
WHERE s.session_id = ? AND u.active = 1
''', (session_id,))
row = cursor.fetchone()
if row:
# Update last activity
cursor.execute('UPDATE sessions SET last_activity = CURRENT_TIMESTAMP WHERE session_id = ?', (session_id,))
conn.commit()
# Check if session is expired (1 hour)
import time
last_activity = time.mktime(time.strptime(str(row['last_activity']), '%Y-%m-%d %H:%M:%S'))
if time.time() - last_activity > 3600: # 1 hour
cursor.execute('DELETE FROM sessions WHERE session_id = ?', (session_id,))
conn.commit()
conn.close()
return None
user = {
'id': row['id'],
'username': row['username'],
'email': row['email'],
'role': row['role'],
'active': row['active']
}
conn.close()
return {'user': user}
conn.close()
return None
def destroy_persistent_session(session_id: str) -> None:
"""Destroy persistent session."""
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute('DELETE FROM sessions WHERE session_id = ?', (session_id,))
conn.commit()
conn.close()
def cleanup_expired_sessions() -> None:
"""Clean up expired sessions (older than 1 hour)."""
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute("DELETE FROM sessions WHERE last_activity < datetime('now', '-1 hour')")
conn.commit()
conn.close()
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment