from fastapi import APIRouter, Depends, HTTPException, Request from sqlmodel import Session, select from datetime import datetime from app.core.db import get_session from app.models import GoogleAccount from app.google.auth import build_flow, token_json_from_creds from app.google.client import get_service router = APIRouter() @router.get("/start") def start_oauth(): """Devuelve el auth_url para que el usuario lo abra y autorice.""" flow = build_flow() auth_url, state = flow.authorization_url( access_type="offline", include_granted_scopes="true", prompt="consent", ) return {"auth_url": auth_url, "state": state} @router.get("/callback") def oauth_callback(request: Request, session: Session = Depends(get_session)): """Recibe code/state y guarda token en SQLite.""" code = request.query_params.get("code") state = request.query_params.get("state") if not code: raise HTTPException(status_code=400, detail="Falta 'code' en el callback") flow = build_flow(state=state) try: flow.fetch_token(code=code) except Exception as e: raise HTTPException(status_code=400, detail=f"No se pudo obtener token: {e}") creds = flow.credentials token_json = token_json_from_creds(creds) # Obtenemos el email con OAuth2 userinfo try: oauth2 = get_service("oauth2", "v2", token_json) info = oauth2.userinfo().get().execute() email = info.get("email") if not email: raise ValueError("No se pudo leer email") except Exception as e: raise HTTPException(status_code=400, detail=f"Token ok pero no pude obtener email: {e}") existing = session.exec(select(GoogleAccount).where(GoogleAccount.email == email)).first() now = datetime.utcnow() if existing: existing.token_json = token_json existing.updated_at = now session.add(existing) session.commit() return {"status": "updated", "email": email} else: acc = GoogleAccount(email=email, token_json=token_json, created_at=now, updated_at=now) session.add(acc) session.commit() return {"status": "created", "email": email} @router.get("/accounts") def list_accounts(session: Session = Depends(get_session)): rows = session.exec(select(GoogleAccount)).all() return [{"email": r.email, "created_at": r.created_at, "updated_at": r.updated_at} for r in rows] @router.delete("/accounts/{email}") def delete_account(email: str, session: Session = Depends(get_session)): acc = session.exec(select(GoogleAccount).where(GoogleAccount.email == email)).first() if not acc: raise HTTPException(status_code=404, detail="Cuenta no encontrada") session.delete(acc) session.commit() return {"status": "deleted", "email": email}