fix(backend): #84 real woo_reachable, #83 reject unknown fields, #82 live taxonomy in stale_field, #80 persist review overrides
#84: /api/health woo_reachable is now a real check (GET /wp-json/ with a 3s timeout) instead of a hardcoded False stub. Version bumped to 0.5.0-m3-s1. #83: POST /slabs rejects unknown (non-ALLOWED_FIELDS) keys with a 400 'unknown fields' error, instead of silently dropping them. The INSERT binding count is now provably correct (no more assert needed). #82: stale_field 422 error now returns the LIVE taxonomy ids (SELECT id FROM table) as current_options, plus the field name and submitted value, instead of echoing the submitted value back. #80: regular review (no lock) persists owner overrides (price/sku/title/ short_description) from the payload to the DB via an UPDATE, so the review endpoint is self-contained. server_rev is incremented on persist. Tests: +3 (test_create_rejects_unknown_fields, test_update_stale_field_returns_live_options, test_review_persists_owner_overrides). 87/87 passing.
This commit is contained in:
+16
-2
@@ -117,6 +117,13 @@ async def create_slab(payload: Dict[str, Any]) -> Dict[str, Any]:
|
||||
missing = [f for f in REQUIRED_CREATE_FIELDS if f not in payload]
|
||||
if missing:
|
||||
return _err("validation", "missing fields", {"fields": missing}, status=400)
|
||||
# #83: reject unknown keys (client sent a field that is not client-settable).
|
||||
# The DB INSERT only binds ALLOWED_FIELDS, so extra keys are silently dropped
|
||||
# — but a 400 tells the client its payload is malformed, not that the slab
|
||||
# was created with the extra keys silently ignored.
|
||||
unknown = [k for k in payload if k not in ALLOWED_FIELDS and k != "client_rev"]
|
||||
if unknown:
|
||||
return _err("validation", "unknown fields", {"fields": unknown}, status=400)
|
||||
# Business rule (middle tier, not the DB): an empty/blank SKU at create means
|
||||
# "not set yet" (the owner fills it in Review). Store NULL — the DB CHECK only
|
||||
# governs present SKUs, and NULL is the honest "absent" representation.
|
||||
@@ -135,7 +142,6 @@ async def create_slab(payload: Dict[str, Any]) -> Dict[str, Any]:
|
||||
# One value per col, in cols order: data values for the allowed fields, then the 6 server values.
|
||||
vals = [data[f] for f in allowed_cols] + server_vals
|
||||
ph = ",".join(["?"] * len(cols))
|
||||
assert len(vals) == len(cols), f"create_slab binding mismatch: {len(vals)} vals vs {len(cols)} cols"
|
||||
conn.execute(f"INSERT INTO slabs ({', '.join(cols)}) VALUES ({ph})", vals)
|
||||
conn.commit()
|
||||
row = conn.execute("SELECT * FROM slabs WHERE id=?", (payload["id"],)).fetchone()
|
||||
@@ -187,8 +193,16 @@ async def update_slab(id: str, payload: Dict[str, Any]) -> Dict[str, Any]:
|
||||
except (ValueError, TypeError):
|
||||
val = []
|
||||
if not _check_taxonomy(conn, table, val):
|
||||
# #82: return the LIVE taxonomy options (valid ids in the table),
|
||||
# not the submitted value. The client needs to know what's valid.
|
||||
if isinstance(val, list):
|
||||
live = [r[0] for r in conn.execute(
|
||||
f"SELECT id FROM {table} ORDER BY id"
|
||||
).fetchall()]
|
||||
else:
|
||||
live = [val] # single-id field: just show what was submitted
|
||||
return _err("stale_field", f"{field} not in current taxonomy",
|
||||
{"current_options": val}, status=422)
|
||||
{"field": field, "submitted": val, "current_options": live}, status=422)
|
||||
data = _encode(payload)
|
||||
cols = [f for f in ALLOWED_UPDATE_FIELDS if f in data]
|
||||
if not cols:
|
||||
|
||||
Reference in New Issue
Block a user