Spaces:
Runtime error
Runtime error
File size: 6,622 Bytes
f3997d4 | 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 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from app.database.connection import get_db
from app.schemas.auth import UserCreate, UserLogin, UserResponse, TokenResponse
from app.services.auth_service import AuthService
from app.middleware.auth import get_current_user
from app.database.models import User
from app.utils.validators import validate_email, validate_password
router = APIRouter(prefix="/api", tags=["auth"])
@router.post("/signup", response_model=TokenResponse, status_code=status.HTTP_201_CREATED)
async def signup(user_data: UserCreate, db: Session = Depends(get_db)):
"""
Create a new user account.
Args:
user_data: User registration data
db: Database session
Returns:
Access and refresh tokens with user info
Raises:
HTTPException: If email is invalid or already registered
"""
print(f"[SIGNUP] Received signup request for email: {user_data.email}")
# Validate email
if not validate_email(user_data.email):
print(f"[SIGNUP] Invalid email format: {user_data.email}")
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Invalid email format"
)
# Validate password
is_valid, error_msg = validate_password(user_data.password)
if not is_valid:
print(f"[SIGNUP] Password validation failed: {error_msg}")
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=error_msg
)
try:
# Create user
print(f"[SIGNUP] Creating user...")
user = AuthService.create_user(
db=db,
email=user_data.email,
password=user_data.password,
name=user_data.name
)
print(f"[SIGNUP] User created successfully: {user.id}")
# Generate tokens
tokens = AuthService.generate_tokens(user)
print(f"[SIGNUP] Tokens generated successfully")
return TokenResponse(
access_token=tokens["access_token"],
refresh_token=tokens["refresh_token"],
user=UserResponse.from_orm(user)
)
except ValueError as e:
print(f"[SIGNUP] ValueError: {str(e)}")
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e)
)
except Exception as e:
print(f"[SIGNUP] Unexpected error: {type(e).__name__}: {str(e)}")
import traceback
traceback.print_exc()
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="An error occurred during signup"
)
@router.post("/login", response_model=TokenResponse)
async def login(credentials: UserLogin, db: Session = Depends(get_db)):
"""
Authenticate user and return tokens.
Args:
credentials: User login credentials
db: Database session
Returns:
Access and refresh tokens with user info
Raises:
HTTPException: If credentials are invalid
"""
# Authenticate user
user = AuthService.authenticate_user(
db=db,
email=credentials.email,
password=credentials.password
)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect email or password"
)
# Generate tokens
tokens = AuthService.generate_tokens(user)
return TokenResponse(
access_token=tokens["access_token"],
refresh_token=tokens["refresh_token"],
user=UserResponse.from_orm(user)
)
@router.get("/check-auth", response_model=UserResponse)
async def check_auth(current_user: User = Depends(get_current_user)):
"""
Verify authentication token and return user info.
Args:
current_user: Current authenticated user
Returns:
User information
Raises:
HTTPException: If token is invalid or expired
"""
return UserResponse.from_orm(current_user)
@router.post("/auth/google", response_model=TokenResponse)
async def google_auth(
request: dict,
db: Session = Depends(get_db)
):
"""
Authenticate user with Google OAuth and return JWT tokens.
Args:
request: Dictionary with 'credential' field (Google JWT token)
db: Database session
Returns:
Access and refresh JWT tokens with user info
Raises:
HTTPException: If Google token is invalid
"""
from app.config.settings import settings
print(f"[GOOGLE AUTH] Received Google OAuth request")
try:
credential = request.get("credential")
if not credential:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Google credential is required"
)
print(f"[GOOGLE AUTH] Verifying Google token...")
# Verify Google token and get user info
google_data = await AuthService.verify_google_token(
credential=credential,
client_id=settings.GOOGLE_CLIENT_ID
)
print(f"[GOOGLE AUTH] Token verified for email: {google_data['email']}")
# Create or get user
user = AuthService.create_user_from_google(
db=db,
google_id=google_data["google_id"],
email=google_data["email"],
name=google_data.get("name")
)
print(f"[GOOGLE AUTH] User created/retrieved: {user.id}")
# Generate JWT tokens (same as email/password login)
tokens = AuthService.generate_tokens(user)
print(f"[GOOGLE AUTH] JWT tokens generated successfully")
return TokenResponse(
access_token=tokens["access_token"],
refresh_token=tokens["refresh_token"],
user=UserResponse.from_orm(user)
)
except ValueError as e:
print(f"[GOOGLE AUTH] ValueError: {str(e)}")
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e)
)
except Exception as e:
print(f"[GOOGLE AUTH] Unexpected error: {type(e).__name__}: {str(e)}")
import traceback
traceback.print_exc()
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to authenticate with Google"
)
|