Spaces:
Sleeping
Sleeping
| import os | |
| from supabase import create_client, Client | |
| import bcrypt | |
| from dotenv import load_dotenv | |
| # Force environment reload safely | |
| load_dotenv() | |
| SUPABASE_URL = os.environ.get("SUPABASE_URL") | |
| SUPABASE_KEY = os.environ.get("SUPABASE_KEY") | |
| if not SUPABASE_URL or not SUPABASE_KEY: | |
| raise ValueError("CRITICAL: Missing SUPABASE_URL or SUPABASE_KEY inside the .env file! Phase 7 requires this constraint.") | |
| def get_supabase() -> Client: | |
| return create_client(SUPABASE_URL, SUPABASE_KEY) | |
| def create_user(email, password=None, provider="email"): | |
| user = get_user_by_email(email) | |
| if user: | |
| return False, "Email already registered." | |
| password_hash = None | |
| if password: | |
| password_hash = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8') | |
| try: | |
| res = get_supabase().table("users").insert({ | |
| "email": email.lower(), | |
| "password_hash": password_hash, | |
| "provider": provider | |
| }).execute() | |
| if provider != "email": | |
| return res.data[0]["id"] | |
| return True, "Account successfully created! Please log in." | |
| except Exception as e: | |
| if provider != "email": return None | |
| return False, f"Database error: {e}" | |
| def authenticate_user(email, password): | |
| user = get_user_by_email(email) | |
| if not user: | |
| return False, "User not found." | |
| stored_hash = user.get("password_hash") | |
| if stored_hash: | |
| if bcrypt.checkpw(password.encode('utf-8'), stored_hash.encode('utf-8')): | |
| return True, user["id"] | |
| else: | |
| return False, "Incorrect password." | |
| else: | |
| return False, f"Account uses OAuth. Please login with {user.get('provider')}." | |
| def get_user_by_email(email): | |
| res = get_supabase().table("users").select("*").eq("email", email.lower()).execute() | |
| if res.data and len(res.data) > 0: | |
| return res.data[0] | |
| return None | |
| def get_user_by_id(user_id): | |
| res = get_supabase().table("users").select("*").eq("id", user_id).execute() | |
| if res.data and len(res.data) > 0: | |
| return res.data[0] | |
| return None | |
| def authenticate_oauth_user(email, provider): | |
| user = get_user_by_email(email) | |
| if user: | |
| return True, user["id"] | |
| # create_user returns (True, Msg) or (False, Msg) or raw ID if not email. | |
| # Actually create_user returns ID directly if provider != "email": | |
| # Let's cleanly orchestrate the ID return: | |
| uid = create_user(email, provider=provider) | |
| if uid: | |
| return True, uid | |
| return False, "Failed to authenticate with provider." | |
| def create_session(user_id, filename, pdf_text, notes): | |
| payload = { | |
| "user_id": user_id, | |
| "filename": filename, | |
| "pdf_text": pdf_text, | |
| "notes": notes, | |
| "chat_history": [] | |
| } | |
| res = get_supabase().table("sessions").insert(payload).execute() | |
| return res.data[0]["id"] | |
| def get_all_sessions(user_id): | |
| # Retrieve all columns inherently required by `app.py` list map loops | |
| res = get_supabase().table("sessions").select("*").eq("user_id", user_id).order("timestamp", desc=True).execute() | |
| return res.data if res.data else [] | |
| def get_session(session_id): | |
| res = get_supabase().table("sessions").select("*").eq("id", session_id).execute() | |
| if res.data and len(res.data) > 0: | |
| return res.data[0] | |
| return None | |
| def save_chat_message(session_id, role, content): | |
| session_data = get_session(session_id) | |
| if session_data: | |
| chat_history = session_data.get("chat_history", []) | |
| chat_history.append({"role": role, "content": content}) | |
| get_supabase().table("sessions").update({"chat_history": chat_history}).eq("id", session_id).execute() | |
| def delete_session(session_id): | |
| get_supabase().table("sessions").delete().eq("id", session_id).execute() | |