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:
@@ -95,23 +95,33 @@ def create_oauth_blueprint(app_name: str) -> Blueprint:
|
||||
|
||||
if not code or not state or state != expected_state:
|
||||
current_app.logger.warning("OAuth callback: bad state or missing code")
|
||||
# Set _pnone_at to prevent immediate re-trigger of prompt=none
|
||||
import time as _time
|
||||
qsession["_pnone_at"] = _time.time()
|
||||
return redirect("/")
|
||||
|
||||
expected_redirect = app_url(app_name, "/auth/callback")
|
||||
now = datetime.now(timezone.utc)
|
||||
|
||||
# OAuthCode uses hashed storage — look up by code_hash
|
||||
import hashlib
|
||||
code_hash = hashlib.sha256(code.encode()).hexdigest()
|
||||
|
||||
# OAuthCode lives in db_account — use account session
|
||||
async with get_account_session() as s:
|
||||
async with s.begin():
|
||||
result = await s.execute(
|
||||
select(OAuthCode)
|
||||
.where(OAuthCode.code == code)
|
||||
.where(OAuthCode.code_hash == code_hash)
|
||||
.with_for_update()
|
||||
)
|
||||
oauth_code = result.scalar_one_or_none()
|
||||
|
||||
if not oauth_code:
|
||||
current_app.logger.warning("OAuth callback: code not found")
|
||||
# Set _pnone_at to prevent redirect loop
|
||||
import time as _time
|
||||
qsession["_pnone_at"] = _time.time()
|
||||
return redirect("/")
|
||||
|
||||
if oauth_code.used_at is not None:
|
||||
@@ -132,7 +142,9 @@ def create_oauth_blueprint(app_name: str) -> Blueprint:
|
||||
|
||||
oauth_code.used_at = now
|
||||
user_id = oauth_code.user_id
|
||||
grant_token = oauth_code.grant_token
|
||||
|
||||
# grant_token is passed in the redirect URL (raw, for session storage)
|
||||
grant_token = request.args.get("grant_token")
|
||||
|
||||
# Set local session with grant token for revocation checking
|
||||
qsession[SESSION_USER_KEY] = user_id
|
||||
|
||||
Reference in New Issue
Block a user