mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 17:35:10 +03:00
Merge pull request #9158 from supabase/chore/fix-policy-editor
Improve policy page empty state
This commit is contained in:
3 files changed
+73
-31
No files matched your search
@@ -147,7 +147,8 @@ export const createPayloadForUpdatePolicy = (
|
||||
payload.check = formattedPolicyFormFields.check || undefined
|
||||
}
|
||||
if (!isEqual(formattedPolicyFormFields.roles, originalPolicyFormFields.roles)) {
|
||||
payload.roles = formattedPolicyFormFields.roles || undefined
|
||||
if (formattedPolicyFormFields.roles.length === 0) payload.roles = ['public']
|
||||
else payload.roles = formattedPolicyFormFields.roles || undefined
|
||||
}
|
||||
|
||||
return payload
|
||||
|
||||
@@ -4,6 +4,7 @@ import * as Tooltip from '@radix-ui/react-tooltip'
|
||||
|
||||
interface Props {
|
||||
title?: string
|
||||
size?: 'medium' | 'large'
|
||||
children?: ReactNode
|
||||
ctaButtonLabel?: string
|
||||
infoButtonLabel?: string
|
||||
@@ -15,6 +16,7 @@ interface Props {
|
||||
|
||||
const ProductEmptyState: FC<Props> = ({
|
||||
title = '',
|
||||
size = 'medium',
|
||||
children,
|
||||
ctaButtonLabel = '',
|
||||
infoButtonLabel = '',
|
||||
@@ -30,7 +32,7 @@ const ProductEmptyState: FC<Props> = ({
|
||||
<div className="flex space-x-4 p-6 rounded border border-panel-border-light dark:border-panel-border-dark bg-panel-body-light dark:bg-panel-body-dark shadow-md">
|
||||
{/* A graphic can probably be placed here as a sibling to the div below*/}
|
||||
<div className="flex flex-col">
|
||||
<div className="w-80 space-y-4">
|
||||
<div className={`${size === 'medium' ? 'w-80' : 'w-[400px]'} space-y-4`}>
|
||||
<h5>{title}</h5>
|
||||
<div className="flex flex-col space-y-2">{children}</div>
|
||||
{hasAction && (
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useState, PropsWithChildren, FC } from 'react'
|
||||
import React, { useState, FC } from 'react'
|
||||
import { isEmpty } from 'lodash'
|
||||
import { Button, IconSearch, Input } from '@supabase/ui'
|
||||
import { useRouter } from 'next/router'
|
||||
import { Button, IconHelpCircle, IconSearch, Input } from '@supabase/ui'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
import { checkPermissions, useStore } from 'hooks'
|
||||
import { AuthLayout } from 'components/layouts'
|
||||
@@ -14,6 +15,8 @@ import NoTableState from 'components/ui/States/NoTableState'
|
||||
import NoSearchResults from 'components/to-be-cleaned/NoSearchResults'
|
||||
import { PermissionAction } from '@supabase/shared-types/out/constants'
|
||||
import NoPermission from 'components/ui/NoPermission'
|
||||
import ProductEmptyState from 'components/to-be-cleaned/ProductEmptyState'
|
||||
import InformationBox from 'components/ui/InformationBox'
|
||||
|
||||
/**
|
||||
* Filter tables by table name and policy name
|
||||
@@ -50,6 +53,7 @@ const onFilterTables = (
|
||||
|
||||
const AuthPoliciesPage: NextPageWithLayout = () => {
|
||||
const { meta } = useStore()
|
||||
|
||||
const [policiesFilter, setPoliciesFilter] = useState<string | undefined>(undefined)
|
||||
const publicTables = meta.tables.list((table: { schema: string }) => table.schema === 'public')
|
||||
const policies = meta.policies.list()
|
||||
@@ -62,31 +66,31 @@ const AuthPoliciesPage: NextPageWithLayout = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="mb-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<Input
|
||||
size="small"
|
||||
placeholder="Filter tables and policies"
|
||||
className="block w-64 text-sm placeholder-gray-400"
|
||||
value={policiesFilter}
|
||||
onChange={(e) => setPoliciesFilter(e.target.value)}
|
||||
icon={<IconSearch size="tiny" />}
|
||||
/>
|
||||
<Button type="link">
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://supabase.com/docs/learn/auth-deep-dive/auth-row-level-security"
|
||||
>
|
||||
What is RLS?
|
||||
</a>
|
||||
</Button>
|
||||
<div className="flex flex-col h-full">
|
||||
{(publicTables || []).length > 0 && (
|
||||
<div className="mb-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<Input
|
||||
size="small"
|
||||
placeholder="Filter tables and policies"
|
||||
className="block w-64 text-sm placeholder-gray-400"
|
||||
value={policiesFilter}
|
||||
onChange={(e) => setPoliciesFilter(e.target.value)}
|
||||
icon={<IconSearch size="tiny" />}
|
||||
/>
|
||||
<Button type="link">
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://supabase.com/docs/learn/auth-deep-dive/auth-row-level-security"
|
||||
>
|
||||
What is RLS?
|
||||
</a>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<AuthPoliciesTables hasPublicTables={publicTables.length > 0} tables={filteredTables} />
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<AuthPoliciesTables hasPublicTables={publicTables.length > 0} tables={filteredTables} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -103,6 +107,9 @@ interface AuthPoliciesTablesProps {
|
||||
tables: any[]
|
||||
}
|
||||
const AuthPoliciesTables: FC<AuthPoliciesTablesProps> = observer(({ tables, hasPublicTables }) => {
|
||||
const router = useRouter()
|
||||
const { ref } = router.query
|
||||
|
||||
const { ui, meta } = useStore()
|
||||
const roles = meta.roles.list((role: PostgresRole) => !meta.roles.systemRoles.includes(role.name))
|
||||
|
||||
@@ -198,7 +205,7 @@ const AuthPoliciesTables: FC<AuthPoliciesTablesProps> = observer(({ tables, hasP
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
{tables.length > 0 ? (
|
||||
tables.map((table: any) => (
|
||||
<section key={table.id}>
|
||||
@@ -214,7 +221,39 @@ const AuthPoliciesTables: FC<AuthPoliciesTablesProps> = observer(({ tables, hasP
|
||||
) : hasPublicTables ? (
|
||||
<NoSearchResults />
|
||||
) : (
|
||||
<NoTableState message="A public schema table is required before you can create a row-level security policy" />
|
||||
<div className="flex-grow">
|
||||
<ProductEmptyState
|
||||
size="large"
|
||||
title="Postgres Policies"
|
||||
ctaButtonLabel="Create a table"
|
||||
infoButtonLabel="What is RLS?"
|
||||
infoButtonUrl="https://supabase.com/docs/guides/auth/row-level-security"
|
||||
onClickCta={() => router.push(`/project/${ref}/editor`)}
|
||||
>
|
||||
<div className="space-y-4">
|
||||
<InformationBox
|
||||
title="What are policies?"
|
||||
icon={<IconHelpCircle strokeWidth={2} />}
|
||||
description={
|
||||
<div className="space-y-2">
|
||||
<p className="text-sm">
|
||||
Policies restrict, on a per-user basis, which rows can be returned by normal
|
||||
queries, or inserted, updated, or deleted by data modification commands.
|
||||
</p>
|
||||
<p className="text-sm">
|
||||
This is also known as Row-Level Security (RLS). Each policy is attached to a
|
||||
table, and the policy is executed everytime a time is accessed.
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
<p className="text-sm text-scale-1100">
|
||||
A table within the public schema is required before you can create a Row-Level
|
||||
Security policy.
|
||||
</p>
|
||||
</div>
|
||||
</ProductEmptyState>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<PolicyEditorModal
|
||||
@@ -254,6 +293,6 @@ const AuthPoliciesTables: FC<AuthPoliciesTablesProps> = observer(({ tables, hasP
|
||||
onSelectCancel={closeConfirmModal}
|
||||
onSelectConfirm={onToggleRLS}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
})
|
||||
Reference in new issue
Block a user