Skip to content

Commit d8a57c1

Browse files
authored
Add settings for queues: toggle expose through postgrest + permissions via table privileges (supabase#30564)
* Add settings for queues: toggle expose through postgrest + permissions via table privileges * Ensure appropriate grants are granted when toggling, and revoked when disabling * Update to use queues_public schema * Update queue schema to pgmq_public and add/remove from data api when enabling/disabling * Fix query for retrieving toggle state * Add schema invalidation * Remove hard code * Use QueuesSettings from Queues folder, remove from NewQueues * Update SQL for toggling exposure + support RLS enabling * Support toggling RLS for a queue * Update admonition copy in queues for enabling/disable postgrest exposure * Add custom RLS policy for queue * Minor style fixes * Fix * Remove hard code * Update RLS to add message regarding relevancy only if exposure to PostgREST is enabled * Update message in exposing queues to postgREST * Address feedback * Address feedback * Don't revoke postgres role stuff * Remove hard code * Update copy * Update * Address Oli's feedback, ensure that queues ALL have RLS enabled prior to allowing exposure to PostgREST * Address remaining feedback * Remove hardcode * Update * Address feedback
1 parent 48c0578 commit d8a57c1

File tree

44 files changed

+1471
-137
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1471
-137
lines changed

apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/PolicyTemplates.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import CopyButton from 'components/ui/CopyButton'
1010
import NoSearchResults from 'components/ui/NoSearchResults'
1111
import {
1212
getGeneralPolicyTemplates,
13+
getQueuePolicyTemplates,
1314
getRealtimePolicyTemplates,
1415
} from '../PolicyEditorModal/PolicyEditorModal.constants'
1516

@@ -33,7 +34,9 @@ export const PolicyTemplates = ({
3334
const templates =
3435
schema === 'realtime'
3536
? getRealtimePolicyTemplates()
36-
: getGeneralPolicyTemplates(schema, table.length > 0 ? table : 'table_name')
37+
: schema === 'pgmq'
38+
? getQueuePolicyTemplates()
39+
: getGeneralPolicyTemplates(schema, table.length > 0 ? table : 'table_name')
3740

3841
const baseTemplates =
3942
selectedPolicy !== undefined

apps/studio/components/interfaces/Auth/Policies/PolicyEditorModal/PolicyEditorModal.constants.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,3 +326,21 @@ with check ( realtime.messages.extension = 'presence' AND realtime.topic() = 'ch
326326
] as PolicyTemplate[]
327327
return results
328328
}
329+
330+
export const getQueuePolicyTemplates = (): PolicyTemplate[] => {
331+
return [
332+
{
333+
id: 'policy-queues-1',
334+
preview: false,
335+
templateName: 'Allow access to queue',
336+
statement: ``.trim(),
337+
name: 'Allow anon and authenticated to access messages from queue',
338+
description:
339+
'Base policy to ensure that anon and authenticated can only access appropriate rows. USING and CHECK statements will need to be adjusted accordingly',
340+
definition: 'true',
341+
check: 'true',
342+
command: 'ALL',
343+
roles: ['anon', 'authenticated'],
344+
},
345+
]
346+
}

apps/studio/components/interfaces/Auth/Policies/PolicyTableRow/PolicyRow.tsx

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -62,37 +62,43 @@ const PolicyRow = ({
6262
'w-full last:border-0 space-x-4 border-b py-4 lg:items-center'
6363
)}
6464
>
65-
<div className="flex grow flex-col space-y-1">
66-
<div className="flex items-center space-x-4">
67-
<p className="font-mono text-xs text-foreground-light">{policy.command}</p>
68-
<p className="text-sm text-foreground">{policy.name}</p>
65+
<div className="flex grow flex-col gap-y-1">
66+
<div className="flex items-start gap-x-4">
67+
<p className="font-mono text-xs text-foreground-light translate-y-[2px] min-w-12">
68+
{policy.command}
69+
</p>
70+
71+
<div className="flex flex-col gap-y-1">
72+
<p className="text-sm text-foreground">{policy.name}</p>
73+
<div className="flex items-center gap-x-1">
74+
<div className="text-foreground-lighter text-sm">
75+
Applied to:
76+
{policy.roles.slice(0, 3).map((role, i) => (
77+
<code key={`policy-${role}-${i}`} className="text-foreground-light text-xs">
78+
{role}
79+
</code>
80+
))}{' '}
81+
role
82+
</div>
83+
{policy.roles.length > 3 && (
84+
<Tooltip_Shadcn_>
85+
<TooltipTrigger_Shadcn_ asChild>
86+
<code key="policy-etc" className="text-foreground-light text-xs">
87+
+ {policy.roles.length - 3} more roles
88+
</code>
89+
</TooltipTrigger_Shadcn_>
90+
<TooltipContent_Shadcn_ side="bottom" align="center">
91+
{policy.roles.slice(3).join(', ')}
92+
</TooltipContent_Shadcn_>
93+
</Tooltip_Shadcn_>
94+
)}
95+
</div>
96+
</div>
97+
6998
{appliesToAnonymousUsers ? (
7099
<Badge color="yellow">Applies to anonymous users</Badge>
71100
) : null}
72101
</div>
73-
<div className="flex items-center gap-x-1 ml-[60px]">
74-
<div className="text-foreground-lighter text-sm">
75-
Applied to:
76-
{policy.roles.slice(0, 3).map((role, i) => (
77-
<code key={`policy-${role}-${i}`} className="text-foreground-light text-xs">
78-
{role}
79-
</code>
80-
))}{' '}
81-
role
82-
</div>
83-
{policy.roles.length > 3 && (
84-
<Tooltip_Shadcn_>
85-
<TooltipTrigger_Shadcn_ asChild>
86-
<code key="policy-etc" className="text-foreground-light text-xs">
87-
+ {policy.roles.length - 3} more roles
88-
</code>
89-
</TooltipTrigger_Shadcn_>
90-
<TooltipContent_Shadcn_ side="bottom" align="center">
91-
{policy.roles.slice(3).join(', ')}
92-
</TooltipContent_Shadcn_>
93-
</Tooltip_Shadcn_>
94-
)}
95-
</div>
96102
</div>
97103
<div>
98104
{!isLocked && (

apps/studio/components/interfaces/Database/EnumeratedTypes/EnumeratedTypes.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
useEnumeratedTypesQuery,
1414
} from 'data/enumerated-types/enumerated-types-query'
1515
import { useQuerySchemaState } from 'hooks/misc/useSchemaQueryState'
16-
import { EXCLUDED_SCHEMAS } from 'lib/constants/schemas'
16+
import { PROTECTED_SCHEMAS } from 'lib/constants/schemas'
1717
import {
1818
Button,
1919
DropdownMenu,
@@ -53,7 +53,7 @@ const EnumeratedTypes = () => {
5353
: enumeratedTypes.filter((x) => x.schema === selectedSchema)
5454

5555
const protectedSchemas = (schemas ?? []).filter((schema) =>
56-
EXCLUDED_SCHEMAS.includes(schema?.name ?? '')
56+
PROTECTED_SCHEMAS.includes(schema?.name ?? '')
5757
)
5858
const schema = schemas?.find((schema) => schema.name === selectedSchema)
5959
const isLocked = protectedSchemas.some((s) => s.id === schema?.id)

apps/studio/components/interfaces/Database/Functions/CreateFunction/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-ex
1313
import { useDatabaseFunctionCreateMutation } from 'data/database-functions/database-functions-create-mutation'
1414
import { DatabaseFunction } from 'data/database-functions/database-functions-query'
1515
import { useDatabaseFunctionUpdateMutation } from 'data/database-functions/database-functions-update-mutation'
16-
import { EXCLUDED_SCHEMAS } from 'lib/constants/schemas'
16+
import { PROTECTED_SCHEMAS } from 'lib/constants/schemas'
1717
import type { FormSchema } from 'types'
1818
import {
1919
Button,
@@ -203,7 +203,7 @@ const CreateFunction = ({ func, visible, setVisible }: CreateFunctionProps) => {
203203
<FormControl_Shadcn_>
204204
<SchemaSelector
205205
selectedSchemaName={field.value}
206-
excludedSchemas={EXCLUDED_SCHEMAS}
206+
excludedSchemas={PROTECTED_SCHEMAS}
207207
size="small"
208208
onSelectSchema={(name) => field.onChange(name)}
209209
/>

apps/studio/components/interfaces/Database/Functions/FunctionsList/FunctionsList.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { useDatabaseFunctionsQuery } from 'data/database-functions/database-func
1717
import { useSchemasQuery } from 'data/database/schemas-query'
1818
import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
1919
import { useQuerySchemaState } from 'hooks/misc/useSchemaQueryState'
20-
import { EXCLUDED_SCHEMAS } from 'lib/constants/schemas'
20+
import { PROTECTED_SCHEMAS } from 'lib/constants/schemas'
2121
import { useAppStateSnapshot } from 'state/app-state'
2222
import { AiIconAnimation, Input } from 'ui'
2323
import ProtectedSchemaWarning from '../../ProtectedSchemaWarning'
@@ -63,7 +63,7 @@ const FunctionsList = ({
6363
connectionString: project?.connectionString,
6464
})
6565
const [protectedSchemas] = partition(schemas ?? [], (schema) =>
66-
EXCLUDED_SCHEMAS.includes(schema?.name ?? '')
66+
PROTECTED_SCHEMAS.includes(schema?.name ?? '')
6767
)
6868
const foundSchema = schemas?.find((schema) => schema.name === selectedSchema)
6969
const isLocked = protectedSchemas.some((s) => s.id === foundSchema?.id)

apps/studio/components/interfaces/Database/Indexes/Indexes.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { DatabaseIndex, useIndexesQuery } from 'data/database/indexes-query'
1313
import { useSchemasQuery } from 'data/database/schemas-query'
1414
import { useExecuteSqlMutation } from 'data/sql/execute-sql-mutation'
1515
import { useQuerySchemaState } from 'hooks/misc/useSchemaQueryState'
16-
import { EXCLUDED_SCHEMAS } from 'lib/constants/schemas'
16+
import { PROTECTED_SCHEMAS } from 'lib/constants/schemas'
1717
import { AlertCircle, Search, Trash } from 'lucide-react'
1818
import { Button, Input, SidePanel } from 'ui'
1919
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
@@ -64,7 +64,7 @@ const Indexes = () => {
6464
})
6565

6666
const [protectedSchemas] = partition(schemas ?? [], (schema) =>
67-
EXCLUDED_SCHEMAS.includes(schema?.name ?? '')
67+
PROTECTED_SCHEMAS.includes(schema?.name ?? '')
6868
)
6969
const schema = schemas?.find((schema) => schema.name === selectedSchema)
7070
const isLocked = protectedSchemas.some((s) => s.id === schema?.id)

apps/studio/components/interfaces/Database/ProtectedSchemaWarning.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useState } from 'react'
22
import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, Alert_Shadcn_, Button, Modal } from 'ui'
33

4-
import { EXCLUDED_SCHEMAS } from 'lib/constants/schemas'
4+
import { PROTECTED_SCHEMAS } from 'lib/constants/schemas'
55
import { AlertCircle } from 'lucide-react'
66

77
export const ProtectedSchemaModal = ({
@@ -31,7 +31,7 @@ export const ProtectedSchemaModal = ({
3131
access through the dashboard.
3232
</p>
3333
<div className="flex flex-wrap gap-1">
34-
{EXCLUDED_SCHEMAS.map((schema) => (
34+
{PROTECTED_SCHEMAS.map((schema) => (
3535
<code key={schema} className="text-xs">
3636
{schema}
3737
</code>

apps/studio/components/interfaces/Database/Publications/PublicationsTables.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import InformationBox from 'components/ui/InformationBox'
1010
import { Loading } from 'components/ui/Loading'
1111
import { useTablesQuery } from 'data/tables/tables-query'
1212
import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
13-
import { EXCLUDED_SCHEMAS } from 'lib/constants/schemas'
13+
import { PROTECTED_SCHEMAS } from 'lib/constants/schemas'
1414
import { Button, Input } from 'ui'
1515
import PublicationsTableItem from './PublicationsTableItem'
1616
import { ChevronLeft, Search, AlertCircle } from 'lucide-react'
@@ -44,8 +44,8 @@ const PublicationsTables = ({ selectedPublication, onSelectBack }: PublicationsT
4444
select(tables) {
4545
return tables.filter((table) =>
4646
filterString.length === 0
47-
? !EXCLUDED_SCHEMAS.includes(table.schema)
48-
: !EXCLUDED_SCHEMAS.includes(table.schema) && table.name.includes(filterString)
47+
? !PROTECTED_SCHEMAS.includes(table.schema)
48+
: !PROTECTED_SCHEMAS.includes(table.schema) && table.name.includes(filterString)
4949
)
5050
},
5151
}

apps/studio/components/interfaces/Database/Tables/ColumnList.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader'
1515
import { useTableEditorQuery } from 'data/table-editor/table-editor-query'
1616
import { isTableLike } from 'data/table-editor/table-editor-types'
1717
import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
18-
import { EXCLUDED_SCHEMAS } from 'lib/constants/schemas'
18+
import { PROTECTED_SCHEMAS } from 'lib/constants/schemas'
1919
import {
2020
Button,
2121
DropdownMenu,
@@ -61,7 +61,7 @@ const ColumnList = ({
6161
? selectedTable?.columns ?? []
6262
: selectedTable?.columns?.filter((column: any) => column.name.includes(filterString))) ?? []
6363

64-
const isLocked = EXCLUDED_SCHEMAS.includes(selectedTable?.schema ?? '')
64+
const isLocked = PROTECTED_SCHEMAS.includes(selectedTable?.schema ?? '')
6565
const canUpdateColumns = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'columns')
6666

6767
return (

0 commit comments

Comments
 (0)