proto(woo): per-browser Woo creds via X-Woo-* request headers

Prototype routing so 2–3 owners can share one store URL with different WP
application passwords. Device creds live in localStorage; server uses
request override → Settings fallback and never writes overrides into the
Settings row. Inference stays on shared Settings.

See PROTOTYPE.md for UAT with two browsers and known LAN forge risk.
This commit is contained in:
grokbot_ty
2026-09-26 12:26:21 -07:00
parent fc40c66c44
commit 2f6335ec26
8 changed files with 419 additions and 31 deletions
+12 -11
View File
@@ -213,22 +213,23 @@ from .woo import (
WooCredentialsMissing,
WooError,
WooForbiddenError,
client_for_request,
settings_woo_creds,
)
def _woo_credentials() -> tuple[str, str | None, str | None]:
conn = get_connection()
base = os.environ.get("WOO_BASE_URL", "")
user_row = conn.execute("SELECT value FROM settings WHERE key='woo_wp_username'").fetchone()
pass_row = conn.execute("SELECT value_enc FROM settings WHERE key='woo_app_password'").fetchone()
return base, (user_row[0] if user_row else None), (pass_row[0] if pass_row else None)
"""Shop-default Woo creds (Settings). Used by health probe only."""
return settings_woo_creds(get_connection())
@app.post("/api/v1/settings/test-woo")
async def test_woo() -> dict[str, Any]:
base, username, enc_password = _woo_credentials()
async def test_woo(request: Request) -> dict[str, Any]:
"""Probe Woo + sync taxonomy. Optional X-Woo-Username / X-Woo-App-Password
override shop-default Settings for this request only (never persisted).
"""
try:
client = WooClient.from_settings(base, username, enc_password)
client = client_for_request(get_connection(), request.headers)
except WooCredentialsMissing as e:
return {
"ok": False,
@@ -260,10 +261,10 @@ async def get_taxonomy() -> dict[str, Any]:
@app.post("/api/v1/admin/taxonomy/sync")
async def post_taxonomy_sync() -> dict[str, Any]:
base, username, enc_password = _woo_credentials()
async def post_taxonomy_sync(request: Request) -> dict[str, Any]:
"""Refresh taxonomy cache. Honors X-Woo-* override headers for this request."""
try:
client = WooClient.from_settings(base, username, enc_password)
client = client_for_request(get_connection(), request.headers)
except WooCredentialsMissing as e:
return JSONResponse(status_code=502, content=_error("woo_unavailable", str(e)))
try: