fix to strava sync

This commit is contained in:
Davide Scaini
2026-04-10 17:55:24 +02:00
parent eeed3fe3b2
commit f67e7552fd
2 changed files with 68 additions and 0 deletions
+65
View File
@@ -18,6 +18,7 @@ from pathlib import Path
from typing import Any, Optional
from fastapi import Cookie, FastAPI, File, Form, HTTPException, Request, Response, UploadFile
from fastapi.responses import RedirectResponse
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.gzip import GZipMiddleware
from fastapi.responses import JSONResponse
@@ -643,6 +644,70 @@ async def submit_feedback(
return JSONResponse({"ok": True, "id": submission_id})
# ── Strava ────────────────────────────────────────────────────────────────────
_strava_oauth_states: set[str] = set()
@app.get("/api/strava/status")
async def strava_status(bincio_session: Optional[str] = Cookie(default=None)) -> JSONResponse:
user = _require_user(bincio_session)
if not strava_client_id:
return JSONResponse({"configured": False, "connected": False, "last_sync": None})
dd = _get_data_dir() / user.handle
token_path = dd / "strava_token.json"
connected = token_path.exists()
last_sync = None
if connected:
try:
token = json.loads(token_path.read_text())
last_sync = token.get("last_sync_at")
except Exception:
pass
return JSONResponse({"configured": True, "connected": connected, "last_sync": last_sync})
@app.get("/api/strava/auth-url")
async def strava_auth_url(request: Request, bincio_session: Optional[str] = Cookie(default=None)) -> JSONResponse:
_require_user(bincio_session)
if not strava_client_id:
raise HTTPException(400, "Strava client ID not configured on this server")
state = secrets.token_urlsafe(16)
_strava_oauth_states.add(state)
redirect_uri = str(request.url_for("strava_callback"))
from bincio.extract.strava_api import auth_url
return JSONResponse({"url": auth_url(strava_client_id, redirect_uri, state=state)})
@app.get("/api/strava/callback", name="strava_callback")
async def strava_callback(
request: Request,
code: str = "",
error: str = "",
state: str = "",
bincio_session: Optional[str] = Cookie(default=None),
) -> RedirectResponse:
site_origin = str(request.base_url).rstrip("/")
if error or not code:
return RedirectResponse(f"{site_origin}/?strava=error")
if state not in _strava_oauth_states:
return RedirectResponse(f"{site_origin}/?strava=error")
_strava_oauth_states.discard(state)
user = _current_user(bincio_session)
if not user:
return RedirectResponse(f"{site_origin}/?strava=error")
if not strava_client_id or not strava_client_secret:
return RedirectResponse(f"{site_origin}/?strava=error")
dd = _get_data_dir() / user.handle
from bincio.extract.strava_api import StravaError, exchange_code, save_token
try:
token = exchange_code(strava_client_id, strava_client_secret, code)
except StravaError:
return RedirectResponse(f"{site_origin}/?strava=error")
save_token(dd, token)
return RedirectResponse(f"{site_origin}/?strava=connected")
@app.post("/api/strava/sync")
async def serve_strava_sync(bincio_session: Optional[str] = Cookie(default=None)) -> JSONResponse:
user = _require_user(bincio_session)