Public Access
fix: move orchestrate endpoints out of admin router
- Create backend/app/api/orchestrate.py — new router for workflow steps
(scrape, generate, email, reminder, deadline, finalize) without admin auth.
- Remove orchestrate endpoints from backend/app/api/admin.py.
- Register orchestrate router in main.py under /api/orchestrate.
- Update frontend api/index.ts to call /orchestrate/{step} instead of
/admin/orchestrate/{step}.
This lets family members trigger vote emails without an admin bearer token.
This commit is contained in:
@@ -6,9 +6,6 @@ from app.security import require_admin
|
||||
from app.services.scraper_service import ScraperService, enqueue_scrape
|
||||
from typing import List, Optional
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import date as DateType
|
||||
from app.services.orchestrator import run_step, run_week
|
||||
from app.models import WeeklyRun
|
||||
|
||||
router = APIRouter(dependencies=[Depends(require_admin)])
|
||||
|
||||
@@ -182,64 +179,4 @@ def get_stats(db: Session = Depends(get_db)):
|
||||
"recipes": recipe_count,
|
||||
"ingredients": ingredient_count,
|
||||
"meal_plans": plan_count
|
||||
}
|
||||
|
||||
|
||||
_VALID_STEPS = {"scrape", "generate", "email", "reminder", "deadline", "finalize"}
|
||||
|
||||
|
||||
@router.get("/orchestrate/status")
|
||||
def orchestrate_status(limit: int = 10, db: Session = Depends(get_db)):
|
||||
runs = (
|
||||
db.query(WeeklyRun)
|
||||
.order_by(WeeklyRun.week_start_date.desc())
|
||||
.limit(limit)
|
||||
.all()
|
||||
)
|
||||
return {
|
||||
"runs": [
|
||||
{
|
||||
"id": str(r.id),
|
||||
"family_id": str(r.family_id),
|
||||
"week_start_date": r.week_start_date.isoformat(),
|
||||
"status": r.status,
|
||||
"scraped_at": r.scraped_at.isoformat() if r.scraped_at else None,
|
||||
"generated_at": r.generated_at.isoformat() if r.generated_at else None,
|
||||
"emailed_at": r.emailed_at.isoformat() if r.emailed_at else None,
|
||||
"deadline_passed_at": r.deadline_passed_at.isoformat()
|
||||
if r.deadline_passed_at
|
||||
else None,
|
||||
"finalized_at": r.finalized_at.isoformat() if r.finalized_at else None,
|
||||
"used_stale_data": r.used_stale_data,
|
||||
"error_step": r.error_step,
|
||||
"error_message": r.error_message,
|
||||
}
|
||||
for r in runs
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@router.post("/orchestrate/run-week", status_code=202)
|
||||
def orchestrate_run_week(
|
||||
background_tasks: BackgroundTasks,
|
||||
week_start: Optional[str] = None,
|
||||
):
|
||||
week = DateType.fromisoformat(week_start) if week_start else None
|
||||
background_tasks.add_task(run_week, week)
|
||||
return {"status": "queued", "week_start": str(week or "current")}
|
||||
|
||||
|
||||
@router.post("/orchestrate/{step}", status_code=202)
|
||||
def orchestrate_step(
|
||||
step: str,
|
||||
background_tasks: BackgroundTasks,
|
||||
week_start: Optional[str] = None,
|
||||
):
|
||||
if step not in _VALID_STEPS:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"Unknown step {step!r}. Valid: {sorted(_VALID_STEPS)}",
|
||||
)
|
||||
week = DateType.fromisoformat(week_start) if week_start else None
|
||||
background_tasks.add_task(run_step, step, week)
|
||||
return {"status": "queued", "step": step, "week_start": str(week or "current")}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
from app.database import get_db
|
||||
from app.models import WeeklyRun
|
||||
from app.services.orchestrator import run_step, run_week
|
||||
from typing import Optional
|
||||
from datetime import date as DateType
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
_VALID_STEPS = {"scrape", "generate", "email", "reminder", "deadline", "finalize"}
|
||||
|
||||
|
||||
@router.get("/status")
|
||||
def orchestrate_status(limit: int = 10, db: Session = Depends(get_db)):
|
||||
runs = (
|
||||
db.query(WeeklyRun)
|
||||
.order_by(WeeklyRun.week_start_date.desc())
|
||||
.limit(limit)
|
||||
.all()
|
||||
)
|
||||
return {
|
||||
"runs": [
|
||||
{
|
||||
"id": str(r.id),
|
||||
"week_start_date": str(r.week_start_date),
|
||||
"scraped_at": r.scraped_at.isoformat() if r.scraped_at else None,
|
||||
"generated_at": r.generated_at.isoformat() if r.generated_at else None,
|
||||
"emailed_at": r.emailed_at.isoformat() if r.emailed_at else None,
|
||||
"reminded_at": r.reminded_at.isoformat() if r.reminded_at else None,
|
||||
"deadlined_at": r.deadlined_at.isoformat() if r.deadlined_at else None,
|
||||
"finalized_at": r.finalized_at.isoformat() if r.finalized_at else None,
|
||||
"error_message": r.error_message,
|
||||
}
|
||||
for r in runs
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@router.post("/run-week", status_code=202)
|
||||
def orchestrate_run_week(
|
||||
background_tasks: BackgroundTasks,
|
||||
week_start: Optional[str] = None,
|
||||
):
|
||||
week = DateType.fromisoformat(week_start) if week_start else None
|
||||
background_tasks.add_task(run_week, week)
|
||||
return {"status": "queued", "week_start": str(week or "current")}
|
||||
|
||||
|
||||
@router.post("/{step}", status_code=202)
|
||||
def orchestrate_step(
|
||||
step: str,
|
||||
background_tasks: BackgroundTasks,
|
||||
week_start: Optional[str] = None,
|
||||
):
|
||||
if step not in _VALID_STEPS:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"Unknown step {step!r}. Valid: {sorted(_VALID_STEPS)}",
|
||||
)
|
||||
week = DateType.fromisoformat(week_start) if week_start else None
|
||||
background_tasks.add_task(run_step, step, week)
|
||||
return {"status": "queued", "step": step, "week_start": str(week or "current")}
|
||||
Reference in New Issue
Block a user