102 lines
5.2 KiB
Python
102 lines
5.2 KiB
Python
"""Shared SQLite database pentru toate datele auth-related (trusted devices, backup codes, email cache)."""
|
|
import aiosqlite
|
|
import logging
|
|
from pathlib import Path
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
DB_DIR = Path(__file__).parent.parent.parent / "backend" / "data"
|
|
DB_PATH = DB_DIR / "app.db"
|
|
|
|
|
|
async def get_db() -> aiosqlite.Connection:
|
|
conn = await aiosqlite.connect(DB_PATH)
|
|
conn.row_factory = aiosqlite.Row
|
|
return conn
|
|
|
|
|
|
async def init_app_db():
|
|
"""Create all auth-related tables. Safe to call multiple times."""
|
|
DB_DIR.mkdir(parents=True, exist_ok=True)
|
|
async with aiosqlite.connect(DB_PATH) as db:
|
|
await db.execute("PRAGMA journal_mode=WAL")
|
|
await db.execute("PRAGMA busy_timeout=5000")
|
|
await db.execute("PRAGMA foreign_keys = ON")
|
|
|
|
# Telegram tables (delegate init from telegram/db/database.py)
|
|
await db.execute("""CREATE TABLE IF NOT EXISTS telegram_users (
|
|
telegram_user_id INTEGER PRIMARY KEY,
|
|
username TEXT, first_name TEXT NOT NULL, last_name TEXT,
|
|
oracle_username TEXT, jwt_token TEXT, jwt_refresh_token TEXT,
|
|
token_expires_at TIMESTAMP, linked_at TIMESTAMP,
|
|
last_active_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, is_active BOOLEAN DEFAULT 1
|
|
)""")
|
|
await db.execute("""CREATE TABLE IF NOT EXISTS telegram_auth_codes (
|
|
code TEXT PRIMARY KEY, telegram_user_id INTEGER, oracle_username TEXT,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, expires_at TIMESTAMP NOT NULL,
|
|
used BOOLEAN DEFAULT 0, used_at TIMESTAMP, server_id TEXT,
|
|
FOREIGN KEY (telegram_user_id) REFERENCES telegram_users(telegram_user_id)
|
|
)""")
|
|
await db.execute("""CREATE TABLE IF NOT EXISTS telegram_sessions (
|
|
session_id TEXT PRIMARY KEY, telegram_user_id INTEGER NOT NULL,
|
|
conversation_state TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, expires_at TIMESTAMP NOT NULL,
|
|
FOREIGN KEY (telegram_user_id) REFERENCES telegram_users(telegram_user_id)
|
|
)""")
|
|
await db.execute("""CREATE TABLE IF NOT EXISTS email_auth_codes (
|
|
code TEXT PRIMARY KEY, email TEXT NOT NULL, oracle_username TEXT NOT NULL,
|
|
telegram_user_id INTEGER NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
expires_at TIMESTAMP NOT NULL, used INTEGER DEFAULT 0, used_at TIMESTAMP,
|
|
failed_attempts INTEGER DEFAULT 0,
|
|
FOREIGN KEY (telegram_user_id) REFERENCES telegram_users(telegram_user_id)
|
|
)""")
|
|
|
|
# Trusted devices (migrated from JSON)
|
|
await db.execute("""CREATE TABLE IF NOT EXISTS trusted_devices (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
token_hash TEXT NOT NULL UNIQUE,
|
|
username TEXT NOT NULL,
|
|
server_id TEXT,
|
|
expires_at TIMESTAMP NOT NULL,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
)""")
|
|
|
|
# Backup codes (new)
|
|
await db.execute("""CREATE TABLE IF NOT EXISTS backup_codes (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
username TEXT NOT NULL,
|
|
server_id TEXT,
|
|
code_hash TEXT NOT NULL,
|
|
used INTEGER DEFAULT 0,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
used_at TIMESTAMP
|
|
)""")
|
|
|
|
# Email-server cache (migrated from in-memory)
|
|
await db.execute("""CREATE TABLE IF NOT EXISTS email_server_cache (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
email TEXT NOT NULL,
|
|
server_id TEXT NOT NULL,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
UNIQUE(email, server_id)
|
|
)""")
|
|
|
|
# Indexes for telegram
|
|
await db.execute("CREATE INDEX IF NOT EXISTS idx_auth_codes_telegram_user ON telegram_auth_codes(telegram_user_id)")
|
|
await db.execute("CREATE INDEX IF NOT EXISTS idx_auth_codes_expires ON telegram_auth_codes(expires_at)")
|
|
await db.execute("CREATE INDEX IF NOT EXISTS idx_sessions_telegram_user ON telegram_sessions(telegram_user_id)")
|
|
await db.execute("CREATE INDEX IF NOT EXISTS idx_sessions_expires ON telegram_sessions(expires_at)")
|
|
await db.execute("CREATE INDEX IF NOT EXISTS idx_email_auth_email ON email_auth_codes(email)")
|
|
await db.execute("CREATE INDEX IF NOT EXISTS idx_email_auth_telegram_user ON email_auth_codes(telegram_user_id)")
|
|
await db.execute("CREATE INDEX IF NOT EXISTS idx_email_auth_expires ON email_auth_codes(expires_at)")
|
|
|
|
# Indexes for new tables
|
|
await db.execute("CREATE INDEX IF NOT EXISTS idx_trusted_devices_user ON trusted_devices(username, server_id)")
|
|
await db.execute("CREATE INDEX IF NOT EXISTS idx_trusted_devices_expires ON trusted_devices(expires_at)")
|
|
await db.execute("CREATE INDEX IF NOT EXISTS idx_backup_codes_user ON backup_codes(username, server_id)")
|
|
await db.execute("CREATE INDEX IF NOT EXISTS idx_email_cache_email ON email_server_cache(email)")
|
|
await db.execute("CREATE INDEX IF NOT EXISTS idx_email_cache_server ON email_server_cache(server_id)")
|
|
|
|
await db.commit()
|
|
logger.info("[APP_DB] Database initialized successfully")
|