refactor: use useAsyncCheckPermissionsV2 part 8

This commit is contained in:
phamhieu committed 2026-10-02 12:17:42 +07:00
1 parent a25a84e06b
commit 9b53b97906
29 files changed
+110 -180

No files matched your search

@@ -1,4 +1,3 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useParams } from 'common'
import type { ChangeEvent, ComponentProps, ReactNode } from 'react'
import { useEffect, useRef, useState } from 'react'
@@ -21,11 +20,11 @@ import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
import { PasswordStrengthBar } from '@/components/ui/PasswordStrengthBar'
import { useDatabasePasswordResetMutation } from '@/data/database/database-password-reset-mutation'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useIsProjectActive, useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { useIsProjectActive } from '@/hooks/misc/useSelectedProject'
import { DEFAULT_MINIMUM_PASSWORD_STRENGTH } from '@/lib/constants'
import { passwordStrength, PasswordStrengthScore } from '@/lib/password-strength'
import { generateStrongPassword } from '@/lib/project'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
export type ResetDbPasswordDialogProps = {
disabled?: boolean
@@ -46,16 +45,9 @@ export const ResetDbPasswordDialog = ({
}: ResetDbPasswordDialogProps) => {
const { ref } = useParams()
const isProjectActive = useIsProjectActive()
const { data: project } = useSelectedProjectQuery()
const { can: canResetDbPassword } = useAsyncCheckPermissions(
PermissionAction.UPDATE,
'projects',
{
resource: {
project_id: project?.id,
},
}
const { can: canResetDbPassword } = useAsyncCheckPermissionsV2(
FGA_PERMISSIONS.PROJECT.DATABASE_CONFIG_WRITE
)
const [showResetDbPass, setShowResetDbPass] = useState<boolean>(false)
@@ -1,4 +1,3 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useParams } from 'common'
import { ExternalLink, Info } from 'lucide-react'
import Link from 'next/link'
@@ -21,7 +20,6 @@ import Panel from '@/components/ui/Panel'
import { useProjectDiskResizeMutation } from '@/data/config/project-disk-resize-mutation'
import { useDatabaseSizeQuery } from '@/data/database/database-size-query'
import { useCheckEntitlements } from '@/hooks/misc/useCheckEntitlements'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled'
import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
import {
@@ -31,6 +29,7 @@ import {
} from '@/hooks/misc/useSelectedProject'
import { DOCS_URL } from '@/lib/constants'
import { formatBytes } from '@/lib/helpers'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
export interface DiskSizeConfigurationProps {
disabled?: boolean
@@ -50,14 +49,8 @@ export const DiskSizeConfiguration = ({ disabled = false }: DiskSizeConfiguratio
parseAsBoolean.withDefault(false)
)
const { can: canUpdateDiskSizeConfig } = useAsyncCheckPermissions(
PermissionAction.UPDATE,
'projects',
{
resource: {
project_id: project?.id,
},
}
const { can: canUpdateDiskSizeConfig } = useAsyncCheckPermissionsV2(
FGA_PERMISSIONS.PROJECT.INFRA_DISK_CONFIG_WRITE
)
const { isPending: isUpdatingDiskSize } = useProjectDiskResizeMutation({
@@ -1,4 +1,4 @@
import { PermissionAction, SupportCategories } from '@supabase/shared-types/out/constants'
import { SupportCategories } from '@supabase/shared-types/out/constants'
import { LOCAL_STORAGE_KEYS, useParams } from 'common'
import { Loader2 } from 'lucide-react'
import Link from 'next/link'
@@ -57,10 +57,10 @@ import { useJitDbAccessUpdateMutation } from '@/data/jit-db-access/jit-db-access
import { useOrganizationMembersQuery } from '@/data/organizations/organization-members-query'
import { useProjectMembersQuery } from '@/data/projects/project-members-query'
import { useSSLEnforcementUpdateMutation } from '@/data/ssl-enforcement/ssl-enforcement-update-mutation'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { DOCS_URL } from '@/lib/constants'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
export const JitDbAccessConfiguration = () => {
const { ref } = useParams()
@@ -104,10 +104,8 @@ export const JitDbAccessConfiguration = () => {
connectionString: project?.connectionString,
})
const { can: canUpdateJitDbAccess } = useAsyncCheckPermissions(
PermissionAction.UPDATE,
'projects',
{ resource: { project_id: project?.id } }
const { can: canUpdateJitDbAccess } = useAsyncCheckPermissionsV2(
FGA_PERMISSIONS.PROJECT.ADMIN_WRITE
)
const { mutateAsync: updateJitDbAccess, isPending: isUpdatingJitDbAccess } =
@@ -125,7 +123,7 @@ export const JitDbAccessConfiguration = () => {
)
}
},
onError: () => {},
onError: () => { },
})
const { mutateAsync: enableSSLEnforcement, isPending: isEnablingSSLEnforcement } =
@@ -150,7 +148,7 @@ export const JitDbAccessConfiguration = () => {
setSelectedUserToDelete(null)
if (ruleIdToEdit === variables.userId) resetSheetState()
},
onError: () => {},
onError: () => { },
})
const isMutating = isUpdatingJitDbAccess || isRevokingAccess
@@ -1,4 +1,3 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useParams } from 'common'
import { AlertCircle, ChevronDown, Globe, Lock } from 'lucide-react'
import { useState } from 'react'
@@ -32,10 +31,10 @@ import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
import { DocsButton } from '@/components/ui/DocsButton'
import { HighAvailabilityDisabledSectionNotice } from '@/components/ui/HighAvailability/HighAvailabilityDisabledSectionNotice'
import { useNetworkRestrictionsQuery } from '@/data/network-restrictions/network-restrictions-query'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useHighAvailability } from '@/hooks/misc/useHighAvailability'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { DOCS_URL } from '@/lib/constants'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
const HA_DISABLED_TITLE = 'Network restrictions unavailable on High Availability projects'
const HA_DISABLED_DESCRIPTION =
@@ -93,14 +92,8 @@ export const NetworkRestrictions = () => {
{ projectRef: ref },
{ enabled: Boolean(project) }
)
const { can: canUpdateNetworkRestrictions } = useAsyncCheckPermissions(
PermissionAction.UPDATE,
'projects',
{
resource: {
project_id: project?.id,
},
}
const { can: canUpdateNetworkRestrictions } = useAsyncCheckPermissionsV2(
FGA_PERMISSIONS.PROJECT.DATABASE_NETWORK_RESTRICTIONS_WRITE
)
const isSectionDisabled = isHighAvailability || !canUpdateNetworkRestrictions
@@ -20,8 +20,9 @@ const { mockUseAsyncCheckPermissions, mockUseHighAvailability, mockUseSelectedPr
mockUseSelectedProjectQuery: vi.fn(),
}))
vi.mock('@/hooks/misc/useCheckPermissions', () => ({
useAsyncCheckPermissions: mockUseAsyncCheckPermissions,
vi.mock('@/hooks/misc/useCheckPermissionsV2', () => ({
useAsyncCheckPermissionsV2: mockUseAsyncCheckPermissions,
FGA_PERMISSIONS: { PROJECT: { DATABASE_SSL_CONFIG_WRITE: 'database_ssl_config_write', } },
}))
vi.mock('@/hooks/misc/useHighAvailability', () => ({
@@ -1,4 +1,3 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useParams } from 'common'
import { template } from 'lodash'
import { Download, Loader2 } from 'lucide-react'
@@ -25,14 +24,12 @@ import { useJitDbAccessQuery } from '@/data/jit-db-access/jit-db-access-query'
import { useSSLEnforcementQuery } from '@/data/ssl-enforcement/ssl-enforcement-query'
import { useSSLEnforcementUpdateMutation } from '@/data/ssl-enforcement/ssl-enforcement-update-mutation'
import { useCustomContent } from '@/hooks/custom-content/useCustomContent'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useHighAvailability } from '@/hooks/misc/useHighAvailability'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { DOCS_URL } from '@/lib/constants'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
export const SSLConfiguration = () => {
const { ref } = useParams()
const { data: project } = useSelectedProjectQuery()
const [isConfirmDialogOpen, setIsConfirmDialogOpen] = useState(false)
const { data: settings } = useProjectSettingsV2Query({ projectRef: ref })
@@ -61,14 +58,8 @@ export const SSLConfiguration = () => {
},
})
const { can: canUpdateSSLEnforcement } = useAsyncCheckPermissions(
PermissionAction.UPDATE,
'projects',
{
resource: {
project_id: project?.id,
},
}
const { can: canUpdateSSLEnforcement } = useAsyncCheckPermissionsV2(
FGA_PERMISSIONS.PROJECT.DATABASE_SSL_CONFIG_WRITE
)
// Derived directly from the query so a refetch triggered elsewhere (e.g.
@@ -1,4 +1,3 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useParams } from 'common'
import { Loader2 } from 'lucide-react'
import { useEffect, useState } from 'react'
@@ -18,21 +17,15 @@ import { DocsButton } from '@/components/ui/DocsButton'
import { InlineLink } from '@/components/ui/InlineLink'
import { useComplianceConfigUpdateMutation } from '@/data/config/project-compliance-config-mutation'
import { useProjectSettingsV2Query } from '@/data/config/project-settings-v2-query'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { DOCS_URL } from '@/lib/constants'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
export const ComplianceConfig = () => {
const { ref } = useParams()
const { data: project } = useSelectedProjectQuery()
const [isSensitive, setIsSensitive] = useState(false)
const { can: canUpdateComplianceConfig } = useAsyncCheckPermissions(
PermissionAction.UPDATE,
'projects',
{
resource: { project_id: project?.id },
}
const { can: canUpdateComplianceConfig } = useAsyncCheckPermissionsV2(
FGA_PERMISSIONS.PROJECT.ADMIN_WRITE
)
const {
@@ -1,5 +1,4 @@
import { zodResolver } from '@hookform/resolvers/zod'
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useParams } from 'common'
import { useForm, useWatch } from 'react-hook-form'
import {
@@ -22,9 +21,8 @@ import { DocsButton } from '@/components/ui/DocsButton'
import { useProjectSettingsV2Query } from '@/data/config/project-settings-v2-query'
import { useCheckCNAMERecordMutation } from '@/data/custom-domains/check-cname-mutation'
import { useCustomDomainCreateMutation } from '@/data/custom-domains/custom-domains-create-mutation'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { DOCS_URL } from '@/lib/constants'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
const schema = z.object({
domain: z.string().trim().min(1, 'A value for your custom domain is required'),
@@ -32,21 +30,14 @@ const schema = z.object({
export const CustomDomainsConfigureHostname = () => {
const { ref } = useParams()
const { data: project } = useSelectedProjectQuery()
const { mutate: checkCNAMERecord, isPending: isCheckingRecord } = useCheckCNAMERecordMutation()
const { mutate: createCustomDomain, isPending: isCreating } = useCustomDomainCreateMutation()
const { data: settings } = useProjectSettingsV2Query({ projectRef: ref })
const endpoint = settings?.app_config?.endpoint
const { can: canConfigureCustomDomain } = useAsyncCheckPermissions(
PermissionAction.UPDATE,
'projects',
{
resource: {
project_id: project?.id,
},
}
const { can: canConfigureCustomDomain } = useAsyncCheckPermissionsV2(
FGA_PERMISSIONS.PROJECT.CUSTOM_DOMAIN_WRITE
)
const form = useForm<z.infer<typeof schema>>({
@@ -1,4 +1,3 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useRouter } from 'next/router'
import { useState } from 'react'
import { Alert, AlertDescription, AlertTitle, CriticalIcon } from 'ui'
@@ -15,9 +14,9 @@ import { DeleteBranchModal } from '../../BranchManagement/DeleteBranchModal'
import { SwitchToPreviewModal } from '../../BranchManagement/SwitchToPreviewModal'
import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
import { useBranchesQuery } from '@/data/branches/branches-query'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { useTrack } from '@/lib/telemetry/track'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
export const DeleteBranchPanel = () => {
const router = useRouter()
@@ -30,9 +29,8 @@ export const DeleteBranchPanel = () => {
const [showDeleteModal, setShowDeleteModal] = useState(false)
const [showSwitchToPreviewModal, setShowSwitchToPreviewModal] = useState(false)
const { can: canDeleteBranches } = useAsyncCheckPermissions(
PermissionAction.DELETE,
'preview_branches'
const { can: canDeleteBranches } = useAsyncCheckPermissionsV2(
FGA_PERMISSIONS.PROJECT.BRANCHING_DEVELOPMENT_DELETE
)
const { data: branches } = useBranchesQuery({ projectRef })
@@ -1,22 +1,19 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useState } from 'react'
import { DeleteProjectModal } from './DeleteProjectModal'
import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
export interface DeleteProjectButtonProps {
variant?: 'danger' | 'default'
}
export const DeleteProjectButton = ({ variant = 'danger' }: DeleteProjectButtonProps) => {
const { data: project } = useSelectedProjectQuery()
const [isOpen, setIsOpen] = useState(false)
const { can: canDeleteProject } = useAsyncCheckPermissions(PermissionAction.UPDATE, 'projects', {
resource: { project_id: project?.id },
})
const { can: canDeleteProject } = useAsyncCheckPermissionsV2(
FGA_PERMISSIONS.PROJECT.ADMIN_WRITE
)
return (
<>
@@ -28,8 +28,9 @@ vi.mock('common', async () => {
}
})
vi.mock('@/hooks/misc/useCheckPermissions', () => ({
useAsyncCheckPermissions: mockUseAsyncCheckPermissions,
vi.mock('@/hooks/misc/useCheckPermissionsV2', () => ({
useAsyncCheckPermissionsV2: mockUseAsyncCheckPermissions,
FGA_PERMISSIONS: { PROJECT: { ADMIN_WRITE: 'project_admin_write', } },
}))
vi.mock('@/hooks/misc/useSelectedProject', () => ({
@@ -1,5 +1,4 @@
import { zodResolver } from '@hookform/resolvers/zod'
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { IS_PLATFORM, useParams } from 'common'
import { useForm } from 'react-hook-form'
import { toast } from 'sonner'
@@ -23,10 +22,10 @@ import { DocsButton } from '@/components/ui/DocsButton'
import { InlineLink } from '@/components/ui/InlineLink'
import { useBranchesQuery } from '@/data/branches/branches-query'
import { useProjectUpdateMutation } from '@/data/projects/project-update-mutation'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useDeploymentMode } from '@/hooks/misc/useDeploymentMode'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { DOCS_URL } from '@/lib/constants'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
export const General = () => {
const { ref } = useParams()
@@ -41,11 +40,9 @@ export const General = () => {
const branch = branches?.find((x) => x.project_ref === ref)
const projectName = isBranch ? branch?.name : project?.name
const { can: canUpdateProject } = useAsyncCheckPermissions(PermissionAction.UPDATE, 'projects', {
resource: {
project_id: project?.id,
},
})
const { can: canUpdateProject } = useAsyncCheckPermissionsV2(
FGA_PERMISSIONS.PROJECT.ADMIN_WRITE
)
const { mutate: updateProject, isPending: isUpdating } = useProjectUpdateMutation()
@@ -22,8 +22,9 @@ vi.mock('@/hooks/misc/useCheckEntitlements', () => ({
useCheckEntitlements: mockUseCheckEntitlements,
}))
vi.mock('@/hooks/misc/useCheckPermissions', () => ({
useAsyncCheckPermissions: mockUseAsyncCheckPermissions,
vi.mock('@/hooks/misc/useCheckPermissionsV2', () => ({
useAsyncCheckPermissionsV2: mockUseAsyncCheckPermissions,
FGA_PERMISSIONS: { PROJECT: { ADMIN_WRITE: 'project_admin_write', } },
}))
vi.mock('@/hooks/misc/useSelectedOrganization', () => ({
@@ -1,4 +1,3 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { CirclePause } from 'lucide-react'
import { useRouter } from 'next/router'
import { useState } from 'react'
@@ -18,7 +17,6 @@ import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
import { useSetProjectStatus } from '@/data/projects/project-detail-query'
import { useProjectPauseMutation } from '@/data/projects/project-pause-mutation'
import { useCheckEntitlements } from '@/hooks/misc/useCheckEntitlements'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
import {
useIsHighAvailability,
@@ -26,6 +24,7 @@ import {
useSelectedProjectQuery,
} from '@/hooks/misc/useSelectedProject'
import { PROJECT_STATUS } from '@/lib/constants'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
export const PauseProjectButton = () => {
const router = useRouter()
@@ -40,9 +39,8 @@ export const PauseProjectButton = () => {
const projectRef = project?.ref ?? ''
const isPaused = project?.status === PROJECT_STATUS.INACTIVE
const { can: canPauseProject } = useAsyncCheckPermissions(
PermissionAction.INFRA_EXECUTE,
'queue_jobs.projects.pause'
const { can: canPauseProject } = useAsyncCheckPermissionsV2(
[FGA_PERMISSIONS.PROJECT.ADMIN_WRITE]
)
const isFreePlan = organization?.plan.id === 'free'
@@ -26,8 +26,9 @@ vi.mock('next/router', () => ({
useRouter: () => ({ push: vi.fn() }),
}))
vi.mock('@/hooks/misc/useCheckPermissions', () => ({
useAsyncCheckPermissions: mockUseAsyncCheckPermissions,
vi.mock('@/hooks/misc/useCheckPermissionsV2', () => ({
useAsyncCheckPermissionsV2: mockUseAsyncCheckPermissions,
FGA_PERMISSIONS: {},
}))
vi.mock('@/hooks/misc/useIsFeatureEnabled', () => ({
@@ -1,4 +1,3 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useFlag } from 'common'
import { ChevronDown, RefreshCw } from 'lucide-react'
import { useRouter } from 'next/router'
@@ -18,11 +17,11 @@ import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
import { useSetProjectStatus } from '@/data/projects/project-detail-query'
import { useProjectRestartMutation } from '@/data/projects/project-restart-mutation'
import { useProjectRestartServicesMutation } from '@/data/projects/project-restart-services-mutation'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled'
import { useIsProjectActive, useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { PROJECT_STATUS } from '@/lib/constants'
import { type ResponseError } from '@/types'
import { useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
export const RestartServerButton = () => {
const router = useRouter()
@@ -45,9 +44,8 @@ export const RestartServerButton = () => {
const projectRegion = project?.region ?? ''
const projectRestartDisabled = useFlag('disableProjectRestarts')
const { can: canRestartProject } = useAsyncCheckPermissions(
PermissionAction.INFRA_EXECUTE,
'reboot'
const { can: canRestartProject } = useAsyncCheckPermissionsV2(
'project_operations_write'
)
const { mutate: restartProject, isPending: isRestartingProject } = useProjectRestartMutation({
@@ -1,4 +1,3 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useQueryClient } from '@tanstack/react-query'
import { useFlag } from 'common'
import { Loader, Shield, Wrench } from 'lucide-react'
@@ -32,9 +31,9 @@ import { useOrganizationsQuery } from '@/data/organizations/organizations-query'
import { projectKeys } from '@/data/projects/keys'
import { useProjectTransferMutation } from '@/data/projects/project-transfer-mutation'
import { useProjectTransferPreviewQuery } from '@/data/projects/project-transfer-preview-query'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { DOCS_URL } from '@/lib/constants'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
export const TransferProjectButton = () => {
const { data: project } = useSelectedProjectQuery()
@@ -83,9 +82,8 @@ export const TransferProjectButton = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isOpen])
const { can: canTransferProject } = useAsyncCheckPermissions(
PermissionAction.UPDATE,
'organizations'
const { can: canTransferProject } = useAsyncCheckPermissionsV2(
[FGA_PERMISSIONS.PROJECT.ADMIN_WRITE, FGA_PERMISSIONS.ORGANIZATION.ADMIN_WRITE]
)
async function handleTransferProject() {
@@ -1,5 +1,4 @@
import { zodResolver } from '@hookform/resolvers/zod'
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { AnimatePresence, motion } from 'framer-motion'
import { Loader2 } from 'lucide-react'
import { useEffect, useState } from 'react'
@@ -37,10 +36,10 @@ import { useGitHubConnectionDeleteMutation } from '@/data/integrations/github-co
import { useGitHubConnectionUpdateMutation } from '@/data/integrations/github-connection-update-mutation'
import type { GitHubConnection } from '@/data/integrations/integrations.types'
import { useCheckEntitlements } from '@/hooks/misc/useCheckEntitlements'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { DOCS_URL } from '@/lib/constants'
import { useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
interface GitHubIntegrationConnectionFormProps {
connection?: GitHubConnection
@@ -60,13 +59,11 @@ export const GitHubIntegrationConnectionForm = ({
const { hasAccess: hasAccessToBranching } = useCheckEntitlements('branching_limit')
const { can: canUpdateGitHubConnection } = useAsyncCheckPermissions(
PermissionAction.UPDATE,
'integrations.github_connections'
const { can: canUpdateGitHubConnection } = useAsyncCheckPermissionsV2(
'organization_integrations_write'
)
const { can: canCreateGitHubConnection } = useAsyncCheckPermissions(
PermissionAction.CREATE,
'integrations.github_connections'
const { can: canCreateGitHubConnection } = useAsyncCheckPermissionsV2(
'organization_integrations_write'
)
const {
@@ -1,4 +1,3 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useParams } from 'common'
import { Plus } from 'lucide-react'
import { useRouter } from 'next/router'
@@ -30,7 +29,6 @@ import {
type GitHubConnection,
} from '@/data/integrations/github-connections-query'
import type { IntegrationProjectConnection } from '@/data/integrations/integrations.types'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
import {
GITHUB_INTEGRATION_INSTALLATION_URL,
@@ -38,6 +36,7 @@ import {
} from '@/lib/github'
import { SHORTCUT_IDS } from '@/state/shortcuts/registry'
import { useShortcut } from '@/state/shortcuts/useShortcut'
import { useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
const toIntegrationProjectConnection = (
connection: GitHubConnection
@@ -64,14 +63,12 @@ export const GitHubSection = ({ isProjectScoped }: { isProjectScoped: boolean })
const { data: org } = useSelectedOrganizationQuery()
const { can: canReadGitHubConnection, isLoading: isLoadingPermissions } =
useAsyncCheckPermissions(PermissionAction.READ, 'integrations.github_connections')
const { can: canCreateGitHubConnection } = useAsyncCheckPermissions(
PermissionAction.CREATE,
'integrations.github_connections'
useAsyncCheckPermissionsV2('organization_integrations_read')
const { can: canCreateGitHubConnection } = useAsyncCheckPermissionsV2(
'organization_integrations_write'
)
const { can: canUpdateGitHubConnection } = useAsyncCheckPermissions(
PermissionAction.UPDATE,
'integrations.github_connections'
const { can: canUpdateGitHubConnection } = useAsyncCheckPermissionsV2(
'organization_integrations_write'
)
const { data: gitHubAuthorization } = useGitHubAuthorizationQuery({
@@ -1,4 +1,3 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { ExternalLink } from 'lucide-react'
import { useCallback, useMemo } from 'react'
import { toast } from 'sonner'
@@ -31,12 +30,12 @@ import type {
IntegrationName,
IntegrationProjectConnection,
} from '@/data/integrations/integrations.types'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { pluralize } from '@/lib/helpers'
import { getIntegrationConfigurationUrl } from '@/lib/integration-utils'
import { useSidePanelsStateSnapshot } from '@/state/side-panels'
import { useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
export const VercelSection = ({ isProjectScoped }: { isProjectScoped: boolean }) => {
const { data: project } = useSelectedProjectQuery()
@@ -46,14 +45,12 @@ export const VercelSection = ({ isProjectScoped }: { isProjectScoped: boolean })
const isBranch = project?.parent_project_ref !== undefined
const { can: canReadVercelConnection, isLoading: isLoadingPermissions } =
useAsyncCheckPermissions(PermissionAction.READ, 'integrations.vercel_connections')
const { can: canCreateVercelConnection } = useAsyncCheckPermissions(
PermissionAction.CREATE,
'integrations.vercel_connections'
useAsyncCheckPermissionsV2('organization_integrations_read')
const { can: canCreateVercelConnection } = useAsyncCheckPermissionsV2(
'organization_integrations_write'
)
const { can: canUpdateVercelConnection } = useAsyncCheckPermissions(
PermissionAction.UPDATE,
'integrations.vercel_connections'
const { can: canUpdateVercelConnection } = useAsyncCheckPermissionsV2(
'organization_integrations_write'
)
const { mutate: deleteVercelConnection } = useIntegrationsVercelInstalledConnectionDeleteMutation(
@@ -1,4 +1,3 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { IS_PLATFORM, useParams } from 'common'
import { Copy, Eye, EyeOff, Play } from 'lucide-react'
import { Key, ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react'
@@ -42,11 +41,10 @@ import { MultiSelectActionBar, type LogCopyFormat } from './MultiSelectActionBar
import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
import { DownloadResultsButton } from '@/components/ui/DownloadResultsButton'
import { useSelectedLog } from '@/hooks/analytics/useSelectedLog'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useProfile } from '@/lib/profile'
import { SHORTCUT_IDS } from '@/state/shortcuts/registry'
import { useShortcut } from '@/state/shortcuts/useShortcut'
import type { ResponseError } from '@/types'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
interface Props {
data?: LogData[]
@@ -103,7 +101,6 @@ export const LogTable = ({
columnRenderers,
}: Props) => {
const { ref } = useParams()
const { profile } = useProfile()
const [selectedLogId] = useSelectedLog()
const [selectedRow, setSelectedRow] = useState<LogData | null>(null)
const [selectedRows, setSelectedRows] = useState<Set<string>>(new Set())
@@ -132,13 +129,8 @@ export const LogTable = ({
)
}, [])
const { can: canCreateLogQuery } = useAsyncCheckPermissions(
PermissionAction.CREATE,
'user_content',
{
resource: { type: 'log_sql', owner_id: profile?.id },
subject: { id: profile?.id },
}
const { can: canCreateLogQuery } = useAsyncCheckPermissionsV2(
FGA_PERMISSIONS.PROJECT.SNIPPETS_WRITE
)
const firstRow = data[0]
@@ -1,4 +1,3 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { Card } from 'ui'
import { Admonition } from 'ui-patterns/Admonition'
@@ -19,13 +18,16 @@ import {
import { InlineLink } from '@/components/ui/InlineLink'
import { useAPIKeys } from '@/data/api-keys/api-keys-query'
import { useVaultSecretDecryptedValueQuery } from '@/data/vault/vault-secret-decrypted-value-query'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { DOCS_URL } from '@/lib/constants'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
export const SimpleConfigurationDetails = ({ bucketName }: { bucketName?: string }) => {
const { data: project } = useSelectedProjectQuery()
const { can: canReadAPIKeys } = useAsyncCheckPermissions(PermissionAction.SECRETS_READ, '*')
const { can: canReadAPIKeys } = useAsyncCheckPermissionsV2([
FGA_PERMISSIONS.PROJECT.API_GATEWAY_KEYS_READ,
FGA_PERMISSIONS.PROJECT.API_GATEWAY_KEYS_SECRET_READ
])
const integration = INTEGRATIONS.find((i) => i.id === 'iceberg_wrapper' && i.type === 'wrapper')
const wrapperMeta = (integration?.type === 'wrapper' && integration.meta) as WrapperMeta
@@ -1,4 +1,3 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useQueryClient } from '@tanstack/react-query'
import { useParams } from 'common'
import { useEffect, useState } from 'react'
@@ -29,14 +28,17 @@ import { useAPIKeys } from '@/data/api-keys/api-keys-query'
import { fdwKeys } from '@/data/fdw/keys'
import { vaultSecretsKeys } from '@/data/vault/keys'
import { useVaultSecretUpdateMutation } from '@/data/vault/vault-secret-update-mutation'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
export const UpdateCatalogTokenDialog = ({ vaultTokenId }: { vaultTokenId?: string }) => {
const { ref } = useParams()
const queryClient = useQueryClient()
const { data: project } = useSelectedProjectQuery()
const { can: canReadAPIKeys } = useAsyncCheckPermissions(PermissionAction.SECRETS_READ, '*')
const { can: canReadAPIKeys } = useAsyncCheckPermissionsV2([
FGA_PERMISSIONS.PROJECT.API_GATEWAY_KEYS_READ,
FGA_PERMISSIONS.PROJECT.API_GATEWAY_KEYS_SECRET_READ
])
const [open, setOpen] = useState(false)
const [selectedKey, setSelectedKey] = useState<string>()
@@ -1,5 +1,3 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import {
getAnalyticsBucketPublicationName,
getAnalyticsBucketS3KeyName,
@@ -15,8 +13,8 @@ import { useReplicationPublicationQuery } from '@/data/replication/publication-q
import { useReplicationSourcesQuery } from '@/data/replication/sources-query'
import { useS3AccessKeyDeleteMutation } from '@/data/storage/s3-access-key-delete-mutation'
import { useStorageCredentialsQuery } from '@/data/storage/s3-access-key-query'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
/**
* Returns all the data that's associated to a specified analytics bucket (e.g publications, S3 keys, etc)
@@ -26,9 +24,8 @@ export const useAnalyticsBucketAssociatedEntities = (
{ projectRef, bucketId }: { projectRef?: string; bucketId?: string },
options: { enabled: boolean } = { enabled: true }
) => {
const { can: canReadS3Credentials } = useAsyncCheckPermissions(
PermissionAction.STORAGE_ADMIN_READ,
'*'
const { can: canReadS3Credentials } = useAsyncCheckPermissionsV2(
FGA_PERMISSIONS.PROJECT.STORAGE_CONFIG_READ
)
const {
@@ -1,4 +1,3 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useQueryClient } from '@tanstack/react-query'
import { useDebounce } from '@uidotdev/usehooks'
import { useParams } from 'common'
@@ -21,9 +20,9 @@ import { InfiniteListDefault, LoaderForIconMenuItems } from '@/components/ui/Inf
import { useProjectApiUrl } from '@/data/config/project-endpoint-query'
import { useBucketObjectsInfiniteQuery } from '@/data/storage/bucket-objects-infinite-query'
import { storageKeys } from '@/data/storage/keys'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { formatBytes } from '@/lib/helpers'
import { noop } from '@/lib/void'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
const SelectAllCheckbox = ({
columnFiles,
@@ -103,7 +102,9 @@ export const BucketFilePickerColumn = ({
const columnRef = useRef<HTMLDivElement | null>(null)
const { hostEndpoint } = useProjectApiUrl({ projectRef: projectRef! })
const { can: canUpdateStorage } = useAsyncCheckPermissions(PermissionAction.STORAGE_WRITE, '*')
const { can: canUpdateStorage } = useAsyncCheckPermissionsV2(
FGA_PERMISSIONS.PROJECT.STORAGE_WRITE
)
const {
columns,
@@ -1,4 +1,3 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useQueryClient } from '@tanstack/react-query'
import { useParams } from 'common'
import {
@@ -33,7 +32,7 @@ import { useBucketFilePickerStateSnapshot } from './BucketFilePickerState'
import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
import { useProjectApiUrl } from '@/data/config/project-endpoint-query'
import { storageKeys } from '@/data/storage/keys'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
const VIEW_OPTIONS = [
{ key: STORAGE_VIEWS.COLUMNS, name: 'As columns' },
@@ -137,7 +136,9 @@ export const BucketFilePickerHeader = () => {
setSelectedFilePreview,
} = useBucketFilePickerStateSnapshot()
const { can: canUpdateStorage } = useAsyncCheckPermissions(PermissionAction.STORAGE_WRITE, '*')
const { can: canUpdateStorage } = useAsyncCheckPermissionsV2(
FGA_PERMISSIONS.PROJECT.STORAGE_WRITE
)
const breadcrumbs = columns
const backDisabled = columns.length < 1
@@ -1,10 +1,9 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { Dispatch, RefObject, SetStateAction } from 'react'
import { STORAGE_BUCKET_SORT } from '../Storage.constants'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { SHORTCUT_IDS } from '@/state/shortcuts/registry'
import { useShortcut } from '@/state/shortcuts/useShortcut'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
interface UseFilesBucketsShortcutsParams {
searchInputRef: RefObject<HTMLInputElement | null>
@@ -23,7 +22,9 @@ export function useFilesBucketsShortcuts({
setCreateVisible,
onRefresh,
}: UseFilesBucketsShortcutsParams) {
const { can: canCreateBuckets } = useAsyncCheckPermissions(PermissionAction.STORAGE_WRITE, '*')
const { can: canCreateBuckets } = useAsyncCheckPermissionsV2(
FGA_PERMISSIONS.PROJECT.STORAGE_WRITE
)
useShortcut(
SHORTCUT_IDS.LIST_PAGE_FOCUS_SEARCH,
@@ -1,16 +1,17 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { Plus } from 'lucide-react'
import { MouseEventHandler } from 'react'
import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
export const CreateBucketButton = ({
onClick,
}: {
onClick: MouseEventHandler<HTMLButtonElement>
}) => {
const { can: canCreateBuckets } = useAsyncCheckPermissions(PermissionAction.STORAGE_WRITE, '*')
const { can: canCreateBuckets } = useAsyncCheckPermissionsV2(
FGA_PERMISSIONS.PROJECT.STORAGE_WRITE
)
return (
<ButtonTooltip
@@ -1,4 +1,3 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { AnimatePresence, motion } from 'framer-motion'
import { get, noop, sum, uniqBy } from 'lodash'
import { ChevronsDown, ChevronsUp, Copy, Eye, FolderPlus, Upload } from 'lucide-react'
@@ -30,10 +29,10 @@ import { FileExplorerRow } from './FileExplorerRow'
import { FileExplorerRowContextMenuProvider } from './FileExplorerRowContextMenu'
import { useStoragePreference } from './useStoragePreference'
import { InfiniteListDefault, LoaderForIconMenuItems } from '@/components/ui/InfiniteList'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { BASE_PATH } from '@/lib/constants'
import { formatBytes } from '@/lib/helpers'
import { useStorageExplorerStateSnapshot } from '@/state/storage-explorer'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
const DragOverOverlay = ({ isOpen, onDragLeave, onDrop, folderIsEmpty }: any) => {
return (
@@ -98,7 +97,9 @@ export const FileExplorerColumn = ({
const snap = useStorageExplorerStateSnapshot()
const { view, setSortByOrder, setSortBy, setView } = useStoragePreference(snap.projectRef)
const { can: canUpdateStorage } = useAsyncCheckPermissions(PermissionAction.STORAGE_WRITE, '*')
const { can: canUpdateStorage } = useAsyncCheckPermissionsV2(
FGA_PERMISSIONS.PROJECT.STORAGE_WRITE
)
useEffect(() => {
if (fileExplorerColumnRef) {