File size: 3,930 Bytes
91990f9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
from fastapi import APIRouter, HTTPException, Response, Request
from pydantic import BaseModel, EmailStr
from config.database import get_supabase, get_supabase_admin
from config.settings import get_settings

router = APIRouter(prefix="/api/auth", tags=["auth"])
settings = get_settings()

class RegisterRequest(BaseModel):
    email: EmailStr
    password: str
    display_name: str = ""

class LoginRequest(BaseModel):
    email: EmailStr
    password: str

@router.post("/register")
async def register(data: RegisterRequest):
    supabase = get_supabase()
    try:
        response = supabase.auth.sign_up({
            "email": data.email,
            "password": data.password,
            "options": {
                "data": {
                    "full_name": data.display_name or data.email.split("@")[0]
                }
            }
        })
        if response.user is None:
            raise HTTPException(status_code=400, detail="Registration failed")
        
        # Sync to public users table
        admin_db = get_supabase_admin()
        admin_db.table("users").insert({
            "id": response.user.id,
            "email": data.email,
            "display_name": data.display_name or data.email.split("@")[0],
            "role": "free"
        }).execute()

        return {"message": "Registration successful. Please check your email to verify your account."}
    except Exception as e:
        error_msg = str(e)
        if "23505" in error_msg or "users_pkey" in error_msg:
            raise HTTPException(status_code=400, detail="An account with this email already exists.")
        
        # Hide raw database dictionary strings if they slip through
        if error_msg.startswith("{") and "'code'" in error_msg:
            import ast
            try:
                err_dict = ast.literal_eval(error_msg)
                if isinstance(err_dict, dict) and "message" in err_dict:
                    # Still, we might not want to expose raw DB messages, but it's better than the dict
                    raise HTTPException(status_code=400, detail=err_dict["message"])
            except (ValueError, SyntaxError):
                pass
            raise HTTPException(status_code=400, detail="An error occurred during registration.")

        raise HTTPException(status_code=400, detail=error_msg)

@router.post("/login")
async def login(data: LoginRequest, response: Response):
    supabase = get_supabase()
    try:
        auth_response = supabase.auth.sign_in_with_password({
            "email": data.email,
            "password": data.password
        })
        if auth_response.user is None:
            raise HTTPException(status_code=401, detail="Invalid email or password")

        response.set_cookie(
            key="access_token",
            value=auth_response.session.access_token,
            httponly=True,
            secure=True,
            samesite="lax",
            max_age=604800
        )
        return {
            "message": "Login successful",
            "user": {
                "id": str(auth_response.user.id),
                "email": auth_response.user.email,
                "display_name": auth_response.user.user_metadata.get("full_name", "")
            }
        }
    except Exception as e:
        raise HTTPException(status_code=401, detail="Invalid email or password")

@router.post("/logout")
async def logout(response: Response):
    response.delete_cookie("access_token")
    return {"message": "Logged out successfully"}

@router.post("/forgot-password")
async def forgot_password(email: EmailStr):
    supabase = get_supabase()
    try:
        supabase.auth.reset_password_email(
            email,
            options={"redirect_to": f"{settings.frontend_url}/auth/reset-password"}
        )
        return {"message": "Password reset email sent"}
    except Exception as e:
        raise HTTPException(status_code=400, detail=str(e))