Financial2API / web_app /database.py
Shivam4096's picture
Upload folder using huggingface_hub
558d330 verified
Raw History Blame Contribute Delete
5.89 kB
"""
web_app/database.py — Database audit logging system.
Supports dual-driver data persistence:
- Direct Cloud Supabase PostgreSQL storage (if environment variables exist).
- Automatic Local SQLite database fallback.
"""
import os
import sqlite3
import datetime
from pathlib import Path
from typing import List, Dict
DB_PATH = Path(__file__).parent / "financial_audit.db"
def init_db():
"""Initializes the local SQLite database if not present."""
conn = sqlite3.connect(str(DB_PATH))
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS financial_analysis_audit (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TEXT NOT NULL,
user_email TEXT NOT NULL,
company_ticker TEXT NOT NULL,
company_name TEXT NOT NULL,
selected_formats TEXT NOT NULL,
ai_model_used TEXT NOT NULL,
status TEXT NOT NULL
)
""")
conn.commit()
conn.close()
def save_audit_log(user_email: str, company_ticker: str, company_name: str, selected_formats: List[str], ai_models: List[str], status: str):
"""
Saves an audit log entry.
Tries Supabase first, falls back to local SQLite on failure or if not configured.
"""
timestamp = datetime.datetime.utcnow().isoformat()
selected_formats_str = ", ".join(selected_formats)
ai_models_str = ", ".join(ai_models) if ai_models else "none"
supabase_url = os.environ.get("SUPABASE_URL")
supabase_key = os.environ.get("SUPABASE_KEY")
if supabase_url and supabase_key:
try:
from supabase import create_client, Client
supabase: Client = create_client(supabase_url, supabase_key)
data = {
"user_email": user_email,
"company_ticker": company_ticker,
"company_name": company_name,
"selected_formats": selected_formats, # stored as text array in Postgres
"ai_model_used": ai_models_str,
"status": status
}
supabase.table("financial_analysis_audit").insert(data).execute()
print("Audit log successfully written to Cloud Supabase DB.")
return
except Exception as e:
print(f"Supabase logging failed: {e}. Falling back to SQLite.")
# Local SQLite Fallback
try:
init_db()
conn = sqlite3.connect(str(DB_PATH))
cursor = conn.cursor()
cursor.execute("""
INSERT INTO financial_analysis_audit (timestamp, user_email, company_ticker, company_name, selected_formats, ai_model_used, status)
VALUES (?, ?, ?, ?, ?, ?, ?)
""", (timestamp, user_email, company_ticker, company_name, selected_formats_str, ai_models_str, status))
conn.commit()
conn.close()
print("Audit log written to local SQLite database.")
except Exception as sqle:
print(f"Local SQLite database audit write error: {sqle}")
def get_audit_logs() -> List[Dict]:
"""
Fetches the history of audit logs.
Tries Supabase first, falls back to local SQLite.
"""
supabase_url = os.environ.get("SUPABASE_URL")
supabase_key = os.environ.get("SUPABASE_KEY")
if supabase_url and supabase_key:
try:
from supabase import create_client, Client
supabase: Client = create_client(supabase_url, supabase_key)
response = supabase.table("financial_analysis_audit").select("*").order("timestamp", desc=True).limit(50).execute()
logs = []
for row in response.data:
# Convert list array from supabase to comma-separated string for display alignment
formats = row.get("selected_formats", [])
formats_str = ", ".join(formats) if isinstance(formats, list) else str(formats)
# Format timestamp
ts = row.get("timestamp", "")
if ts:
try:
ts = datetime.datetime.fromisoformat(ts.replace("Z", "+00:00")).strftime("%Y-%m-%d %H:%M:%S")
except:
pass
logs.append({
"timestamp": ts,
"user_email": row.get("user_email", "N/A"),
"company_ticker": row.get("company_ticker", "N/A"),
"company_name": row.get("company_name", "N/A"),
"selected_formats": formats_str,
"ai_model_used": row.get("ai_model_used", "N/A"),
"status": row.get("status", "N/A")
})
return logs
except Exception as e:
print(f"Supabase fetch logs failed: {e}. Falling back to SQLite.")
# SQLite Fallback
try:
init_db()
conn = sqlite3.connect(str(DB_PATH))
conn.row_factory = sqlite3.Row
cursor = conn.cursor()
cursor.execute("SELECT * FROM financial_analysis_audit ORDER BY timestamp DESC LIMIT 50")
rows = cursor.fetchall()
logs = []
for r in rows:
ts = r["timestamp"]
if ts and "T" in ts:
try:
ts = datetime.datetime.fromisoformat(ts).strftime("%Y-%m-%d %H:%M:%S")
except:
pass
logs.append({
"timestamp": ts,
"user_email": r["user_email"],
"company_ticker": r["company_ticker"],
"company_name": r["company_name"],
"selected_formats": r["selected_formats"],
"ai_model_used": r["ai_model_used"],
"status": r["status"]
})
conn.close()
return logs
except Exception as sqle:
print(f"Local SQLite logs retrieve error: {sqle}")
return []