Skip to content

feat: get_org_members apikey support#1311

Merged
riderx merged 3 commits intomainfrom
get_org_members_apikey_support
Dec 29, 2025
Merged

feat: get_org_members apikey support#1311
riderx merged 3 commits intomainfrom
get_org_members_apikey_support

Conversation

@WcaleNieWolny
Copy link
Copy Markdown
Contributor

@WcaleNieWolny WcaleNieWolny commented Dec 28, 2025

Motivation

I want to be able to implement organization members command in the CLI. For that, I need get_org_members to support API keys. I have forgotten to include this in #1300

Business impact

None on its own. The entire feature of 2FA enforcement has a business impact.

Summary by CodeRabbit

  • New Features

    • Organization members endpoint now supports API key authentication in addition to JWT tokens, enabling more flexible integration options for accessing member data.
  • Security

    • Strengthened access controls and rights validation for member retrieval, with additional checks and logging to prevent unauthorized access.

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


Note

Adds API key support and tightens authorization around public.get_org_members.

  • Introduces a SECURITY DEFINER wrapper public.get_org_members(guild_id) that uses public.get_identity (supports API key and JWT) instead of auth.uid
  • Performs rights check via public.check_min_rights, logs denials with public.pg_log, then delegates to inner public.get_org_members(user_id, guild_id)
  • Revokes anon and authenticated execute privileges on the inner function to prevent direct access
  • Implemented as a migration in supabase/migrations/20251228160000_get_org_members_apikey_support.sql

Written by Cursor Bugbot for commit f3895b8. This will update automatically on new commits. Configure here.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Dec 28, 2025

📝 Walkthrough

Walkthrough

Updates the get_org_members migration to add API key support by using get_identity(...), enforce authorization with check_min_rights, log denials via pg_log, raise NO_RIGHTS on failure, and revoke direct access to the inner function from anon and authenticated roles.

Changes

Cohort / File(s) Summary
Database migration (get_org_members wrapper)
supabase/migrations/20251228160000_get_org_members_apikey_support.sql
Adds a SECURITY DEFINER public.get_org_members(guild_id uuid) wrapper that calls get_identity('{read,upload,write,all}'::public.key_mode[]), checks rights with public.check_min_rights, logs denials via public.pg_log, raises EXCEPTION 'NO_RIGHTS' on insufficient rights, returns results from inner get_org_members(v_user_id, guild_id), and revokes inner function access from anon/authenticated.

Sequence Diagram

sequenceDiagram
    actor Client as Client (JWT / API Key)
    participant Wrapper as public.get_org_members(guild_id)
    participant Identity as public.get_identity(...)
    participant Auth as public.check_min_rights(...)
    participant Inner as public.get_org_members(v_user_id, guild_id)
    participant Log as public.pg_log()
    participant DB as Organization Members

    Client->>Wrapper: CALL get_org_members(guild_id)
    Wrapper->>Identity: get_identity('{read,upload,write,all}')
    Identity-->>Wrapper: v_user_id
    Wrapper->>Auth: check_min_rights(v_user_id, guild_id, 'read')
    alt sufficient rights
        Auth-->>Wrapper: ok
        Wrapper->>Inner: SELECT * FROM get_org_members(v_user_id, guild_id)
        Inner->>DB: query members
        DB-->>Inner: members rows
        Inner-->>Wrapper: result set
        Wrapper-->>Client: return members
    else insufficient rights
        Auth-->>Wrapper: denied
        Wrapper->>Log: pg_log(denial...)
        Log-->>Wrapper: logged
        Wrapper-->>Client: RAISE EXCEPTION 'NO_RIGHTS'
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 Keys and tokens in a jittery hop,
I peek and fetch who’s at the top,
I check the rights, I stamp the log,
No sneaky pass across the bog,
Hooray—members fetched, secure as a crop!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description is incomplete; it provides motivation and business impact but is missing the required template sections: Summary (expanded), Test plan, Screenshots, and Checklist. Complete the PR description by adding all required template sections, particularly the Test plan (critical for database migrations) and the Checklist items.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding API key support to the get_org_members function.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch get_org_members_apikey_support

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7995d70 and 2acf876.

📒 Files selected for processing (1)
  • supabase/migrations/20251228160000_get_org_members_apikey_support.sql
🧰 Additional context used
📓 Path-based instructions (3)
supabase/migrations/**/*.sql

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

Database migrations must be created with supabase migration new <feature_slug> and never modify previously committed migrations

Files:

  • supabase/migrations/20251228160000_get_org_members_apikey_support.sql
**/{migrations,tests,__tests__}/**/*.{sql,ts,js}

📄 CodeRabbit inference engine (AGENTS.md)

Always cover database changes with Postgres-level tests and complement them with end-to-end tests for affected user flows

Files:

  • supabase/migrations/20251228160000_get_org_members_apikey_support.sql
supabase/migrations/*.sql

📄 CodeRabbit inference engine (AGENTS.md)

supabase/migrations/*.sql: When creating schema changes, use supabase migration new <feature_slug> to create a single migration file and keep editing that file until the feature ships; never edit previously committed migrations
A migration that introduces a new table may include seed inserts for that table, treating seeding as part of the current feature and not modifying previously committed migrations
Do not create new cron jobs; instead update the process_all_cron_tasks function in a new migration file to add your job if needed

Files:

  • supabase/migrations/20251228160000_get_org_members_apikey_support.sql
🧠 Learnings (5)
📓 Common learnings
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.
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
📚 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/migrations/20251228160000_get_org_members_apikey_support.sql
📚 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/migrations/20251228160000_get_org_members_apikey_support.sql
📚 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/migrations/20251228160000_get_org_members_apikey_support.sql
📚 Learning: 2025-12-25T11:22:13.039Z
Learnt from: WcaleNieWolny
Repo: Cap-go/capgo PR: 1300
File: supabase/migrations/20251224103713_2fa_enforcement.sql:85-96
Timestamp: 2025-12-25T11:22:13.039Z
Learning: In SQL migrations under the repository (e.g., supabase/migrations), enforce that 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. Do not grant admin exceptions to 2FA requirements. This ensures consistent security enforcement across all org-related operations; implement this rule within relevant migrations and associated stored procedures/tests.

Applied to files:

  • supabase/migrations/20251228160000_get_org_members_apikey_support.sql
⏰ 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 (2)
supabase/migrations/20251228160000_get_org_members_apikey_support.sql (2)

5-28: LGTM! Well-implemented authorization wrapper.

The function correctly:

  • Uses get_identity() for dual JWT/API key authentication support
  • Enforces authorization via check_min_rights before delegating to the inner function
  • Logs denial events for audit purposes
  • Uses SECURITY DEFINER with empty search_path for secure execution

This follows the same pattern established in PR #1300 for other org-related functions.


30-33: Correctly addresses the authorization bypass vulnerability.

The REVOKE statements properly close the security gap by removing direct access to the inner function from anon and authenticated roles. This ensures users must go through the wrapper function which enforces proper authorization checks.

Based on learnings from PR #1300, inner functions with user_id parameters should never be granted to public roles.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 SQLFluff (3.5.0)
supabase/migrations/20251228160000_get_org_members_apikey_support.sql

User Error: No dialect was specified. You must configure a dialect or specify one on the command line using --dialect after the command. Available dialects:
ansi, athena, bigquery, clickhouse, databricks, db2, doris, duckdb, exasol, flink, greenplum, hive, impala, mariadb, materialize, mysql, oracle, postgres, redshift, snowflake, soql, sparksql, sqlite, starrocks, teradata, trino, tsql, vertica


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: 1

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 949e24c and 7995d70.

📒 Files selected for processing (1)
  • supabase/migrations/20251228160000_get_org_members_apikey_support.sql
🧰 Additional context used
📓 Path-based instructions (3)
supabase/migrations/**/*.sql

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

Database migrations must be created with supabase migration new <feature_slug> and never modify previously committed migrations

Files:

  • supabase/migrations/20251228160000_get_org_members_apikey_support.sql
**/{migrations,tests,__tests__}/**/*.{sql,ts,js}

📄 CodeRabbit inference engine (AGENTS.md)

Always cover database changes with Postgres-level tests and complement them with end-to-end tests for affected user flows

Files:

  • supabase/migrations/20251228160000_get_org_members_apikey_support.sql
supabase/migrations/*.sql

📄 CodeRabbit inference engine (AGENTS.md)

supabase/migrations/*.sql: When creating schema changes, use supabase migration new <feature_slug> to create a single migration file and keep editing that file until the feature ships; never edit previously committed migrations
A migration that introduces a new table may include seed inserts for that table, treating seeding as part of the current feature and not modifying previously committed migrations
Do not create new cron jobs; instead update the process_all_cron_tasks function in a new migration file to add your job if needed

Files:

  • supabase/migrations/20251228160000_get_org_members_apikey_support.sql
🧠 Learnings (5)
📓 Common learnings
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.
📚 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/migrations/20251228160000_get_org_members_apikey_support.sql
📚 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/migrations/20251228160000_get_org_members_apikey_support.sql
📚 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/migrations/20251228160000_get_org_members_apikey_support.sql
📚 Learning: 2025-12-25T11:22:13.039Z
Learnt from: WcaleNieWolny
Repo: Cap-go/capgo PR: 1300
File: supabase/migrations/20251224103713_2fa_enforcement.sql:85-96
Timestamp: 2025-12-25T11:22:13.039Z
Learning: In SQL migrations under the repository (e.g., supabase/migrations), enforce that 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. Do not grant admin exceptions to 2FA requirements. This ensures consistent security enforcement across all org-related operations; implement this rule within relevant migrations and associated stored procedures/tests.

Applied to files:

  • supabase/migrations/20251228160000_get_org_members_apikey_support.sql
⏰ 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 (2)
supabase/migrations/20251228160000_get_org_members_apikey_support.sql (2)

1-4: Clear documentation of the migration purpose.

The comments effectively explain the motivation for the change and the authentication enhancement.


5-14: Good security configuration.

Using SECURITY DEFINER with search_path = '' follows PostgreSQL security best practices, preventing schema injection attacks while allowing controlled access to underlying tables.

@riderx riderx merged commit a9f7693 into main Dec 29, 2025
4 of 5 checks passed
@riderx riderx deleted the get_org_members_apikey_support branch December 29, 2025 13:24
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

This PR is being reviewed by Cursor Bugbot

Details

You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

v_user_id uuid;
BEGIN
-- Get user ID supporting both JWT and API key authentication
v_user_id := public.get_identity('{read,upload,write,all}'::public.key_mode[]);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

API key organization restriction bypassed in authorization check

The function uses get_identity() instead of get_identity_org_allowed(), which means it doesn't respect the limited_to_orgs restriction on API keys. When an API key is configured to only access specific organizations, this check is bypassed. A user with an API key restricted to Organization A could access member data of Organization B if they're a member of both. Other organization-related functions like invite_user_to_org and rescind_invitation correctly use get_identity_org_allowed() to enforce this restriction.

Fix in Cursor Fix in Web

@sonarqubecloud
Copy link
Copy Markdown

Dalanir pushed a commit that referenced this pull request Jan 12, 2026
* feat: get_org_members apikey support

* fix: coderabbit

---------

Co-authored-by: Martin DONADIEU <martindonadieu@gmail.com>
@coderabbitai coderabbitai bot mentioned this pull request Feb 24, 2026
6 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.

2 participants