Skip to content

Fix invite user error by using admin client for tmp_users#1427

Merged
riderx merged 1 commit into
mainfrom
riderx/fix-invite-user-error
Jan 12, 2026
Merged

Fix invite user error by using admin client for tmp_users#1427
riderx merged 1 commit into
mainfrom
riderx/fix-invite-user-error

Conversation

@riderx
Copy link
Copy Markdown
Member

@riderx riderx commented Jan 12, 2026

Summary

Fixed the "Failed to invite user" error (400 status) that occurred when inviting users. The issue was that the tmp_users table has an RLS policy blocking all authenticated access, but the invite endpoint was using an authenticated Supabase client to perform SELECT, INSERT, and UPDATE operations on that table.

Solution

Switched to using supabaseAdmin (service role client) for all tmp_users operations. Authorization is already enforced by the validateInvite function which checks user membership and org access, so using the service role client is safe and necessary to bypass the RLS policy.

Test plan

  • Invite a new user to an organization and verify the invitation is created
  • Re-invite a previously cancelled user and verify the invitation is updated instead of creating a new one

Summary by CodeRabbit

  • Chores
    • Improved backend infrastructure for the organization user invitation process with enhanced access control mechanisms for temporary user data operations.

✏️ Tip: You can customize this high-level summary in your review settings.

The tmp_users table has an RLS policy that blocks all access ('Disable for all').
The invite function was using an authenticated client which is subject to RLS,
causing SELECT, INSERT, and UPDATE operations to fail with a 400 error.

Switch to using supabaseAdmin (service role client) for tmp_users operations
since authorization is already validated via validateInvite function.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 12, 2026

📝 Walkthrough

Walkthrough

The change replaces all temporary user table operations in the invite function from authenticated client to admin client, maintaining identical functionality while adjusting access permissions for tmp_users table interactions.

Changes

Cohort / File(s) Summary
Admin client migration for tmp_users operations
supabase/functions/_backend/private/invite_new_user_to_org.ts
Replaced authenticated supabase client with supabaseAdmin client for all tmp_users table operations (insert, update, select). Updated imports and added supabaseAdminClient variable initialization. Operations remain functionally identical with elevated permission level.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 With admin powers now in hand,
Invites go forth across the land,
tmp_users bow to higher might,
Permission shifts feel just right,
One file tweaked, six lines arranged,
Access levels duly changed! 🌟

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers the summary, solution rationale, and test plan. However, the checklist section is entirely missing, which is required by the template. Add the checklist section from the template with appropriate checkboxes marked based on the changes made.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: switching to an admin client for tmp_users operations to fix the invite user error.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 22a5d3e and 5229190.

📒 Files selected for processing (1)
  • supabase/functions/_backend/private/invite_new_user_to_org.ts
🧰 Additional context used
📓 Path-based instructions (7)
supabase/functions/_backend/**/*.{ts,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

supabase/functions/_backend/**/*.{ts,js}: Backend code must be placed in supabase/functions/_backend/ as shared code deployed to Cloudflare Workers (API/Plugin/Files workers), Supabase Edge Functions, and other platforms
Use createHono from utils/hono.ts for all Hono framework application initialization and routing
All database operations must use getPgClient() or getDrizzleClient() from utils/pg.ts for PostgreSQL access during active migration to Cloudflare D1
All Hono endpoint handlers must accept Context<MiddlewareKeyVariables> and use c.get('requestId'), c.get('apikey'), and c.get('auth') for request context
Use structured logging with cloudlog({ requestId: c.get('requestId'), message: '...' }) for all backend logging
Use middlewareAPISecret for internal API endpoints and middlewareKey for external API keys; validate against owner_org in the apikeys table
Check c.get('auth')?.authType to determine authentication type ('apikey' vs 'jwt') in backend endpoints
Use Drizzle ORM query patterns with schema from postgress_schema.ts for all database operations; use aliasV2() for self-joins or multiple table references

Files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
supabase/functions/**/*.{ts,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Backend ESLint must pass before commit; run bun lint:backend for backend files

Files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
**/*.{vue,ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Run bun lint to lint Vue, TypeScript, and JavaScript files; use bun lint:fix to auto-fix issues

Files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use single quotes and no semicolons per @antfu/eslint-config rules

Files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
supabase/functions/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

supabase/functions/**/*.ts: Never use the Supabase admin SDK with service key for user-facing APIs; always use client SDK with user authentication to enforce RLS policies. Admin SDK should only be used for internal operations (triggers, CRON jobs, etc.)
When admin access is unavoidable for a user-facing endpoint, sanitize all user inputs carefully to prevent PostgREST query injection

Files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

Run bun lint or lint/format command before validating any backend or frontend task to ensure consistent formatting

Files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
supabase/functions/_backend/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Place core backend logic in supabase/functions/_backend/ with plugins, private, public, triggers, and utils subdirectories

Files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
🧠 Learnings (10)
📚 Learning: 2026-01-10T04:55:25.264Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T04:55:25.264Z
Learning: Applies to supabase/functions/**/*.ts : Never use the Supabase admin SDK with service key for user-facing APIs; always use client SDK with user authentication to enforce RLS policies. Admin SDK should only be used for internal operations (triggers, CRON jobs, etc.)

Applied to files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
📚 Learning: 2025-12-24T14:11:10.256Z
Learnt from: WcaleNieWolny
Repo: Cap-go/capgo PR: 1300
File: supabase/migrations/20251224103713_2fa_enforcement.sql:409-539
Timestamp: 2025-12-24T14:11:10.256Z
Learning: In supabase/migrations for get_orgs_v6 and get_orgs_v7: The inner functions with user_id parameter (get_orgs_v6(uuid) and get_orgs_v7(uuid)) should NOT be granted to anon/authenticated roles as this allows any user to query other users' organizations; only the no-argument wrapper functions should be public as they perform authentication checks.

Applied to files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
📚 Learning: 2026-01-10T04:55:25.264Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T04:55:25.264Z
Learning: Applies to supabase/functions/_backend/**/*.ts : Place core backend logic in supabase/functions/_backend/ with plugins, private, public, triggers, and utils subdirectories

Applied to files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Use `middlewareAPISecret` for internal API endpoints and `middlewareKey` for external API keys; validate against `owner_org` in the `apikeys` table

Applied to files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Check `c.get('auth')?.authType` to determine authentication type ('apikey' vs 'jwt') in backend endpoints

Applied to files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Use `createHono` from `utils/hono.ts` for all Hono framework application initialization and routing

Applied to files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
📚 Learning: 2025-12-25T11:22:19.594Z
Learnt from: WcaleNieWolny
Repo: Cap-go/capgo PR: 1300
File: supabase/migrations/20251224103713_2fa_enforcement.sql:85-96
Timestamp: 2025-12-25T11:22:19.594Z
Learning: In the 2FA enforcement implementation for supabase/migrations: When an org has enforcing_2fa=true, all users including super_admins must have 2FA enabled before accessing any org functions (including check_org_members_2fa_enabled); this is intentional behavior to ensure consistent security enforcement without exceptions for admins.

Applied to files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Backend code must be placed in `supabase/functions/_backend/` as shared code deployed to Cloudflare Workers (API/Plugin/Files workers), Supabase Edge Functions, and other platforms

Applied to files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
📚 Learning: 2026-01-10T04:55:25.264Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T04:55:25.264Z
Learning: Applies to supabase/functions/**/*.ts : When admin access is unavoidable for a user-facing endpoint, sanitize all user inputs carefully to prevent PostgREST query injection

Applied to files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : All Hono endpoint handlers must accept `Context<MiddlewareKeyVariables>` and use `c.get('requestId')`, `c.get('apikey')`, and `c.get('auth')` for request context

Applied to files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
🧬 Code graph analysis (1)
supabase/functions/_backend/private/invite_new_user_to_org.ts (1)
supabase/functions/_backend/utils/supabase.ts (1)
  • supabaseAdmin (75-84)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Run tests
🔇 Additional comments (3)
supabase/functions/_backend/private/invite_new_user_to_org.ts (3)

10-10: LGTM!

Import correctly adds supabaseAdmin to support the admin client usage for tmp_users operations.


116-161: Admin client operations for tmp_users are correctly implemented.

The SELECT, UPDATE, and INSERT operations on tmp_users properly use the admin client with validated inputs:

  • email validated via z.email()
  • first_name/last_name validated with restrictive nameRegex
  • invite_type validated as enum
  • org_id used after org access is verified via authenticated client in validateInvite

The conditional logic correctly handles both re-inviting cancelled users (with 3-hour cooldown) and creating new invitations.


113-114: The admin client usage is appropriate and necessary.

The implementation correctly enforces authorization via the authenticated client first (validating user access to the org), then scopes the admin client operations exclusively to tmp_users. All inputs are thoroughly validated with Zod schema before being passed to the admin client, preventing PostgREST query injection.

The RLS policy on tmp_users is intentionally set to "Disable for all" by design requirement (documented in supabase/migrations/20250613034031_tmp_users_table.sql). This deliberate choice means the admin client is the only viable approach for managing temporary user invitations. The implementation correctly follows security guidelines by sanitizing all user inputs before admin operations.

Likely an incorrect or invalid review comment.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
supabase/functions/_backend/private/invite_new_user_to_org.ts (1)

19-26: Strengthen org_id validation to UUID format.

Since org_id is now used with the admin client (bypassing RLS), validating it as a proper UUID rather than just a non-empty string provides stronger protection against potential injection attacks.

🔒 Proposed fix
 const inviteUserSchema = z.object({
   email: z.email(),
-  org_id: z.string().check(z.minLength(1)),
+  org_id: z.uuid(),
   invite_type: z.enum(['read', 'upload', 'write', 'admin', 'super_admin']),
   captcha_token: z.string().check(z.minLength(1)),
   first_name: z.string().check(z.minLength(1), z.regex(nameRegex, 'First name contains invalid characters')),
   last_name: z.string().check(z.minLength(1), z.regex(nameRegex, 'Last name contains invalid characters')),
 })

Based on coding guidelines: "When admin access is unavoidable for a user-facing endpoint, sanitize all user inputs carefully to prevent PostgREST query injection."

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 22a5d3e and 5229190.

📒 Files selected for processing (1)
  • supabase/functions/_backend/private/invite_new_user_to_org.ts
🧰 Additional context used
📓 Path-based instructions (7)
supabase/functions/_backend/**/*.{ts,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

supabase/functions/_backend/**/*.{ts,js}: Backend code must be placed in supabase/functions/_backend/ as shared code deployed to Cloudflare Workers (API/Plugin/Files workers), Supabase Edge Functions, and other platforms
Use createHono from utils/hono.ts for all Hono framework application initialization and routing
All database operations must use getPgClient() or getDrizzleClient() from utils/pg.ts for PostgreSQL access during active migration to Cloudflare D1
All Hono endpoint handlers must accept Context<MiddlewareKeyVariables> and use c.get('requestId'), c.get('apikey'), and c.get('auth') for request context
Use structured logging with cloudlog({ requestId: c.get('requestId'), message: '...' }) for all backend logging
Use middlewareAPISecret for internal API endpoints and middlewareKey for external API keys; validate against owner_org in the apikeys table
Check c.get('auth')?.authType to determine authentication type ('apikey' vs 'jwt') in backend endpoints
Use Drizzle ORM query patterns with schema from postgress_schema.ts for all database operations; use aliasV2() for self-joins or multiple table references

Files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
supabase/functions/**/*.{ts,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Backend ESLint must pass before commit; run bun lint:backend for backend files

Files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
**/*.{vue,ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Run bun lint to lint Vue, TypeScript, and JavaScript files; use bun lint:fix to auto-fix issues

Files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use single quotes and no semicolons per @antfu/eslint-config rules

Files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
supabase/functions/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

supabase/functions/**/*.ts: Never use the Supabase admin SDK with service key for user-facing APIs; always use client SDK with user authentication to enforce RLS policies. Admin SDK should only be used for internal operations (triggers, CRON jobs, etc.)
When admin access is unavoidable for a user-facing endpoint, sanitize all user inputs carefully to prevent PostgREST query injection

Files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

Run bun lint or lint/format command before validating any backend or frontend task to ensure consistent formatting

Files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
supabase/functions/_backend/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Place core backend logic in supabase/functions/_backend/ with plugins, private, public, triggers, and utils subdirectories

Files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
🧠 Learnings (10)
📚 Learning: 2026-01-10T04:55:25.264Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T04:55:25.264Z
Learning: Applies to supabase/functions/**/*.ts : Never use the Supabase admin SDK with service key for user-facing APIs; always use client SDK with user authentication to enforce RLS policies. Admin SDK should only be used for internal operations (triggers, CRON jobs, etc.)

Applied to files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
📚 Learning: 2025-12-24T14:11:10.256Z
Learnt from: WcaleNieWolny
Repo: Cap-go/capgo PR: 1300
File: supabase/migrations/20251224103713_2fa_enforcement.sql:409-539
Timestamp: 2025-12-24T14:11:10.256Z
Learning: In supabase/migrations for get_orgs_v6 and get_orgs_v7: The inner functions with user_id parameter (get_orgs_v6(uuid) and get_orgs_v7(uuid)) should NOT be granted to anon/authenticated roles as this allows any user to query other users' organizations; only the no-argument wrapper functions should be public as they perform authentication checks.

Applied to files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
📚 Learning: 2026-01-10T04:55:25.264Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T04:55:25.264Z
Learning: Applies to supabase/functions/_backend/**/*.ts : Place core backend logic in supabase/functions/_backend/ with plugins, private, public, triggers, and utils subdirectories

Applied to files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Use `middlewareAPISecret` for internal API endpoints and `middlewareKey` for external API keys; validate against `owner_org` in the `apikeys` table

Applied to files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Check `c.get('auth')?.authType` to determine authentication type ('apikey' vs 'jwt') in backend endpoints

Applied to files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Use `createHono` from `utils/hono.ts` for all Hono framework application initialization and routing

Applied to files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
📚 Learning: 2025-12-25T11:22:19.594Z
Learnt from: WcaleNieWolny
Repo: Cap-go/capgo PR: 1300
File: supabase/migrations/20251224103713_2fa_enforcement.sql:85-96
Timestamp: 2025-12-25T11:22:19.594Z
Learning: In the 2FA enforcement implementation for supabase/migrations: When an org has enforcing_2fa=true, all users including super_admins must have 2FA enabled before accessing any org functions (including check_org_members_2fa_enabled); this is intentional behavior to ensure consistent security enforcement without exceptions for admins.

Applied to files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Backend code must be placed in `supabase/functions/_backend/` as shared code deployed to Cloudflare Workers (API/Plugin/Files workers), Supabase Edge Functions, and other platforms

Applied to files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
📚 Learning: 2026-01-10T04:55:25.264Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T04:55:25.264Z
Learning: Applies to supabase/functions/**/*.ts : When admin access is unavoidable for a user-facing endpoint, sanitize all user inputs carefully to prevent PostgREST query injection

Applied to files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : All Hono endpoint handlers must accept `Context<MiddlewareKeyVariables>` and use `c.get('requestId')`, `c.get('apikey')`, and `c.get('auth')` for request context

Applied to files:

  • supabase/functions/_backend/private/invite_new_user_to_org.ts
🧬 Code graph analysis (1)
supabase/functions/_backend/private/invite_new_user_to_org.ts (1)
supabase/functions/_backend/utils/supabase.ts (1)
  • supabaseAdmin (75-84)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Run tests
🔇 Additional comments (3)
supabase/functions/_backend/private/invite_new_user_to_org.ts (3)

10-10: LGTM!

Import correctly adds supabaseAdmin to support the admin client usage for tmp_users operations.


116-161: Admin client operations for tmp_users are correctly implemented.

The SELECT, UPDATE, and INSERT operations on tmp_users properly use the admin client with validated inputs:

  • email validated via z.email()
  • first_name/last_name validated with restrictive nameRegex
  • invite_type validated as enum
  • org_id used after org access is verified via authenticated client in validateInvite

The conditional logic correctly handles both re-inviting cancelled users (with 3-hour cooldown) and creating new invitations.


113-114: The admin client usage is appropriate and necessary.

The implementation correctly enforces authorization via the authenticated client first (validating user access to the org), then scopes the admin client operations exclusively to tmp_users. All inputs are thoroughly validated with Zod schema before being passed to the admin client, preventing PostgREST query injection.

The RLS policy on tmp_users is intentionally set to "Disable for all" by design requirement (documented in supabase/migrations/20250613034031_tmp_users_table.sql). This deliberate choice means the admin client is the only viable approach for managing temporary user invitations. The implementation correctly follows security guidelines by sanitizing all user inputs before admin operations.

Likely an incorrect or invalid review comment.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5229190391

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +113 to 115
// Use admin client for tmp_users operations since RLS blocks all access on that table
const supabaseAdminClient = supabaseAdmin(c)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Enforce org admin rights before using service role

This handler now uses supabaseAdmin for all tmp_users writes, which bypasses RLS, but there is still no explicit check that the caller has admin+ rights for the org (the earlier validateInvite only validates access via orgs select). That means any authenticated member with read access to an org can invite new users or re‑activate invitations by calling this endpoint directly, even if they should not have invite permissions. The public members API explicitly checks for admin rights; this private route should enforce the same before performing service‑role inserts/updates.

Useful? React with 👍 / 👎.

@sonarqubecloud
Copy link
Copy Markdown

@riderx riderx merged commit 1760d6b into main Jan 12, 2026
11 checks passed
@riderx riderx deleted the riderx/fix-invite-user-error branch January 12, 2026 11:42
@coderabbitai coderabbitai Bot mentioned this pull request Jan 20, 2026
11 tasks
@coderabbitai coderabbitai Bot mentioned this pull request Jan 30, 2026
10 tasks
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