Fix #1125: link logged-in donors to their Stripe Customer (not 'anonymous user') - #1174
Fix #1125: link logged-in donors to their Stripe Customer (not 'anonymous user')#1174rdhyee wants to merge 4 commits into
Conversation
…ous) Pay.__init__ used token-presence as a proxy for "anonymous", but logged-in donors also submit a card token, so they were sent down make_account()'s anonymous branch -> Customer description='anonymous user', Account.user=None. Pass user=transaction.user (None for true anonymous), matching the other make_account(user=...) call sites. Verified the bug reproduced on live txns 16674 (2026-06-18) and 15493 (2026-04-16). Co-authored-by: Claude (rbotyee+Claude) <noreply@anthropic.com> Co-authored-by: Codex (rbotyee+Codex) <noreply@openai.com>
Codex-flagged regression from the make_account(user=...) change: an anonymous POST to a logged-in user's no-campaign transaction would mutate the owner's Stripe account. Reject anonymous requests on user-owned transactions. Co-authored-by: Claude (rbotyee+Claude) <noreply@anthropic.com> Co-authored-by: Codex (rbotyee+Codex) <noreply@openai.com>
Guard now rejects BOTH anonymous and authenticated-different-user attempts to pay a no-campaign transaction owned by another user (Codex round 2). Adds FundViewOwnershipTest covering both cases (asserts charge() is not called). NOTE: test authored from frontend/tests.py patterns but NOT executed in this environment (no Django test DB/Stripe here) -- run before merge. Co-authored-by: Claude (rbotyee+Claude) <noreply@anthropic.com> Co-authored-by: Codex (rbotyee+Codex) <noreply@openai.com>
INSTALLED_APPS uses 'regluit.frontend'/'regluit.payment'; the patch target must be regluit.frontend.views.PaymentManager to intercept the loaded view. Verified against existing frontend/tests.py + settings/common.py conventions. Co-authored-by: Claude (rbotyee+Claude) <noreply@anthropic.com> Co-authored-by: Codex (rbotyee+Codex) <noreply@openai.com>
Codex collaboration → converged (rbotyee+Claude × rbotyee+Codex)3 review rounds, each caught something real:
Status: guard logic Codex-LGTM'd; tests corrected per repo convention but not yet executed (no Django test env here). Will run |
✅ Tests PASS on real Django 4.2 (test.unglue.it)Ran on the freshly-rebuilt test.unglue.it (Django 4.2.21, py3.12, prod-snapshot DB) — the regression test the Codex loop produced now executes green: Test DB built + migrated cleanly; both ownership-guard cases confirmed (anonymous + authenticated-mismatch rejected before |
Fixes #1125.
The one-line fix
In
payment/stripelib.py,Pay.__init__used token-presence as a proxy for "anonymous user." But a logged-in donor entering card details also produces a token, so they were routed throughmake_account()'s anonymous branch → StripeCustomer description='anonymous user'andAccount.user=None(orphaned, no saved-card reuse).Fix: pass
user=transaction.userintomake_account(it'sNonefor a truly anonymous donor, and the user for a logged-in one). This makes the donation path consistent with the othermake_account(user=...)call sites already inFundView(e.g. thetransaction.user.id != request.user.idbranch).Behavior note (for review)
make_accountwithuserset runs the existingif user and user.profile.account:path (deactivate old account → save new →recharge_failed_transactions()). That path is already exercised for logged-in users elsewhere, so this isn't new behavior — it just extends it to the campaign/THANKS donation path. Worth a reviewer eye on therecharge_failed_transactions()side-effect for repeat donors.Verification
Scope
Minimal targeted fix. The broader Stripe modernization (13-yr-old API version, missing
name/receipt_email/metadata) is tracked separately in #1142.Provenance (deliberate disclosure): rbotyee+Claude diagnosis + fix; rbotyee+Codex review (in progress → LGTM); curated by @rdhyee, not yet human/test-verified.
🤖 Generated with Claude Code