Files
supabase/apps/studio/components/ui/AutoEnableRLSNotice.tsx
c569a29c26 chore(studio): use admonition for auto-enable RLS notice (#47354)
## What kind of change does this PR introduce?

Chore. UI polish for the auto-enable RLS notice.

## What is the current behavior?

Auto-enable RLS is shown in a card with a shield icon and a primary
"Learn more" button. The setup dialog uses longer copy and labels like
"Close" / "Create ensure_rls trigger".

## What is the new behavior?

- Banner uses a responsive note `Admonition` instead of a card.
- Clearer copy: title, description, and dialog body tightened around
protecting future tables.
- Actions: "Set up trigger" (default), "Cancel", "Create trigger";
dismiss tooltip updated.
- Code block border tweak in the dialog; SQL template gets a short
identifying comment.

| Before | After |
| --- | --- |
| <img width="1106" height="747" alt="Tables Database temp-stripe
wksp_6UXXrF9W8SK9CCKdlRh8Uts
Supabase-17201C2A-C57A-4AFE-BA79-591920BBEB8D"
src="https://github.com/user-attachments/assets/f7977ef1-b9c2-4064-b779-b32bdbcc4214"
/> | <img width="1106" height="747" alt="Tables Database temp-stripe
wksp_6UXXrF9W8SK9CCKdlRh8Uts
Supabase-48D740A2-0814-41FE-AE92-F86F1C6C4397"
src="https://github.com/user-attachments/assets/7168cd82-5563-4718-94e3-1ffb4fa690c1"
/> |
| <img width="1106" height="747" alt="Tables Database temp-stripe
wksp_6UXXrF9W8SK9CCKdlRh8Uts
Supabase-7FC76297-7640-440E-B4BF-34ECA51F652B"
src="https://github.com/user-attachments/assets/0b38711e-c6af-4d15-a4d5-d98db28bce20"
/> | <img width="1106" height="747" alt="Tables Database temp-stripe
wksp_6UXXrF9W8SK9CCKdlRh8Uts
Supabase-E98B2F86-E19C-4F5B-988F-DAC40E1B845D"
src="https://github.com/user-attachments/assets/01fa3b62-af2b-447d-bd17-b92e86064285"
/> |

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **UI Improvements**
* Refreshed the RLS notice banner with updated wording and a cleaner
alert-style presentation.
* Improved the trigger setup dialog copy, including title/description
text and updated button labels.
* Updated the trigger creation tooltip/action wording for clearer
guidance.
* **Documentation**
* Added a small inline label comment to the generated auto-enable RLS
event trigger SQL for easier readability.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-07-01 01:51:43 +10:00

182 lines
6.0 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { LOCAL_STORAGE_KEYS, useParams } from 'common'
import { ShieldCheck, X } from 'lucide-react'
import { useMemo, useState } from 'react'
import { toast } from 'sonner'
import {
Button,
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogSection,
DialogSectionSeparator,
DialogTitle,
DialogTrigger,
} from 'ui'
import { Admonition } from 'ui-patterns/admonition'
import { CodeBlock } from 'ui-patterns/CodeBlock'
import { AUTO_ENABLE_RLS_EVENT_TRIGGER_SQL } from '@/components/interfaces/Database/Triggers/EventTriggersList/EventTriggers.constants'
import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
import { useDatabaseEventTriggerCreateMutation } from '@/data/database-event-triggers/database-event-trigger-create-mutation'
import { useDatabaseEventTriggersQuery } from '@/data/database-event-triggers/database-event-triggers-query'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useLocalStorageQuery } from '@/hooks/misc/useLocalStorage'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { useTrack } from '@/lib/telemetry/track'
export const AutoEnableRLSNotice = ({ iconOnly }: { iconOnly?: boolean }) => {
const { ref } = useParams()
const { data: project } = useSelectedProjectQuery()
const projectRef = ref ?? project?.ref
// [Joshen] Changing the behaviour of this to not be dismissible, only minimized
// Given that its a security measure that we highly advise. Otherwise there's no way for users to revisit this
const [, setIsMinimized] = useLocalStorageQuery(
LOCAL_STORAGE_KEYS.RLS_EVENT_TRIGGER_BANNER_DISMISSED(projectRef ?? 'unknown'),
false
)
const { data: eventTriggers = [], isLoading: isLoadingEventTriggers } =
useDatabaseEventTriggersQuery({
projectRef: project?.ref,
connectionString: project?.connectionString,
})
const hasDefaultTrigger = useMemo(
() =>
eventTriggers.some(
(trigger) => trigger.name === 'ensure_rls' || trigger.function_name === 'rls_auto_enable'
),
[eventTriggers]
)
if (!projectRef || isLoadingEventTriggers || hasDefaultTrigger) return null
if (iconOnly) {
return <CreateEnsureRLSTriggerDialog iconOnly />
}
return (
<Admonition
type="note"
layout="responsive"
title="Automatically enable Row Level Security (RLS) on new tables"
description="Protect future tables by automatically enabling RLS whenever a table is created."
actions={
<>
<CreateEnsureRLSTriggerDialog />
<ButtonTooltip
icon={<X />}
variant="text"
className="w-6"
tooltip={{ content: { side: 'bottom', text: 'Dismiss' } }}
aria-label="Dismiss RLS notice"
onClick={() => setIsMinimized(true)}
/>
</>
}
/>
)
}
const CreateEnsureRLSTriggerDialog = ({ iconOnly }: { iconOnly?: boolean }) => {
const track = useTrack()
const { data: project } = useSelectedProjectQuery()
const [open, setOpen] = useState(false)
const { can: canCreateTriggers } = useAsyncCheckPermissions(
PermissionAction.TENANT_SQL_ADMIN_WRITE,
'triggers'
)
const { mutate: createEventTrigger, isPending: isCreating } =
useDatabaseEventTriggerCreateMutation({
onSuccess: () => {
toast.success(
'Successfully set up database trigger to automatically enable RLS on all new tables'
)
setOpen(false)
},
})
const handleCreateTrigger = () => {
if (!project) return
track('rls_event_trigger_banner_create_button_clicked')
createEventTrigger({
projectRef: project.ref,
connectionString: project.connectionString,
sql: AUTO_ENABLE_RLS_EVENT_TRIGGER_SQL,
})
}
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
{iconOnly ? (
<ButtonTooltip
variant="default"
icon={<ShieldCheck />}
className="w-7"
tooltip={{ content: { side: 'bottom', text: 'Auto-enable RLS for new tables' } }}
/>
) : (
<Button variant="default">Set up trigger</Button>
)}
</DialogTrigger>
<DialogContent size="large">
<DialogHeader>
<DialogTitle>Automatically enable RLS for new tables</DialogTitle>
<DialogDescription>
Protect future tables with a built-in database trigger.
</DialogDescription>
</DialogHeader>
<DialogSectionSeparator />
<DialogSection className="text-sm flex flex-col gap-y-2">
<p>
Tables in exposed schemas such as <code className="text-code-inline">public</code> are
reachable through your project’s API. Enable Row Level Security (RLS) on these tables so
access is governed by the policies you define, not just the project API key.
</p>
<p>
This trigger automatically enables RLS whenever a new table is created. Review the SQL
before creating it:
</p>
</DialogSection>
<CodeBlock
language="sql"
className="language-sql px-0 border-x-0 border-b-0 rounded-none h-64"
>
{AUTO_ENABLE_RLS_EVENT_TRIGGER_SQL.trim()}
</CodeBlock>
<DialogFooter>
<Button variant="default" disabled={isCreating} onClick={() => setOpen(false)}>
Cancel
</Button>
<ButtonTooltip
disabled={!canCreateTriggers}
loading={isCreating}
onClick={handleCreateTrigger}
tooltip={{
content: {
side: 'bottom',
text: !canCreateTriggers
? 'You need additional permissions to create triggers'
: undefined,
},
}}
>
Create trigger
</ButtonTooltip>
</DialogFooter>
</DialogContent>
</Dialog>
)
}