from fastapi import APIRouter, Depends, HTTPException, Request from fastapi_sso.sso.google import GoogleSSO from app.core.config import settings from app.core.auth import create_access_token from app.db.session import get_db from app.services.user_service import user_service from sqlalchemy.ext.asyncio import AsyncSession from starlette.responses import RedirectResponse router = APIRouter() google_sso = GoogleSSO( client_id=settings.GOOGLE_CLIENT_ID, client_secret=settings.GOOGLE_CLIENT_SECRET, redirect_uri=settings.GOOGLE_REDIRECT_URI, allow_insecure_http=True # Set to False in production ) @router.get("/google/login") async def google_login(): with google_sso: return await google_sso.get_login_redirect() @router.get("/google/callback") async def google_callback(request: Request, db: AsyncSession = Depends(get_db)): with google_sso: try: user_data = await google_sso.verify_and_process(request) except Exception as e: raise HTTPException(status_code=400, detail=f"Google Authentication failed: {str(e)}") if not user_data: raise HTTPException(status_code=400, detail="Failed to get user data from Google") # Check if user exists user = await user_service.get_user_by_email(db, user_data.email) if not user: user = await user_service.create_user( db=db, email=user_data.email, full_name=user_data.display_name or user_data.email, avatar_url=user_data.picture, google_id=user_data.id ) # Record Session from app.models.database import UserSession session_record = UserSession( user_id=user.id, ip_address=request.client.host if request.client else None, user_agent=request.headers.get("user-agent") ) db.add(session_record) await db.commit() # Create access token access_token = create_access_token(data={"sub": user.email}) # Redirect back to frontend with token # In a real app, you might use a more secure way to pass the token import os frontend_url = os.getenv("FRONTEND_URL", "http://localhost:5173") return RedirectResponse(url=f"{frontend_url}/auth/callback?token={access_token}") # Fixing imports and implementing logout properly from app.core.auth import get_user_or_demo from app.models.database import UserSession, User as DBUser from sqlalchemy import select import datetime @router.post("/logout") async def logout_endpoint(db: AsyncSession = Depends(get_db), user: DBUser = Depends(get_user_or_demo)): # Find the latest open session for this user result = await db.execute( select(UserSession) .where(UserSession.user_id == user.id) .where(UserSession.logout_at == None) .order_by(UserSession.login_at.desc()) .limit(1) ) last_session = result.scalar_one_or_none() if last_session: last_session.logout_at = datetime.datetime.utcnow() await db.commit() return {"status": "success", "message": "Logged out successfully"} return {"status": "success", "message": "No active session found"}