Skip to content

Add secure team invitation links#4401

Open
shmlkv wants to merge 2 commits into
umami-software:devfrom
shmlkv:feat/team-invite-registration
Open

Add secure team invitation links#4401
shmlkv wants to merge 2 commits into
umami-software:devfrom
shmlkv:feat/team-invite-registration

Conversation

@shmlkv

@shmlkv shmlkv commented Jul 20, 2026

Copy link
Copy Markdown

Summary

  • Add expiring, one-time invitation links for team member and view-only roles.
  • Let existing users accept an invitation and let new users create a local account and join the team in one flow.
  • Add invitation management to team settings, including active/used/expired/revoked states and revocation.
  • Preserve disabled password authentication in cloud mode or when DISABLE_LOGIN is configured.
  • Prevent duplicate memberships and make invitation redemption transactional and race-safe.

Security

  • Store only a SHA-512 digest of each invitation token.
  • Put the raw token in the URL fragment and remove it from browser history before inspection.
  • Return private no-store responses for invitation and authentication endpoints.
  • Rate-limit public inspection and registration endpoints when Redis is enabled.
  • Revalidate the issuer, team, role, expiry, revocation, and membership inside the redemption transaction.

Screenshot

Team invitation management

Testing

  • pnpm test — 28 test files, 165 tests passed.
  • pnpm exec tsc --noEmit
  • pnpm build-app
  • Biome check for all changed TypeScript, TSX, and JSON files.
  • Applied all migrations to a fresh PostgreSQL 15 database and verified the invite indexes.

View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.

@vercel

vercel Bot commented Jul 20, 2026

Copy link
Copy Markdown

@shmlkv is attempting to deploy a commit to the Umami Software Team on Vercel.

A member of the Team first needs to authorize it.

@greptile-apps

greptile-apps Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds secure team invitation links. The main changes are:

  • New team_invite schema, migration, indexes, and Prisma queries.
  • Invitation creation, inspection, registration, acceptance, and revocation endpoints.
  • Invite management UI in team settings and a public invite landing page.
  • Shared no-store auth responses and password-auth disable checks.

Confidence Score: 4/5

The invite feature has contained issues that need fixes before merging.

  • Existing duplicate memberships can migrate to the wrong team role.
  • The login-and-accept flow can store stale team membership state.
  • Disabled password-auth deployments can show invite forms that only return unauthorized responses.

prisma/migrations/22_add_team_invite/migration.sql, src/app/invite/InvitePage.tsx

Security Review

The invite redemption path hashes tokens, revalidates issuer/team/role state, and consumes invites transactionally. One migration path can still change team permissions when duplicate memberships already exist.

Important Files Changed

Filename Overview
prisma/migrations/22_add_team_invite/migration.sql Adds the invite table and indexes, but duplicate membership cleanup can preserve stale roles.
src/lib/team-invite.ts Adds invite token creation, hashing, issuance, validation, and transactional redemption.
src/queries/prisma/teamInvite.ts Adds the Prisma invite repository with row locking, inspection, revocation, and consume helpers.
src/app/invite/InvitePage.tsx Adds the public invite page, with stale joined-team state and disabled-password-auth UI issues.
src/app/api/auth/login/route.ts Moves login token creation into a shared auth response helper and adds no-store/password-auth checks.
src/app/api/teams/invites/register/route.ts Adds public invite registration with rate limiting, password-auth checks, and transactional redemption.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
  participant U as Invite recipient
  participant UI as Invite page
  participant Inspect as Inspect API
  participant Auth as Auth API
  participant Accept as Accept API
  participant DB as Postgres
  U->>UI: Open invite link
  UI->>Inspect: Inspect token
  Inspect->>DB: Read invite metadata
  Inspect-->>UI: Team and role
  U->>UI: Sign in or register
  UI->>Auth: Login or register
  Auth-->>UI: Auth response
  UI->>Accept: Redeem invite
  Accept->>DB: Create membership and consume invite
  Accept-->>UI: Joined team
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
  participant U as Invite recipient
  participant UI as Invite page
  participant Inspect as Inspect API
  participant Auth as Auth API
  participant Accept as Accept API
  participant DB as Postgres
  U->>UI: Open invite link
  UI->>Inspect: Inspect token
  Inspect->>DB: Read invite metadata
  Inspect-->>UI: Team and role
  U->>UI: Sign in or register
  UI->>Auth: Login or register
  Auth-->>UI: Auth response
  UI->>Accept: Redeem invite
  Accept->>DB: Create membership and consume invite
  Accept-->>UI: Joined team
Loading

Reviews (1): Last reviewed commit: "feat: add team invitation links" | Re-trigger Greptile

Comment thread prisma/migrations/22_add_team_invite/migration.sql
Comment thread src/app/invite/InvitePage.tsx
Comment thread src/app/invite/InvitePage.tsx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant