Skip to content

feat: block subscribing when a same-email account is already subscribed#1750

Merged
nevo-david merged 1 commit into
mainfrom
feat/block-duplicate-email-subscription
Jul 23, 2026
Merged

feat: block subscribing when a same-email account is already subscribed#1750
nevo-david merged 1 commit into
mainfrom
feat/block-duplicate-email-subscription

Conversation

@giladresisi

Copy link
Copy Markdown
Collaborator

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 User uniqueness is @@unique([email, providerName]), not on email alone. That means two User rows and two Organizations 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:

  • On subscribe, look for another account with the same email whose organization owns an active subscription (deletedAt: null, the codebase's definition of active — there is no status column).
  • The current user is excluded by id, so renewing/modifying your own plan is never blocked.
  • Only the org owner (role: SUPERADMIN) counts, so being an invited team member in someone else's paid org does not trigger a false block.
  • If such a sibling exists → the subscribe flow is blocked and the user is told to log off and sign in to that other account. Otherwise nothing changes.

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:

  • Sign up with an email whose other account is subscribed → blocked (message shown, no Stripe checkout created).
  • Sign up with an email whose other account is not subscribed → not blocked (checkout proceeds as before).

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 frontend fetch(...).json() can read the field and surface the message.

Checklist:

  • I have read the CONTRIBUTING guide.
  • I have signed the Contributor License Agreement (CLA).
  • I confirm I have not used AI to submit this PR or generate code for it.
  • I checked that there were no similar issues or PRs already open for this.
  • This PR fixes just ONE issue

🤖 Generated with Claude Code

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>
@postiz-contribution postiz-contribution Bot added the contribution:approved Approved contributor label Jul 20, 2026
@postiz-contribution

Copy link
Copy Markdown

Contribution-checker quality warning
Heuristic score: 19/100 (low). This is a non-blocking warning surfaced by the project's quality settings.

Heuristics that flagged:

  • Wall-of-text PR body: 2545 chars (>2500)
  • Excessive inline code references: 14 inline refs (>3)
  • AI watermark phrase: Matched: "Generated with Claude Code"
  • Commit message too long: Longest: 544 chars

If this is a genuine contribution, please add detail to your PR description and tighten the diff scope before reviewers look at it.

@postiz-agent

postiz-agent Bot commented Jul 20, 2026

Copy link
Copy Markdown

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@nevo-david
nevo-david merged commit 40cafba into main Jul 23, 2026
11 checks passed
@nevo-david
nevo-david deleted the feat/block-duplicate-email-subscription branch July 23, 2026 03:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contribution:approved Approved contributor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants