Skip to content

feat: implement group join via invite code API (#111)#138

Merged
SudiptaPaul-31 merged 1 commit into
Lumina-eX:mainfrom
patopatrish:feat/111-group-invite-code-api
Apr 26, 2026
Merged

feat: implement group join via invite code API (#111)#138
SudiptaPaul-31 merged 1 commit into
Lumina-eX:mainfrom
patopatrish:feat/111-group-invite-code-api

Conversation

@patopatrish
Copy link
Copy Markdown
Contributor

Summary

Implements the full invite code flow for joining groups, closing #111.

  • POST /api/groups/:id/invite — generates a UUID-based invite code for a group, with optional time-based (expires_in) and usage-based (max_uses) expiry
  • POST /api/groups/join — validates an invite code and adds the authenticated user to the group's membership
  • Migration 011 enhances the invites table with usage tracking and adds an atomic PostgreSQL RPC for incrementing use counts without race conditions

What changed

New files

File Purpose
lib/groups/invite.ts Shared utility — code generation, expiry calculation, validation logic, atomic use_count increment
app/api/groups/[id]/invite/route.ts POST /api/groups/:id/invite — generate invite code
app/api/groups/join/route.ts POST /api/groups/join — join group via invite code
scripts/011_enhance_invites_for_group_join.sql DB migration — adds max_uses, use_count, RLS policies, and increment_invite_use_count SQL function

Modified

  • scripts/MIGRATIONS_README.md — documents migration 011 and psql apply command

API reference

Generate invite code

POST /api/groups/:id/invite
Authorization: session cookie (authenticated user, must be group creator or member)

Body (all optional):
{
  "expires_in": 86400,   // seconds until expiry (omit = no time limit)
  "max_uses": 10         // usage cap (omit = unlimited)
}

201 Created
{
  "success": true,
  "invite": {
    "code": "550e8400-e29b-41d4-a716-446655440000",
    "group_id": "room_...",
    "created_at": "2026-04-25T...",
    "expires_at": "2026-04-26T...",
    "max_uses": 10
  }
}

Join via invite code

POST /api/groups/join
Authorization: session cookie (authenticated user)

Body:
{ "code": "550e8400-e29b-41d4-a716-446655440000" }

200 OK
{
  "success": true,
  "group": { "id": "room_...", "name": "..." },
  "membership": { "user_id": "...", "group_id": "...", "joined_at": "..." }
}

Error responses:
400 — missing/invalid code
401 — unauthenticated
403 — not a group member (invite generation only)
404 — code not found / group not found
410 — code expired (time or usage limit reached)
500 — server error

DB migration

Apply after existing migrations:

psql "$DATABASE_URL" -f scripts/011_enhance_invites_for_group_join.sql

Changes to public.invites:

  • Adds max_uses INTEGER (nullable, unlimited when null)
  • Adds use_count INTEGER NOT NULL DEFAULT 0
  • Adds RLS policy: authenticated users can read invites by code (required for join validation)
  • Adds RLS policy: authenticated users can update invites (required for use_count increment)
  • Creates increment_invite_use_count(invite_code text) as SECURITY DEFINER for atomic updates
  • Adds indexes on room_id and created_by

Acceptance criteria checklist

  • Generate a unique invite code for each group
  • Validate invite code before allowing a user to join
  • Support optional time-based expiration (expires_in)
  • Support optional usage-based expiration (max_uses)
  • Codes cannot be reused after expiration (time or usage limit)
  • Invite codes stored securely in DB with metadata (group ID, createdAt, expiresAt, max_uses, use_count)
  • Clear error messages for invalid/expired codes (400, 404, 410)
  • Successful validation adds user to group and updates membership records
  • UUID format for invite codes
  • Middleware-style validation extracted to lib/groups/invite.ts
  • Proper logging for join attempts (both success and failure)

Adds POST /api/groups/:id/invite to generate UUID-based invite codes
with optional time-based (expires_in) and usage-based (max_uses) expiry,
and POST /api/groups/join to validate and consume a code, adding the
user to room_members. Invite use_count is incremented atomically via a
PostgreSQL RPC function to avoid race conditions.

Includes migration 011 which adds max_uses/use_count columns to the
invites table, required RLS policies for authenticated read/update, and
the increment_invite_use_count SQL function.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@drips-wave
Copy link
Copy Markdown

drips-wave Bot commented Apr 25, 2026

@patopatrish Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@SudiptaPaul-31 SudiptaPaul-31 merged commit 3c6501d into Lumina-eX:main Apr 26, 2026
1 check passed
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.

2 participants