Fix cross-DB queries: move page_configs to cart, fix OAuth code_hash lookup

page_configs table lives in db_cart but blog was querying it directly,
causing UndefinedTableError. Move all PageConfig read/write endpoints to
cart service and have blog proxy via fetch_data/call_action.

Also fix OAuth callback to use code_hash lookup (codes are now stored
hashed) and pass grant_token in redirect URL to prevent auth loops.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-26 17:43:21 +00:00
parent 98aee1f656
commit dd52417241
11 changed files with 228 additions and 180 deletions

View File

@@ -7,25 +7,9 @@ from __future__ import annotations
from quart import Blueprint, g, jsonify, request
from sqlalchemy import select
from shared.infrastructure.data_client import DATA_HEADER
from shared.infrastructure.data_client import DATA_HEADER, fetch_data
from shared.contracts.dtos import dto_to_dict
from shared.services.registry import services
from shared.models.page_config import PageConfig
def _page_config_dict(pc: PageConfig) -> dict:
"""Serialize PageConfig to a JSON-safe dict."""
return {
"id": pc.id,
"container_type": pc.container_type,
"container_id": pc.container_id,
"features": pc.features or {},
"sumup_merchant_code": pc.sumup_merchant_code,
"sumup_api_key": pc.sumup_api_key,
"sumup_checkout_prefix": pc.sumup_checkout_prefix,
}
def register() -> Blueprint:
@@ -90,55 +74,30 @@ def register() -> Blueprint:
_handlers["search-posts"] = _search_posts
# --- page-config ---
# --- page-config (proxy to cart, where page_configs table lives) ---
async def _page_config():
"""Return a single PageConfig by container_type + container_id."""
ct = request.args.get("container_type", "page")
cid = request.args.get("container_id", type=int)
if cid is None:
return None
pc = (await g.s.execute(
select(PageConfig).where(
PageConfig.container_type == ct,
PageConfig.container_id == cid,
)
)).scalar_one_or_none()
if not pc:
return None
return _page_config_dict(pc)
return await fetch_data("cart", "page-config",
params={"container_type": request.args.get("container_type", "page"),
"container_id": request.args.get("container_id", "")},
required=False)
_handlers["page-config"] = _page_config
# --- page-config-by-id ---
# --- page-config-by-id (proxy to cart) ---
async def _page_config_by_id():
"""Return a single PageConfig by its primary key."""
pc_id = request.args.get("id", type=int)
if pc_id is None:
return None
pc = await g.s.get(PageConfig, pc_id)
if not pc:
return None
return _page_config_dict(pc)
return await fetch_data("cart", "page-config-by-id",
params={"id": request.args.get("id", "")},
required=False)
_handlers["page-config-by-id"] = _page_config_by_id
# --- page-configs-batch ---
# --- page-configs-batch (proxy to cart) ---
async def _page_configs_batch():
"""Return PageConfigs for multiple container_ids (comma-separated)."""
ct = request.args.get("container_type", "page")
ids_raw = request.args.get("ids", "")
if not ids_raw:
return []
ids = [int(x.strip()) for x in ids_raw.split(",") if x.strip()]
if not ids:
return []
result = await g.s.execute(
select(PageConfig).where(
PageConfig.container_type == ct,
PageConfig.container_id.in_(ids),
)
)
return [_page_config_dict(pc) for pc in result.scalars().all()]
return await fetch_data("cart", "page-configs-batch",
params={"container_type": request.args.get("container_type", "page"),
"ids": request.args.get("ids", "")},
required=False) or []
_handlers["page-configs-batch"] = _page_configs_batch