Step 2 follow-up: use any usable Mealie token for the boot backfill
System MEALIE_API_TOKEN is 401 (legacy 'Cauldron' token from Mealie mint long ago, since rotated/expired). The backfill tries it first; on 401 falls back to any stored per-user token via the new db.first_usable_mealie_token helper. Cobb's user is admin in Mealie and his token returns the full group catalog, so the backfill works without minting a fresh system token.
This commit is contained in:
parent
f74a627ac7
commit
5e62da2013
2 changed files with 36 additions and 4 deletions
|
|
@ -375,6 +375,23 @@ class DB:
|
||||||
|
|
||||||
# --- mealie token ops ---------------------------------------------------
|
# --- mealie token ops ---------------------------------------------------
|
||||||
|
|
||||||
|
def first_usable_mealie_token(self) -> dict | None:
|
||||||
|
"""Return the freshest (last_validated DESC) per-user encrypted Mealie
|
||||||
|
token row. Used at boot as a fallback when the system MEALIE_API_TOKEN
|
||||||
|
env is dead — group admins can list foods, so any user's token works
|
||||||
|
for the backfill scan."""
|
||||||
|
with self.conn() as c, c.cursor() as cur:
|
||||||
|
cur.execute(
|
||||||
|
"""SELECT authentik_sub, encrypted_token
|
||||||
|
FROM cauldron_user_mealie_tokens
|
||||||
|
WHERE last_failure_at IS NULL OR
|
||||||
|
last_validated > COALESCE(last_failure_at, '1970-01-01')
|
||||||
|
ORDER BY last_validated DESC, created_at DESC
|
||||||
|
LIMIT 1"""
|
||||||
|
)
|
||||||
|
row = cur.fetchone()
|
||||||
|
return dict(row) if row else None
|
||||||
|
|
||||||
def get_user_mealie_token_blob(self, sub: str) -> bytes | None:
|
def get_user_mealie_token_blob(self, sub: str) -> bytes | None:
|
||||||
with self.conn() as c, c.cursor() as cur:
|
with self.conn() as c, c.cursor() as cur:
|
||||||
cur.execute(
|
cur.execute(
|
||||||
|
|
|
||||||
|
|
@ -71,12 +71,27 @@ def create_app() -> Flask:
|
||||||
|
|
||||||
# One-time backfill: re-key the legacy cauldron_foods (USDA + curated)
|
# One-time backfill: re-key the legacy cauldron_foods (USDA + curated)
|
||||||
# densities into cauldron_food_metadata, keyed by Mealie food.id. Runs
|
# densities into cauldron_food_metadata, keyed by Mealie food.id. Runs
|
||||||
# only when the new metadata table is empty. After this lands, the
|
# only when the new metadata table is empty. The system MEALIE_API_TOKEN
|
||||||
# legacy parallel-name catalog is no longer authoritative — Step 4
|
# may be expired (Cobb's "Cauldron" token was minted long ago); fall
|
||||||
# cleanup can drop cauldron_foods entirely.
|
# back to any stored per-user token since household admins can list
|
||||||
|
# all foods anyway.
|
||||||
|
def _resolve_backfill_mealie() -> "Mealie":
|
||||||
|
try:
|
||||||
|
system_mealie.who_am_i()
|
||||||
|
return system_mealie
|
||||||
|
except Exception:
|
||||||
|
stash = db.first_usable_mealie_token()
|
||||||
|
if not stash:
|
||||||
|
raise RuntimeError("no usable Mealie token (system + user both unavailable)")
|
||||||
|
return Mealie(
|
||||||
|
base_url=cfg.mealie_api_url,
|
||||||
|
api_token=crypto.decrypt(stash["encrypted_token"]),
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if foods.metadata_count(db) == 0:
|
if foods.metadata_count(db) == 0:
|
||||||
stats = foods.backfill_seed_from_legacy(db, system_mealie)
|
mealie_for_backfill = _resolve_backfill_mealie()
|
||||||
|
stats = foods.backfill_seed_from_legacy(db, mealie_for_backfill)
|
||||||
app.logger.info(
|
app.logger.info(
|
||||||
"cauldron_food_metadata backfill: matched=%d missed=%d total_mealie=%d",
|
"cauldron_food_metadata backfill: matched=%d missed=%d total_mealie=%d",
|
||||||
stats.get("matched", 0),
|
stats.get("matched", 0),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue