Skip to content

feat: show "invitation expired" message for late team-invite acceptances#1642

Open
giladresisi wants to merge 1 commit into
mainfrom
feat/invite-expired-message
Open

feat: show "invitation expired" message for late team-invite acceptances#1642
giladresisi wants to merge 1 commit into
mainfrom
feat/invite-expired-message

Conversation

@giladresisi

Copy link
Copy Markdown
Collaborator

Problem

Team invitation links expire 1 hour after they're sent. The email even says so — but in practice many users skim past that wording and click the link later. When they do, they're silently not added to the inviting org: no error, no explanation. They just land in their own (often free) workspace / on the pricing page and assume the invite or the product is broken.

What this does

Surfaces a clear "invitation expired" toast whenever a late acceptance fails to join the inviting org, so the user understands what happened and can ask for a fresh invite — across every way an invite can be accepted.

How

The challenge is that an invite can be accepted through several different flows, which land the user in the app via different mechanisms:

  • Already logged in (direct link) → the proxy/middleware redirects to the landing page with ?invitation=expired.
  • Register / login / OAuth login → these flows consume the invite token from a single org cookie. A new AuthService.consumeOrgInviteCookie helper handles it in one place: if the token was expired/invalid it sets a short-lived, non-httpOnly invitation cookie (a cookie rather than a redirect param, because the brand-new-account flow detours through an email-activation step before the user ever reaches the app), and it always clears the org cookie so a consumed token is single-use.
  • Frontend → a small InvitationMessage component (mounted once in the app layout) shows the toast from either the query param or the cookie, exactly once, then clears both.

Single-use / no cross-user leak

Because the org cookie is cleared as soon as any auth event consumes it, the expired signal only ever affects the actual late invitee. A subsequent login on the same browser by a different user (e.g. the inviting org owner) no longer re-triggers the toast.

Testing

Verified locally (temporarily lowering the invite expiry to 1 minute):

  • register (brand-new account) — expired invite shows the toast
  • activation flow (LOCAL + email provider) — toast survives the register → email → activate round-trip and shows after landing
  • login (existing, logged-out invitee) — expired invite shows the toast
  • cookie reuse — after the first auth event the org cookie is cleared, so logging in as a different user afterwards (e.g. the inviting org owner) does not show the toast

Notes

  • No DB/schema changes; the 1-hour expiry and email copy are unchanged.
  • Behavior is additive — valid invites and the existing redirects are untouched.

🤖 Generated with Claude Code

When a user accepted a team invitation after the 1-hour link expiry, they
were silently not added to the inviting org and dropped on the pricing page
with no explanation. Surface an "invitation expired" toast across every
acceptance path.

- proxy: already-logged-in invitees redirect to the landing page with
  ?invitation=expired instead of the (query-stripping) "/" hop
- register/login/oauth: a single-use `org` invite cookie is handled by
  AuthService.consumeOrgInviteCookie, which flags expiry via a short-lived
  `invitation` cookie (so it survives the email-activation detour) and then
  always clears the `org` cookie so a consumed/expired token can't leak to
  the next user who signs in on the same browser
- frontend: InvitationMessage shows the toast from the query param or the
  cookie, once, then clears both

Tested locally (temporarily lowering the invite expiry to 1 minute):
- register (brand-new account) — expired invite shows the toast
- activation flow (LOCAL + email provider) — toast survives the
  register -> email -> activate round-trip and shows after landing
- login (existing, logged-out invitee) — expired invite shows the toast
- cookie reuse — after the first auth event the `org` cookie is cleared, so
  logging in as a different user afterwards (e.g. the inviting org owner)
  no longer shows the toast

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@postiz-contribution postiz-contribution Bot added the contribution:approved Approved contributor label Jun 26, 2026
@postiz-contribution

Copy link
Copy Markdown

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

Heuristics that flagged:

  • Wall-of-text PR body: 2648 chars (>2500)
  • Excessive emojis in body: 5 emojis (>2)
  • Excessive inline code references: 8 inline refs (>3)
  • PR doesn't use the repo's PR template: 5 required checkbox items missing (max 1, match ≥80%)
  • Body adds too many extra headers beyond the template: 6 extra headers (>1)
  • AI watermark phrase: Matched: "Generated with Claude Code"
  • Commit message too long: Longest: 1484 chars
  • Excessive added comments: 18 added comment lines (ratio 0.18)

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 Jun 26, 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.

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.

1 participant