Fix TeamSnap callback stalls

This commit is contained in:
Codex
2026-04-24 09:28:58 -05:00
parent 0c61540cf7
commit 2574dc52c5
3 changed files with 122 additions and 6 deletions

View File

@@ -2,6 +2,7 @@ from __future__ import annotations
import secrets
import time
from urllib.parse import urlencode
from fastapi import APIRouter, Depends, HTTPException, Query, Request, Response, status
from fastapi.responses import JSONResponse, RedirectResponse
@@ -42,6 +43,10 @@ def normalize_return_to(return_to: str | None) -> str:
return return_to
def build_signin_error_redirect_url(message: str) -> str:
return f"/signin?{urlencode({'error': message})}"
@router.get("/teamsnap/start")
def teamsnap_start(return_to: str | None = Query(default="/")) -> Response:
if not settings.teamsnap_client_id:
@@ -63,14 +68,31 @@ def teamsnap_start(return_to: str | None = Query(default="/")) -> Response:
@router.get("/teamsnap/callback")
async def teamsnap_callback(
request: Request,
code: str = Query(...),
code: str | None = Query(default=None),
error: str | None = Query(default=None),
db: Session = Depends(get_db),
) -> Response:
if error:
redirect = RedirectResponse(
url=build_signin_error_redirect_url(f"TeamSnap sign-in failed: {error}"),
status_code=status.HTTP_303_SEE_OTHER,
)
set_no_store(redirect)
redirect.delete_cookie(settings.auth_return_cookie_name)
return redirect
if not code:
redirect = RedirectResponse(
url=build_signin_error_redirect_url("TeamSnap sign-in did not return an authorization code."),
status_code=status.HTTP_303_SEE_OTHER,
)
set_no_store(redirect)
redirect.delete_cookie(settings.auth_return_cookie_name)
return redirect
token_payload = await exchange_code_for_token(code)
session = UserSession(session_token=create_session_token(), provider="teamsnap")
update_session_tokens(session, token_payload)
if session.access_token:
session.external_user_id = await fetch_teamsnap_user_id(session.access_token)
db.add(session)
db.commit()
redirect_target = normalize_return_to(request.cookies.get(settings.auth_return_cookie_name))
@@ -113,12 +135,21 @@ async def teamsnap_token(
if not session.access_token:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Missing TeamSnap access token")
session_updated = False
if not session.external_user_id:
session.external_user_id = await fetch_teamsnap_user_id(session.access_token)
session_updated = session.external_user_id is not None
expires_soon = session.token_expires_at is None or session.token_expires_at.timestamp() <= (time.time() + 60)
if expires_soon and session.refresh_token:
token_payload = await refresh_access_token(session.refresh_token)
update_session_tokens(session, token_payload)
if not session.external_user_id and session.access_token:
session.external_user_id = await fetch_teamsnap_user_id(session.access_token)
session_updated = True
if session_updated or expires_soon:
db.add(session)
db.commit()
db.refresh(session)