PolicyTableRowHeader.tsx150 lines · main
1import { PermissionAction } from '@supabase/shared-types/out/constants'
2import { useParams } from 'common'
3import { noop } from 'lodash'
4import { Lock, Table } from 'lucide-react'
5import { AiIconAnimation, Badge, CardTitle } from 'ui'
6
7import type { PolicyTable } from './PolicyTableRow.types'
8import { SIDEBAR_KEYS } from '@/components/layouts/ProjectLayout/LayoutSidebar/LayoutSidebarProvider'
9import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
10import { EditorTablePageLink } from '@/data/prefetchers/project.$ref.editor.$id'
11import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
12import { useAiAssistantStateSnapshot } from '@/state/ai-assistant-state'
13import { useSidebarManagerSnapshot } from '@/state/sidebar-manager-state'
14
15interface PolicyTableRowHeaderProps {
16 table: PolicyTable
17 isLocked: boolean
18 hasApiAccess: boolean
19 isLoadingApiAccess: boolean
20 onSelectToggleRLS: (table: PolicyTable) => void
21 onSelectCreatePolicy: (table: PolicyTable) => void
22}
23
24export const PolicyTableRowHeader = ({
25 table,
26 isLocked,
27 hasApiAccess,
28 isLoadingApiAccess,
29 onSelectToggleRLS = noop,
30 onSelectCreatePolicy,
31}: PolicyTableRowHeaderProps) => {
32 const { ref } = useParams()
33 const aiSnap = useAiAssistantStateSnapshot()
34 const { openSidebar } = useSidebarManagerSnapshot()
35
36 const { can: canCreatePolicies } = useAsyncCheckPermissions(
37 PermissionAction.TENANT_SQL_ADMIN_WRITE,
38 'policies'
39 )
40 const { can: canToggleRLS } = useAsyncCheckPermissions(
41 PermissionAction.TENANT_SQL_ADMIN_WRITE,
42 'tables'
43 )
44
45 const isRealtimeSchema = table.schema === 'realtime'
46 const isRealtimeMessagesTable = isRealtimeSchema && table.name === 'messages'
47 const isTableLocked = isRealtimeSchema ? !isRealtimeMessagesTable : isLocked
48
49 return (
50 <div id={table.id.toString()} className="flex w-full items-center justify-between">
51 <div className="flex gap-x-4 text-left flex-wrap">
52 <EditorTablePageLink
53 projectRef={ref}
54 id={String(table.id)}
55 className="flex items-center gap-3 flex-wrap"
56 >
57 <Table strokeWidth={1.5} size={16} className="text-foreground-muted" />
58 <CardTitle className="m-0 normal-case">{table.name}</CardTitle>
59 {!table.rls_enabled && (
60 <Badge variant="warning" className="shrink-0">
61 RLS Disabled
62 </Badge>
63 )}
64 {!isLoadingApiAccess && !hasApiAccess && (
65 <Badge variant="default" className="shrink-0">
66 API Disabled
67 </Badge>
68 )}
69 </EditorTablePageLink>
70 {isTableLocked && (
71 <Badge>
72 <span className="flex gap-2 items-center text-xs uppercase text-foreground-lighter">
73 <Lock size={12} /> Locked
74 </span>
75 </Badge>
76 )}
77 </div>
78 {!isTableLocked && (
79 <div className="flex-1">
80 <div className="flex flex-row justify-end gap-x-2">
81 {!isRealtimeMessagesTable && (
82 <ButtonTooltip
83 type="default"
84 disabled={!canToggleRLS}
85 onClick={() => onSelectToggleRLS(table)}
86 data-testid={`${table.name}-toggle-rls`}
87 tooltip={{
88 content: {
89 side: 'bottom',
90 text: !canToggleRLS
91 ? 'You need additional permissions to toggle RLS'
92 : undefined,
93 },
94 }}
95 >
96 {table.rls_enabled ? 'Disable RLS' : 'Enable RLS'}
97 </ButtonTooltip>
98 )}
99 <ButtonTooltip
100 type="default"
101 disabled={!canToggleRLS || !canCreatePolicies}
102 onClick={() => onSelectCreatePolicy(table)}
103 data-testid={`${table.name}-create-policy`}
104 tooltip={{
105 content: {
106 side: 'bottom',
107 text: !canToggleRLS
108 ? !canToggleRLS || !canCreatePolicies
109 ? 'You need additional permissions to create RLS policies'
110 : undefined
111 : undefined,
112 },
113 }}
114 >
115 Create policy
116 </ButtonTooltip>
117
118 <ButtonTooltip
119 type="default"
120 className="px-1"
121 onClick={() => {
122 openSidebar(SIDEBAR_KEYS.AI_ASSISTANT)
123 aiSnap.newChat({
124 name: 'Create new policy',
125 initialInput: `Create and name a new policy for the ${table.schema} schema on the ${table.name} table that ...`,
126 })
127 }}
128 tooltip={{
129 content: {
130 side: 'bottom',
131 text:
132 !canToggleRLS || !canCreatePolicies
133 ? 'You need additional permissions to create RLS policies'
134 : 'Create with Briven Assistant',
135 },
136 }}
137 aria-label={
138 !canToggleRLS || !canCreatePolicies
139 ? 'You need additional permissions to create RLS policies'
140 : 'Create with Briven Assistant'
141 }
142 >
143 <AiIconAnimation size={16} />
144 </ButtonTooltip>
145 </div>
146 </div>
147 )}
148 </div>
149 )
150}