import * as Tooltip from '@radix-ui/react-tooltip' import type { PostgresTable } from '@supabase/postgres-meta' import { PermissionAction } from '@supabase/shared-types/out/constants' import { useParams } from 'common' import { Lock, MousePointer2, PlusCircle } from 'lucide-react' import Link from 'next/link' import { useState } from 'react' import toast from 'react-hot-toast' import { Button, Modal, PopoverContent_Shadcn_, PopoverTrigger_Shadcn_, Popover_Shadcn_ } from 'ui' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import APIDocsButton from 'components/ui/APIDocsButton' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import ConfirmModal from 'ui-patterns/Dialogs/ConfirmDialog' import { useDatabasePoliciesQuery } from 'data/database-policies/database-policies-query' import { useDatabasePublicationsQuery } from 'data/database-publications/database-publications-query' import { useDatabasePublicationUpdateMutation } from 'data/database-publications/database-publications-update-mutation' import { useTableUpdateMutation } from 'data/tables/table-update-mutation' import { useCheckPermissions, useIsFeatureEnabled } from 'hooks' import { RoleImpersonationPopover } from '../RoleImpersonationSelector' import { EXCLUDED_SCHEMAS } from 'lib/constants/schemas' export interface GridHeaderActionsProps { table: PostgresTable canEditViaTableEditor: boolean isViewSelected: boolean isTableSelected: boolean } const GridHeaderActions = ({ table, isViewSelected, isTableSelected }: GridHeaderActionsProps) => { const { ref } = useParams() const { project } = useProjectContext() const realtimeEnabled = useIsFeatureEnabled('realtime:all') const isLocked = EXCLUDED_SCHEMAS.includes(table.schema) const { mutate: updateTable } = useTableUpdateMutation({ onError: (error) => { toast.error(`Failed to toggle RLS: ${error.message}`) }, onSettled: () => { closeConfirmModal() }, }) const [showEnableRealtime, setShowEnableRealtime] = useState(false) const [open, setOpen] = useState(false) const [rlsConfirmModalOpen, setRlsConfirmModalOpen] = useState(false) const projectRef = project?.ref const { data } = useDatabasePoliciesQuery({ projectRef: project?.ref, connectionString: project?.connectionString, }) const policies = (data ?? []).filter( (policy) => policy.schema === table.schema && policy.table === table.name ) const { data: publications } = useDatabasePublicationsQuery({ projectRef: project?.ref, connectionString: project?.connectionString, }) const realtimePublication = (publications ?? []).find( (publication) => publication.name === 'supabase_realtime' ) const realtimeEnabledTables = realtimePublication?.tables ?? [] const isRealtimeEnabled = realtimeEnabledTables.some((t: any) => t.id === table?.id) const { mutate: updatePublications, isLoading: isTogglingRealtime } = useDatabasePublicationUpdateMutation({ onSuccess: () => { setShowEnableRealtime(false) }, onError: (error) => { toast.error(`Failed to toggle realtime for ${table.name}: ${error.message}`) }, }) const canSqlWriteTables = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') const canSqlWriteColumns = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'columns') const isReadOnly = !canSqlWriteTables && !canSqlWriteColumns // This will change when we allow autogenerated API docs for schemas other than `public` const doesHaveAutoGeneratedAPIDocs = table.schema === 'public' const toggleRealtime = async () => { if (!project) return console.error('Project is required') if (!realtimePublication) return console.error('Unable to find realtime publication') const exists = realtimeEnabledTables.some((x: any) => x.id == table.id) const tables = !exists ? [`${table.schema}.${table.name}`].concat( realtimeEnabledTables.map((t: any) => `${t.schema}.${t.name}`) ) : realtimeEnabledTables .filter((x: any) => x.id != table.id) .map((x: any) => `${x.schema}.${x.name}`) updatePublications({ projectRef: project?.ref, connectionString: project?.connectionString, id: realtimePublication.id, tables, }) } const closeConfirmModal = () => { setRlsConfirmModalOpen(false) } const onToggleRLS = async () => { const payload = { id: table.id, rls_enabled: !table.rls_enabled, } updateTable({ projectRef: project?.ref!, connectionString: project?.connectionString, id: payload.id, schema: table.schema, payload: payload, }) } return ( <>
RLS is enabled for this table, but no policies are set.
Select queries will return an empty array of results.
You can restrict and control who can read, write and update data in this table using Row Level Security.
With RLS enabled, anonymous users will not be able to read/write data in the table.
{!isLocked && (Once realtime has been {isRealtimeEnabled ? 'disabled' : 'enabled'}, the table will{' '} {isRealtimeEnabled ? 'no longer ' : ''}broadcast any changes to authorized subscribers.
{!isRealtimeEnabled && (You may also select which events to broadcast to subscribers on the{' '} database replication {' '} settings.
)}