buildersai / app /routes /auth.py
Kushal
Initial deployment: FastAPI backend with Docker
f3997d4
Raw
History Blame Contribute Delete
6.62 kB
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"
)