cardserver / app /services /database.py
GitHub Actions
🚀 Auto-deploy from GitHub
86d79a3
import os
from supabase import create_client
from dotenv import load_dotenv
import bcrypt
import uuid
from datetime import datetime, timedelta
from typing import Optional, Dict, Any
load_dotenv()
SUPABASE_URL = os.getenv("SUPABASE_URL")
SUPABASE_KEY = os.getenv("SUPABASE_KEY")
supabase = create_client(SUPABASE_URL, SUPABASE_KEY)
def get_supabase_client():
return supabase
async def save_card(supabase_client, card_data: dict):
"""Speichert die Daten der generierten Horoskopkarte in Supabase."""
try:
# Map the dictionary fields to the database table
db_record = {
"terms": card_data["terms"],
"card_date": card_data["card_date"],
"card_text": card_data["card_text"],
"image_filename": card_data["image_filename"],
"qr_code_filename": card_data["qr_code_filename"],
"qr_code_link": card_data["qr_code_link"],
"session_id": str(card_data["session_id"]), # Convert UUID to string
"lang": card_data.get("lang", "de"),
"prompt_text": card_data.get("prompt_text"),
"ml_model_info": card_data.get("ml_model_info"),
"generation_params": card_data.get("generation_params")
# created_at wird von Supabase automatisch gesetzt, wenn entsprechend konfiguriert
}
response = supabase_client.table("cards").insert(db_record).execute()
return response
except Exception as e:
# Hier wäre ein besseres Logging/Fehlerhandling gut
print(f"Error saving to Supabase: {e}")
raise
# User management functions
async def get_user_by_username(username: str) -> Optional[Dict[str, Any]]:
"""Get user by username from the database"""
try:
response = supabase.table("users").select("*").eq("username", username).execute()
if response.data:
return response.data[0]
return None
except Exception as e:
print(f"Error getting user by username: {e}")
return None
async def get_user_by_email(email: str) -> Optional[Dict[str, Any]]:
"""Get user by email from the database"""
try:
response = supabase.table("users").select("*").eq("email", email).execute()
if response.data:
return response.data[0]
return None
except Exception as e:
print(f"Error getting user by email: {e}")
return None
async def create_user(username: str, email: str, password: str) -> Optional[Dict[str, Any]]:
"""Create a new user with hashed password"""
try:
# Hash the password
password_hash = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
user_data = {
"username": username,
"email": email,
"password_hash": password_hash
}
response = supabase.table("users").insert(user_data).execute()
if response.data:
return response.data[0]
return None
except Exception as e:
print(f"Error creating user: {e}")
return None
async def verify_password(plain_password: str, hashed_password: str) -> bool:
"""Verify a password against its hash"""
try:
return bcrypt.checkpw(plain_password.encode('utf-8'), hashed_password.encode('utf-8'))
except Exception as e:
print(f"Error verifying password: {e}")
return False
async def update_last_login(user_id: str):
"""Update the last login timestamp for a user"""
try:
from datetime import datetime
current_time = datetime.utcnow().isoformat()
supabase.table("users").update({"last_login": current_time}).eq("id", user_id).execute()
except Exception as e:
print(f"Error updating last login: {e}")
# Session management functions
async def create_user_session(user_id: str, token_jti: str, expires_at: datetime) -> Optional[Dict[str, Any]]:
"""Create a new user session"""
try:
session_data = {
"user_id": user_id,
"token_jti": token_jti,
"expires_at": expires_at.isoformat(),
"is_revoked": False
}
response = supabase.table("user_sessions").insert(session_data).execute()
if response.data:
return response.data[0]
return None
except Exception as e:
print(f"Error creating user session: {e}")
return None
async def get_user_session(token_jti: str) -> Optional[Dict[str, Any]]:
"""Get user session by token JTI"""
try:
response = supabase.table("user_sessions").select("*").eq("token_jti", token_jti).eq("is_revoked", False).execute()
if response.data:
return response.data[0]
return None
except Exception as e:
print(f"Error getting user session: {e}")
return None
async def revoke_user_session(token_jti: str):
"""Revoke a user session"""
try:
supabase.table("user_sessions").update({"is_revoked": True}).eq("token_jti", token_jti).execute()
except Exception as e:
print(f"Error revoking user session: {e}")
async def cleanup_expired_sessions():
"""Remove expired sessions from the database"""
try:
current_time = datetime.utcnow().isoformat()
supabase.table("user_sessions").delete().lt("expires_at", current_time).execute()
except Exception as e:
print(f"Error cleaning up expired sessions: {e}")