codenexus / routers /auth.py
farhan1221's picture
Upload 26 files
91990f9 verified
Raw
History Blame Contribute Delete
3.93 kB
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))