Skip to content

Commit dac2ff0

Browse files
authored
feat: display FGA permission groups with OR logic (supabase#42438)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Update API reference docs to properly render FGA permission groups, showing the OR relationship between permission sets. ## What is the current behavior? Right now, only the first FGA permission group is shown, missing alternative permission sets that also grant access to an endpoint. ## What is the new behavior? Display all FGA permission groups with "or" separator between them. <img width="542" height="165" alt="Screenshot 2026-02-04 at 1 16 23 PM" src="https://github.com/user-attachments/assets/adee529d-e15d-4912-98c4-1c5a8cd4c9d7" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit **Documentation** - Improved the API reference documentation by reorganizing how endpoint permissions are displayed. Permissions are now grouped with clear "or" separators between groups, making it easier to understand the complete set of permission requirements for each API endpoint. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent f237b7b commit dac2ff0

File tree

1 file changed

+33
-24
lines changed

1 file changed

+33
-24
lines changed

apps/docs/features/docs/Reference.sections.tsx

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,5 @@
1-
import { isFeatureEnabled } from 'common'
2-
import { Fragment } from 'react'
3-
import ReactMarkdown from 'react-markdown'
4-
import {
5-
Badge,
6-
TabsContent_Shadcn_,
7-
TabsList_Shadcn_,
8-
TabsTrigger_Shadcn_,
9-
Tabs_Shadcn_,
10-
cn,
11-
} from 'ui'
12-
13-
import { type IApiEndPoint } from './Reference.api.utils'
14-
import { RefInternalLink } from './Reference.navigation.client'
15-
import { ApiOperationBodySchemeSelector } from './Reference.ui.client'
161
import ApiSchema from '~/components/ApiSchema'
17-
import { REFERENCES, clientSdkIds } from '~/content/navigation.references'
2+
import { clientSdkIds, REFERENCES } from '~/content/navigation.references'
183
import {
194
getApiEndpointById,
205
getCliSpec,
@@ -23,7 +8,7 @@ import {
238
getSelfHostedApiEndpointById,
249
getTypeSpec,
2510
} from '~/features/docs/Reference.generated.singleton'
26-
import { MDXRemoteRefs, getRefMarkdown } from '~/features/docs/Reference.mdx'
11+
import { getRefMarkdown, MDXRemoteRefs } from '~/features/docs/Reference.mdx'
2712
import type { MethodTypes } from '~/features/docs/Reference.typeSpec'
2813
import { formatMethodSignature } from '~/features/docs/Reference.typeSpec'
2914
import {
@@ -38,6 +23,21 @@ import {
3823
import type { AbbrevApiReferenceSection } from '~/features/docs/Reference.utils'
3924
import { normalizeMarkdown } from '~/features/docs/Reference.utils'
4025
import { CodeBlock } from '~/features/ui/CodeBlock/CodeBlock'
26+
import { isFeatureEnabled } from 'common'
27+
import { Fragment } from 'react'
28+
import ReactMarkdown from 'react-markdown'
29+
import {
30+
Badge,
31+
cn,
32+
Tabs_Shadcn_,
33+
TabsContent_Shadcn_,
34+
TabsList_Shadcn_,
35+
TabsTrigger_Shadcn_,
36+
} from 'ui'
37+
38+
import { type IApiEndPoint } from './Reference.api.utils'
39+
import { RefInternalLink } from './Reference.navigation.client'
40+
import { ApiOperationBodySchemeSelector } from './Reference.ui.client'
4141

4242
type RefSectionsProps = {
4343
libraryId: string
@@ -286,8 +286,10 @@ async function ApiEndpointSection({ link, section, servicePath }: ApiEndpointSec
286286
: await getApiEndpointById(section.id)
287287
if (!endpointDetails) return null
288288

289-
const endpointFgaPermissions =
290-
endpointDetails.security?.find((sec) => 'fga_permissions' in sec)?.fga_permissions ?? []
289+
const endpointFgaPermissionGroups =
290+
endpointDetails.security
291+
?.filter((sec) => 'fga_permissions' in sec)
292+
.map((sec) => sec.fga_permissions) ?? []
291293
const pathParameters = (endpointDetails.parameters ?? []).filter((param) => param.in === 'path')
292294
const queryParameters = (endpointDetails.parameters ?? []).filter((param) => param.in === 'query')
293295
const bodyParameters =
@@ -360,16 +362,23 @@ async function ApiEndpointSection({ link, section, servicePath }: ApiEndpointSec
360362
</ul>
361363
</section>
362364
)}
363-
{endpointFgaPermissions.length > 0 && (
365+
{endpointFgaPermissionGroups.length > 0 && (
364366
<section>
365367
<h3 className="mb-3 text-base text-foreground">
366368
The fine-grained token must include the following permissions to access this endpoint:
367369
</h3>
368370
<ul>
369-
{endpointFgaPermissions.map((perm) => (
370-
<li key={perm} className="list-['-'] ml-2 pl-2">
371-
<span className="font-mono text-sm font-medium text-foreground">{perm}</span>
372-
</li>
371+
{endpointFgaPermissionGroups.map((group, groupIndex) => (
372+
<Fragment key={groupIndex}>
373+
{groupIndex > 0 && (
374+
<li className="my-2 text-foreground-lighter text-sm italic">or</li>
375+
)}
376+
{group.map((perm, permIndex) => (
377+
<li key={permIndex} className="list-['-'] ml-2 pl-2">
378+
<span className="font-mono text-sm font-medium text-foreground">{perm}</span>
379+
</li>
380+
))}
381+
</Fragment>
373382
))}
374383
</ul>
375384
</section>

0 commit comments

Comments
 (0)