feat: block subscribing when a same-email account is already subscribed#1750
Merged
Conversation
A person can create two accounts with the same email (LOCAL + OAuth) because User uniqueness is @@unique([email, providerName]). Guard the subscribe path: if another account with the same email owns an org with an active subscription (deletedAt: null), block the subscribe flow and tell them to sign in to that account instead. Excludes the current user by id, so renewing your own plan is unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Contribution-checker quality warning Heuristics that flagged:
If this is a genuine contribution, please add detail to your PR description and tighten the diff scope before reviewers look at it. |
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What kind of change does this PR introduce?
Feature — a guard on the subscribe path.
Why was this change needed?
Postiz lets a person create two separate accounts with the same primary email — one via LOCAL (email + password) and one via Google OAuth — because
Useruniqueness is@@unique([email, providerName]), not onemailalone. That means twoUserrows and twoOrganizations can exist for one email, and both could start paid subscriptions.We intentionally do not touch signup — people must still be able to create the second account. The only new behavior is at the moment they try to start a paid subscription:
deletedAt: null, the codebase's definition of active — there is nostatuscolumn).id, so renewing/modifying your own plan is never blocked.role: SUPERADMIN) counts, so being an invited team member in someone else's paid org does not trigger a false block.Follows the layering rule (Controller → Service → Repository). No schema change, no migration — read-only guard. New
t()keys were added and translated via lingo.dev.Tested locally both ways:
Other information:
Both subscribe entry points are guarded —
/billing/subscribe(plans page, shown via a dialog) and/billing/embedded(onboarding full-page checkout, shown inline in a bordered box). The endpoints return{ blocked: true }rather than throwing, so the existing frontendfetch(...).json()can read the field and surface the message.Checklist:
🤖 Generated with Claude Code