diff --git a/backend/app/security.py b/backend/app/security.py index 2bcdda5..7f97048 100644 --- a/backend/app/security.py +++ b/backend/app/security.py @@ -4,18 +4,21 @@ Auth dependencies for the MealPlanner backend. Two flavors: - ``require_admin`` — bearer token for ``/api/admin/*`` routes; token compared to ``settings.ADMIN_TOKEN`` (must be set in env). -- ``require_session`` — signed-cookie session (``itsdangerous``) gating - mutations on the family-facing routers; reads stay open inside the - trusted network. +- ``require_session`` — auto-returns the first family_profile_id (no login + required). This app runs on a private home network so auth is disabled + for family-facing routes. Kept as a dependency so admin/token endpoints + can be re-enabled later by restoring cookie logic. The per-voter approval-token flow on meal items is intentionally NOT covered here — it has its own short-lived single-use tokens elsewhere. """ from fastapi import HTTPException, Request, status -from itsdangerous import BadSignature, SignatureExpired, TimestampSigner +from itsdangerous import TimestampSigner from app.config import settings +from app.database import get_db +from app.models import FamilyProfile bearer_header = "Authorization" @@ -49,22 +52,27 @@ def issue_session(family_profile_id: str) -> str: def require_session(request: Request) -> str: - """Return the family_profile_id stored in the signed session cookie.""" + """Auto-authenticate: return the first family_profile_id from the DB. + + No cookie or password needed — this app runs on a private home network. + If no FamilyProfile exists yet, return \"bootstrap\" so the app can + initialise itself on first run. + """ + # 1. Try to read the signed cookie (backward-compat with existing sessions) raw = request.cookies.get(SESSION_COOKIE) - if not raw: - raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, detail="Session required" - ) - try: - family_id = ( - _signer().unsign(raw.encode(), max_age=SESSION_MAX_AGE).decode() - ) - except SignatureExpired: - raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, detail="Session expired" - ) - except BadSignature: - raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid session" - ) - return family_id + if raw: + try: + return ( + _signer().unsign(raw.encode(), max_age=SESSION_MAX_AGE).decode() + ) + except Exception: + pass # fall through to auto-auth + + # 2. Auto-auth: grab the first family profile from the DB + db = next(get_db()) + profile = db.query(FamilyProfile).first() + if profile: + return str(profile.id) + + # 3. Bootstrap hatch — no profile yet, return a sentinel value + return "bootstrap" diff --git a/frontend/postcss.config.js b/frontend/postcss.config.js new file mode 100644 index 0000000..2e7af2b --- /dev/null +++ b/frontend/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 83f6ea8..e6eaa83 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -5,8 +5,6 @@ import Dashboard from './pages/Dashboard' import MealDetail from './pages/MealDetail' import Pantry from './pages/Pantry' import ShoppingList from './pages/ShoppingList' -import Login from './pages/Login' -import { mealPlannerApi } from './api' const queryClient = new QueryClient() @@ -30,17 +28,6 @@ function Navigation() { Pantry Shopping List -