From 0e9012c04fbb144fcaa895e9a53979f4d2ff20c7 Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Wed, 22 Apr 2026 23:30:49 +0800 Subject: [PATCH] Nit --- .../Auth/RLSTester/RLSTableCard.tsx | 63 +++++++------- .../Auth/RLSTester/RLSTesterSheet.tsx | 87 +++++++++++++++---- .../EdgeFunctionTesterSheet.tsx | 2 +- 3 files changed, 106 insertions(+), 46 deletions(-) diff --git a/apps/studio/components/interfaces/Auth/RLSTester/RLSTableCard.tsx b/apps/studio/components/interfaces/Auth/RLSTester/RLSTableCard.tsx index 18670c8ebb7..25ca8b5942b 100644 --- a/apps/studio/components/interfaces/Auth/RLSTester/RLSTableCard.tsx +++ b/apps/studio/components/interfaces/Auth/RLSTester/RLSTableCard.tsx @@ -8,9 +8,9 @@ import { CollapsibleTrigger_Shadcn_, WarningIcon, } from 'ui' -import { Admonition } from 'ui-patterns' import { ButtonTooltip } from '@/components/ui/ButtonTooltip' +import { useRoleImpersonationStateSnapshot } from '@/state/role-impersonation-state' interface RLSTableCardProps { table: { schema: string; name: string; isRLSEnabled: boolean } @@ -53,9 +53,10 @@ export const RLSTableCard = ({ <> {!!trueOnlyPolicy ? (

- A policy exists for the {role} role on this - table that evaluates to true, so all data is - accessible to the role. + The policy "{trueOnlyPolicy.name}" for the{' '} + {role} role on this table that evaluates to{' '} + true, so all data from this query is + accessible to this user.

) : (

@@ -65,31 +66,33 @@ export const RLSTableCard = ({

)} -

- Evaluated policies -

- +
+

+ {policies.length} {policies.length > 1 ? 'policies' : 'policy'} applied +

+ +
) }, [isRLSEnabled, noPolicies, trueOnlyPolicy, role, policies, handleSelectEditPolicy]) @@ -97,7 +100,7 @@ export const RLSTableCard = ({ return (
diff --git a/apps/studio/components/interfaces/Auth/RLSTester/RLSTesterSheet.tsx b/apps/studio/components/interfaces/Auth/RLSTester/RLSTesterSheet.tsx index 265fc204790..1f0f89d5129 100644 --- a/apps/studio/components/interfaces/Auth/RLSTester/RLSTesterSheet.tsx +++ b/apps/studio/components/interfaces/Auth/RLSTester/RLSTesterSheet.tsx @@ -35,6 +35,7 @@ import { Results } from '../../SQLEditor/UtilityPanel/Results' import { RLSTableCard } from './RLSTableCard' import { CodeEditor } from '@/components/ui/CodeEditor/CodeEditor' import { useParseClientCodeMutation } from '@/data/ai/parse-client-code-mutation' +import type { User } from '@/data/auth/users-infinite-query' import { useDatabasePoliciesQuery } from '@/data/database-policies/database-policies-query' import { useCheckTableRLSStatusMutation } from '@/data/database/table-check-rls-mutation' import { @@ -61,6 +62,8 @@ type ParseQueryResults = { }[] operation: ParseSQLQueryResponse['operation'] role?: string + user?: User + externalAuth?: string } interface RLSTesterSheetProps { @@ -105,7 +108,7 @@ export const RLSTesterSheet = ({ handleSelectEditPolicy }: RLSTesterSheetProps) const { mutateAsync: getTableRLSStatus } = useCheckTableRLSStatusMutation() const isServiceRole = parseQueryResults?.role === undefined - const hasRLSEnabledButNoPolicies = parseQueryResults?.tables.some( + const tableWithRLSEnabledButNoPolicies = parseQueryResults?.tables.find( (x) => x.isRLSEnabled && x.tablePolicies.length === 0 ) @@ -174,7 +177,26 @@ export const RLSTesterSheet = ({ handleSelectEditPolicy }: RLSTesterSheetProps) queryKey: ['rls-tester'], }) - setParseQueryResults({ tables, operation: data.operation, role: role?.role }) + const user = + impersonatedRoleState.role?.type === 'postgrest' && + impersonatedRoleState.role.role === 'authenticated' && + impersonatedRoleState.role.userType === 'native' + ? impersonatedRoleState.role.user + : undefined + const externalAuth = + impersonatedRoleState.role?.type === 'postgrest' && + impersonatedRoleState.role.role === 'authenticated' && + impersonatedRoleState.role.userType === 'external' && + impersonatedRoleState.role.externalAuth + ? impersonatedRoleState.role.externalAuth.sub + : undefined + setParseQueryResults({ + tables, + operation: data.operation, + role: role?.role, + user, + externalAuth, + }) } else { toast('Only SELECT statements are supported for now') } @@ -316,32 +338,67 @@ export const RLSTesterSheet = ({ handleSelectEditPolicy }: RLSTesterSheetProps) <>

- Table access summary + Summary

- {!isServiceRole && hasRLSEnabledButNoPolicies && ( - + + {!!parseQueryResults && ( +
+
+

Ran as

+ {!parseQueryResults.role ? ( + postgres + ) : parseQueryResults.user ? ( +

{parseQueryResults.user.email}

+ ) : parseQueryResults.externalAuth ? ( +

+ {parseQueryResults.externalAuth} +

+ ) : ( + {parseQueryResults.role} + )} +
+ + {parseQueryResults.role === 'anon' && ( +

Not logged in user

+ )} + {!!parseQueryResults.user && ( + ID: {parseQueryResults.user.id} + )} +
+ )} + + {!isServiceRole && !!tableWithRLSEnabledButNoPolicies && ( +

Query returns no rows for the{' '} {parseQueryResults.role} role

- One of the tables has RLS enabled, but no policies set up for this role + The table{' '} + + {tableWithRLSEnabledButNoPolicies.schema}. + {tableWithRLSEnabledButNoPolicies.table} + {' '} + has RLS enabled but no policies set up for this role.

)} {isServiceRole ? ( - + +

+ Query returns all rows for the{' '} + postgres role +

+

+ The role has admin privileges and bypasses all RLS policies. +

+
) : ( <> - {/*

- Table access -

*/} +

+ Policies applied +

{parseQueryResults?.tables.map((x) => { const { schema, table, tablePolicies, isRLSEnabled } = x diff --git a/apps/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionTesterSheet.tsx b/apps/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionTesterSheet.tsx index 106c5e22a22..9e5f0b7fc30 100644 --- a/apps/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionTesterSheet.tsx +++ b/apps/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionTesterSheet.tsx @@ -450,7 +450,7 @@ export const EdgeFunctionTesterSheet = ({ visible, onClose }: EdgeFunctionTester - +