Initial commit

This commit is contained in:
belviskhoremk
2026-02-22 21:59:37 +00:00
commit 5bd496d355
27 changed files with 4172 additions and 0 deletions

82
app/dependencies.py Normal file
View File

@@ -0,0 +1,82 @@
from fastapi import Depends, HTTPException, status, Header
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from typing import Optional
from app.database import get_supabase
from app.config import settings
import logging
logger = logging.getLogger(__name__)
security = HTTPBearer(auto_error=False)
async def get_current_user(
credentials: Optional[HTTPAuthorizationCredentials] = Depends(security),
):
"""Extract and verify the current user from Supabase JWT"""
if not credentials:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Not authenticated",
)
token = credentials.credentials
supabase = get_supabase()
try:
response = supabase.auth.get_user(token)
if not response or not response.user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid or expired token",
)
return response.user
except Exception as e:
logger.error(f"Auth error: {e}")
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid or expired token",
)
async def get_optional_user(
credentials: Optional[HTTPAuthorizationCredentials] = Depends(security),
):
"""Optional auth - returns None if not authenticated"""
if not credentials:
return None
try:
return await get_current_user(credentials)
except HTTPException:
return None
async def get_user_subscription(user=Depends(get_current_user)):
"""Get user's subscription plan"""
supabase = get_supabase()
try:
result = (
supabase.table("subscriptions")
.select("*")
.eq("user_id", user.id)
.eq("status", "active")
.execute()
)
if result.data:
return result.data[0]
return {"plan": "free", "status": "active", "user_id": user.id}
except Exception:
return {"plan": "free", "status": "active", "user_id": user.id}
async def require_plan(min_plan: str, user=Depends(get_current_user)):
"""Require a minimum plan level"""
plan_order = ["free", "starter", "pro", "enterprise"]
subscription = await get_user_subscription(user)
user_plan = subscription.get("plan", "free")
if plan_order.index(user_plan) < plan_order.index(min_plan):
raise HTTPException(
status_code=status.HTTP_402_PAYMENT_REQUIRED,
detail=f"This feature requires {min_plan} plan or higher",
)
return user