feat: handle Garmin MFA and activity retries
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
from fastapi import APIRouter, Form, Request
|
||||
from fastapi import APIRouter, Form, HTTPException, Request
|
||||
from fastapi.responses import HTMLResponse
|
||||
from sqlalchemy import func, select
|
||||
|
||||
from app.auth.admin import require_admin
|
||||
from app.auth.csrf import ensure_csrf_token, validate_csrf
|
||||
from app.db.models import Activity
|
||||
from app.db.repositories import UserRepository
|
||||
from app.db.repositories import ActivityRepository, UserRepository
|
||||
from app.sync.manager import SyncAlreadyRunning
|
||||
from app.web.routes import templates
|
||||
|
||||
@@ -59,6 +59,42 @@ async def manual_sync_all(request: Request, csrf_token: str = Form(...)):
|
||||
)
|
||||
|
||||
|
||||
@router.post("/users/{user_id}/garmin-mfa", response_class=HTMLResponse)
|
||||
async def garmin_mfa(request: Request, user_id: int, csrf_token: str = Form(...), code: str = Form(...)):
|
||||
require_admin(request)
|
||||
validate_csrf(request, csrf_token)
|
||||
stripped = code.strip()
|
||||
if not stripped or len(stripped) > 20:
|
||||
raise HTTPException(status_code=400, detail="Invalid MFA code")
|
||||
try:
|
||||
outcome = await request.app.state.sync_manager.sync_user(user_id, mfa_code=stripped)
|
||||
except SyncAlreadyRunning:
|
||||
return HTMLResponse("Sync already running for this user", status_code=409)
|
||||
return templates.TemplateResponse(
|
||||
request, "fragments/sync_result.html", {"outcomes": [_normalize_outcome(outcome)]}
|
||||
)
|
||||
|
||||
|
||||
@router.post("/activities/{activity_id}/retry", response_class=HTMLResponse)
|
||||
async def retry_activity(request: Request, activity_id: int, csrf_token: str = Form(...)):
|
||||
require_admin(request)
|
||||
validate_csrf(request, csrf_token)
|
||||
with request.app.state.session_factory() as session:
|
||||
activity_repo = ActivityRepository(session)
|
||||
try:
|
||||
activity = activity_repo.reset_retryable_failure(activity_id)
|
||||
except ValueError:
|
||||
return HTMLResponse("Activity is not retryable", status_code=409)
|
||||
user_id = activity.user_id
|
||||
try:
|
||||
outcome = await request.app.state.sync_manager.sync_user(user_id)
|
||||
except SyncAlreadyRunning:
|
||||
return HTMLResponse("Sync already running for this user", status_code=409)
|
||||
return templates.TemplateResponse(
|
||||
request, "fragments/sync_result.html", {"outcomes": [_normalize_outcome(outcome)]}
|
||||
)
|
||||
|
||||
|
||||
@router.get("/system", response_class=HTMLResponse)
|
||||
def system_page(request: Request):
|
||||
require_admin(request)
|
||||
|
||||
Reference in New Issue
Block a user