Skip to content

Commit 8c8110a

Browse files
authored
chore: disable role impersonation for edge functions (supabase#36599)
* chore: disable role impersonation for edge functions * allow service role and anon
1 parent 4e3264d commit 8c8110a

File tree

3 files changed

+41
-17
lines changed

3 files changed

+41
-17
lines changed

apps/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionTesterSheet.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'
1515
import { IS_PLATFORM } from 'lib/constants'
1616
import { prettifyJSON } from 'lib/helpers'
1717
import { getRoleImpersonationJWT } from 'lib/role-impersonation'
18-
import { useGetImpersonatedRoleState } from 'state/role-impersonation-state'
18+
import {
19+
RoleImpersonationStateContextProvider,
20+
useGetImpersonatedRoleState,
21+
} from 'state/role-impersonation-state'
1922
import {
2023
Badge,
2124
Button,
@@ -416,7 +419,12 @@ export const EdgeFunctionTesterSheet = ({ visible, onClose }: EdgeFunctionTester
416419

417420
<SheetFooter className="px-5 py-3 border-t">
418421
<div className="flex items-center gap-2">
419-
<RoleImpersonationPopover portal={false} />
422+
{/* [Alaister]: We're using a fresh context here as edge functions don't allow impersonating users. */}
423+
<RoleImpersonationStateContextProvider
424+
key={`role-impersonation-state-${projectRef}`}
425+
>
426+
<RoleImpersonationPopover portal={false} disallowAuthenticatedOption={true} />
427+
</RoleImpersonationStateContextProvider>
420428
<Button
421429
type="primary"
422430
htmlType="submit"

apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationPopover.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@ export interface RoleImpersonationPopoverProps {
1212
serviceRoleLabel?: string
1313
variant?: 'regular' | 'connected-on-right' | 'connected-on-left' | 'connected-on-both'
1414
align?: 'center' | 'start' | 'end'
15+
disallowAuthenticatedOption?: boolean
1516
}
1617

1718
const RoleImpersonationPopover = ({
1819
portal = true,
1920
serviceRoleLabel,
2021
variant = 'regular',
2122
align = 'end',
23+
disallowAuthenticatedOption = false,
2224
}: RoleImpersonationPopoverProps) => {
2325
const state = useRoleImpersonationStateSnapshot()
2426

@@ -64,7 +66,10 @@ const RoleImpersonationPopover = ({
6466
side="bottom"
6567
align={align}
6668
>
67-
<RoleImpersonationSelector serviceRoleLabel={serviceRoleLabel} />
69+
<RoleImpersonationSelector
70+
serviceRoleLabel={serviceRoleLabel}
71+
disallowAuthenticatedOption={disallowAuthenticatedOption}
72+
/>
6873
</PopoverContent_Shadcn_>
6974
</Popover_Shadcn_>
7075
)

apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationSelector.tsx

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@ import UserImpersonationSelector from './UserImpersonationSelector'
1010
export interface RoleImpersonationSelectorProps {
1111
serviceRoleLabel?: string
1212
padded?: boolean
13+
disallowAuthenticatedOption?: boolean
1314
}
1415

1516
const RoleImpersonationSelector = ({
1617
serviceRoleLabel,
1718
padded = true,
19+
disallowAuthenticatedOption = false,
1820
}: RoleImpersonationSelectorProps) => {
1921
const state = useRoleImpersonationStateSnapshot()
2022

@@ -81,38 +83,47 @@ const RoleImpersonationSelector = ({
8183
icon={<AnonIcon isSelected={selectedOption === 'anon'} />}
8284
/>
8385

84-
<RoleImpersonationRadio
85-
value="authenticated"
86-
isSelected={
87-
selectedOption === 'authenticated' &&
88-
(isAuthenticatedOptionFullySelected || 'partially')
89-
}
90-
onSelectedChange={onSelectedChange}
91-
icon={<AuthenticatedIcon isSelected={selectedOption === 'authenticated'} />}
92-
/>
86+
{!disallowAuthenticatedOption && (
87+
<RoleImpersonationRadio
88+
value="authenticated"
89+
isSelected={
90+
selectedOption === 'authenticated' &&
91+
(isAuthenticatedOptionFullySelected || 'partially')
92+
}
93+
onSelectedChange={onSelectedChange}
94+
icon={<AuthenticatedIcon isSelected={selectedOption === 'authenticated'} />}
95+
/>
96+
)}
9397
</fieldset>
9498
</form>
9599

96100
{selectedOption === 'service_role' && (
97101
<p className="text-foreground-light text-sm">
98-
The default Postgres/superuser role. This has admin privileges.
102+
The default Postgres/superuser role.
103+
{disallowAuthenticatedOption ? <br /> : ' '}
104+
This has admin privileges.
99105
<br />
100106
It will bypass Row Level Security (RLS) policies.
101107
</p>
102108
)}
103109

104110
{selectedOption === 'anon' && (
105111
<p className="text-foreground-light text-sm">
106-
For "anonymous access". This is the role which the API (PostgREST) will use when a user
112+
For "anonymous access".
113+
{disallowAuthenticatedOption ? <br /> : ' '}
114+
This is the role which the API (PostgREST)
107115
<br />
108-
is not logged in. It will respect Row Level Security (RLS) policies.
116+
will use when a user is not logged in.
117+
{disallowAuthenticatedOption ? <br /> : ' '}
118+
It will respect Row Level Security (RLS) policies.
109119
</p>
110120
)}
111121

112122
{selectedOption === 'authenticated' && (
113123
<p className="text-foreground-light text-sm">
114-
For "authenticated access". This is the role which the API (PostgREST) will use when
115-
<br /> a user is logged in. It will respect Row Level Security (RLS) policies.
124+
For "authenticated access". This is the role which the API (PostgREST)
125+
<br />
126+
will use when a user is logged in. It will respect Row Level Security (RLS) policies.
116127
</p>
117128
)}
118129
</div>

0 commit comments

Comments
 (0)