mirror of
https://github.com/supabase/supabase.git
synced 2026-10-10 20:05:06 +03:00
## Context Previous PR was [here](https://github.com/supabase/supabase/pull/45143) but it got stale with lots of conflicts so figured it'll be easier redo it off the latest master Moves policies page from Auth to Database under an Access Control section along with Roles. This moves all existing files, applies redirects, and updates urls to point to the new route <img width="274" height="412" alt="image" src="https://github.com/user-attachments/assets/7952c185-64ae-4355-ba36-45397efe1787" /> <img width="453" height="471" alt="image" src="https://github.com/user-attachments/assets/04b3dcb3-48a5-4049-9893-d01109fb46a9" /> ## To test - [ ] Verify that policies now live under Database correctly <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a quick navigation shortcut to open **Database > Policies (RLS)**. * **Bug Fixes** * Updated Policies and RLS-related links across the product to open the **Database policies** area (menus, command palette, context actions, alerts, and link-outs). * Added a permanent redirect from the old **auth policies** URL to the new **database policies** URL. * **Documentation** * Updated RLS Dashboard and security checklist instructions to reference **Database > Policies**. * **Tests** * Adjusted automated tests to validate the new Policies route. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
151 lines
5.3 KiB
TypeScript
151 lines
5.3 KiB
TypeScript
import { PermissionAction } from '@supabase/shared-types/out/constants'
|
|
import { useParams } from 'common'
|
|
import { noop } from 'lodash'
|
|
import { Lock, Table } from 'lucide-react'
|
|
import { AiIconAnimation, Badge, CardTitle } from 'ui'
|
|
|
|
import type { PolicyTable } from './PolicyTableRow.types'
|
|
import { SIDEBAR_KEYS } from '@/components/layouts/ProjectLayout/LayoutSidebar/LayoutSidebarProvider'
|
|
import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
|
|
import { EditorTablePageLink } from '@/data/prefetchers/project.$ref.editor.$id'
|
|
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
|
|
import { useAiAssistantStateSnapshot } from '@/state/ai-assistant-state'
|
|
import { useSidebarManagerSnapshot } from '@/state/sidebar-manager-state'
|
|
|
|
interface PolicyTableRowHeaderProps {
|
|
table: PolicyTable
|
|
isLocked: boolean
|
|
hasApiAccess: boolean
|
|
isLoadingApiAccess: boolean
|
|
onSelectToggleRLS: (table: PolicyTable) => void
|
|
onSelectCreatePolicy: (table: PolicyTable) => void
|
|
}
|
|
|
|
export const PolicyTableRowHeader = ({
|
|
table,
|
|
isLocked,
|
|
hasApiAccess,
|
|
isLoadingApiAccess,
|
|
onSelectToggleRLS = noop,
|
|
onSelectCreatePolicy,
|
|
}: PolicyTableRowHeaderProps) => {
|
|
const { ref } = useParams()
|
|
const aiSnap = useAiAssistantStateSnapshot()
|
|
const { openSidebar } = useSidebarManagerSnapshot()
|
|
|
|
const { can: canCreatePolicies } = useAsyncCheckPermissions(
|
|
PermissionAction.TENANT_SQL_ADMIN_WRITE,
|
|
'policies'
|
|
)
|
|
const { can: canToggleRLS } = useAsyncCheckPermissions(
|
|
PermissionAction.TENANT_SQL_ADMIN_WRITE,
|
|
'tables'
|
|
)
|
|
|
|
const isRealtimeSchema = table.schema === 'realtime'
|
|
const isRealtimeMessagesTable = isRealtimeSchema && table.name === 'messages'
|
|
const isTableLocked = isRealtimeSchema ? !isRealtimeMessagesTable : isLocked
|
|
|
|
return (
|
|
<div id={table.id.toString()} className="flex w-full items-center justify-between">
|
|
<div className="flex gap-x-4 text-left flex-wrap">
|
|
<EditorTablePageLink
|
|
projectRef={ref}
|
|
id={String(table.id)}
|
|
className="flex items-center gap-3 flex-wrap"
|
|
>
|
|
<Table strokeWidth={1.5} size={16} className="text-foreground-muted" />
|
|
<CardTitle className="m-0 normal-case">{table.name}</CardTitle>
|
|
{!table.rls_enabled && (
|
|
<Badge variant="warning" className="shrink-0">
|
|
RLS Disabled
|
|
</Badge>
|
|
)}
|
|
{!isLoadingApiAccess && !hasApiAccess && (
|
|
<Badge variant="default" className="shrink-0">
|
|
API Disabled
|
|
</Badge>
|
|
)}
|
|
</EditorTablePageLink>
|
|
{isTableLocked && (
|
|
<Badge>
|
|
<span className="flex gap-2 items-center text-xs uppercase text-foreground-lighter">
|
|
<Lock size={12} /> Locked
|
|
</span>
|
|
</Badge>
|
|
)}
|
|
</div>
|
|
{!isTableLocked && (
|
|
<div className="flex-1">
|
|
<div className="flex flex-row justify-end gap-x-2">
|
|
{!isRealtimeMessagesTable && (
|
|
<ButtonTooltip
|
|
variant="default"
|
|
disabled={!canToggleRLS}
|
|
onClick={() => onSelectToggleRLS(table)}
|
|
data-testid={`${table.name}-toggle-rls`}
|
|
tooltip={{
|
|
content: {
|
|
side: 'bottom',
|
|
text: !canToggleRLS
|
|
? 'You need additional permissions to toggle RLS'
|
|
: undefined,
|
|
},
|
|
}}
|
|
>
|
|
{table.rls_enabled ? 'Disable RLS' : 'Enable RLS'}
|
|
</ButtonTooltip>
|
|
)}
|
|
<ButtonTooltip
|
|
variant="default"
|
|
disabled={!canToggleRLS || !canCreatePolicies}
|
|
onClick={() => onSelectCreatePolicy(table)}
|
|
data-testid={`${table.name}-create-policy`}
|
|
tooltip={{
|
|
content: {
|
|
side: 'bottom',
|
|
text: !canToggleRLS
|
|
? !canToggleRLS || !canCreatePolicies
|
|
? 'You need additional permissions to create RLS policies'
|
|
: undefined
|
|
: undefined,
|
|
},
|
|
}}
|
|
>
|
|
Create policy
|
|
</ButtonTooltip>
|
|
|
|
<ButtonTooltip
|
|
variant="default"
|
|
className="px-1"
|
|
onClick={() => {
|
|
openSidebar(SIDEBAR_KEYS.AI_ASSISTANT)
|
|
aiSnap.newChat({
|
|
name: 'Create new policy',
|
|
initialInput: `Create and name a new policy for the ${table.schema} schema on the ${table.name} table that ...`,
|
|
})
|
|
}}
|
|
tooltip={{
|
|
content: {
|
|
side: 'bottom',
|
|
text:
|
|
!canToggleRLS || !canCreatePolicies
|
|
? 'You need additional permissions to create RLS policies'
|
|
: 'Create with Supabase Assistant',
|
|
},
|
|
}}
|
|
aria-label={
|
|
!canToggleRLS || !canCreatePolicies
|
|
? 'You need additional permissions to create RLS policies'
|
|
: 'Create with Supabase Assistant'
|
|
}
|
|
>
|
|
<AiIconAnimation size={16} />
|
|
</ButtonTooltip>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|