Spaces:
Running
Running
| import os | |
| from fastapi import FastAPI, Header, HTTPException | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from supabase import create_client, Client | |
| from jose import jwt, JWTError | |
| from dotenv import load_dotenv | |
| # Load environment variables from .env file for local development | |
| load_dotenv() | |
| # --- Configuration --- | |
| # These will be set as "Secrets" in your Hugging Face Space settings | |
| SUPABASE_URL = os.getenv("SUPABASE_URL") | |
| SUPABASE_SERVICE_KEY = os.getenv("SUPABASE_SERVICE_ROLE_KEY") | |
| JWT_SECRET_KEY = os.getenv("JWT_SECRET_KEY") | |
| ALGORITHM = "HS256" | |
| # This should be the URL of your deployed frontend app (e.g., Vercel) | |
| # --- Initialization --- | |
| app = FastAPI() | |
| # Initialize Supabase client with the service role key for admin access | |
| try: | |
| supabase: Client = create_client(SUPABASE_URL, SUPABASE_SERVICE_KEY) | |
| except Exception as e: | |
| print(f"Error initializing Supabase client: {e}") | |
| supabase = None | |
| # Configure CORS (Cross-Origin Resource Sharing) | |
| # This allows your frontend to make requests to this backend | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_credentials=False, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # --- API Endpoint --- | |
| async def get_itinerary_data(authorization: str = Header(...)): | |
| """ | |
| Verifies the user's custom JWT and fetches their itinerary from Supabase. | |
| """ | |
| if not supabase: | |
| raise HTTPException(status_code=500, detail="Database connection not configured.") | |
| try: | |
| # 1. Extract token from "Bearer <token>" header | |
| token_type, token = authorization.split() | |
| if token_type.lower() != "bearer": | |
| raise HTTPException(status_code=401, detail="Invalid token type") | |
| # 2. Verify and decode the JWT | |
| payload = jwt.decode(token, JWT_SECRET_KEY, algorithms=[ALGORITHM]) | |
| # 3. Extract user ID (adjust 'id' to match the key in your JWT payload) | |
| user_id = payload.get("id") | |
| if user_id is None: | |
| raise HTTPException(status_code=401, detail="User ID not found in token payload") | |
| # 4. Query Supabase for the itinerary data | |
| # Using the admin client bypasses RLS, which is what we want here | |
| response = supabase.table("itineraries").select("itinerary_data").eq("user_id", user_id).single().execute() | |
| # Check for errors from Supabase (e.g., no rows found) | |
| if not response.data: | |
| raise HTTPException(status_code=404, detail="Itinerary not found for this user") | |
| # 5. Return the data | |
| return response.data | |
| except JWTError: | |
| raise HTTPException(status_code=401, detail="Could not validate credentials") | |
| except HTTPException as e: | |
| # Re-raise HTTPExceptions to preserve status code and detail | |
| raise e | |
| except Exception as e: | |
| # Catch any other unexpected errors | |
| print(f"An unexpected error occurred: {e}") | |
| raise HTTPException(status_code=500, detail="Internal server error") |