From 9b53b97906c76ff934baaf641148d16233c3635f Mon Sep 17 00:00:00 2001 From: phamhieu Date: Fri, 2 Oct 2026 12:17:42 +0700 Subject: [PATCH] refactor: use useAsyncCheckPermissionsV2 part 8 --- .../DatabaseSettings/ResetDbPasswordDialog.tsx | 16 ++++------------ .../Settings/Database/DiskSizeConfiguration.tsx | 13 +++---------- .../JitDbAccessConfiguration.tsx | 14 ++++++-------- .../NetworkRestrictions/NetworkRestrictions.tsx | 13 +++---------- .../Settings/Database/SSLConfiguration.test.tsx | 5 +++-- .../Settings/Database/SSLConfiguration.tsx | 15 +++------------ .../ComplianceConfig/ProjectComplianceMode.tsx | 13 +++---------- .../CustomDomainsConfigureHostname.tsx | 15 +++------------ .../Settings/General/DeleteBranchPanel.tsx | 8 +++----- .../DeleteProjectPanel/DeleteProjectButton.tsx | 11 ++++------- .../interfaces/Settings/General/General.test.tsx | 5 +++-- .../interfaces/Settings/General/General.tsx | 11 ++++------- .../Infrastructure/PauseProjectButton.test.tsx | 5 +++-- .../Infrastructure/PauseProjectButton.tsx | 8 +++----- .../Infrastructure/RestartServerButton.test.tsx | 5 +++-- .../Infrastructure/RestartServerButton.tsx | 8 +++----- .../TransferProjectButton.tsx | 8 +++----- .../GitHubIntegrationConnectionForm.tsx | 13 +++++-------- .../GithubIntegration/GithubSection.tsx | 15 ++++++--------- .../VercelIntegration/VercelSection.tsx | 15 ++++++--------- .../interfaces/Settings/Logs/LogTable.tsx | 14 +++----------- .../SimpleConfigurationDetails.tsx | 8 +++++--- .../UpdateCatalogTokenDialog.tsx | 8 +++++--- .../useAnalyticsBucketAssociatedEntities.tsx | 9 +++------ .../BucketFilePickerColumn.tsx | 7 ++++--- .../BucketFilePickerHeader.tsx | 7 ++++--- .../FilesBuckets/useFilesBucketsShortcuts.ts | 7 ++++--- .../interfaces/Storage/NewBucketButton.tsx | 7 ++++--- .../StorageExplorer/FileExplorerColumn.tsx | 7 ++++--- 29 files changed, 110 insertions(+), 180 deletions(-) diff --git a/apps/studio/components/interfaces/Settings/Database/DatabaseSettings/ResetDbPasswordDialog.tsx b/apps/studio/components/interfaces/Settings/Database/DatabaseSettings/ResetDbPasswordDialog.tsx index 9e64e5a1107..e9406b21a3c 100644 --- a/apps/studio/components/interfaces/Settings/Database/DatabaseSettings/ResetDbPasswordDialog.tsx +++ b/apps/studio/components/interfaces/Settings/Database/DatabaseSettings/ResetDbPasswordDialog.tsx @@ -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(false) diff --git a/apps/studio/components/interfaces/Settings/Database/DiskSizeConfiguration.tsx b/apps/studio/components/interfaces/Settings/Database/DiskSizeConfiguration.tsx index 800dce887ae..65e9600adbe 100644 --- a/apps/studio/components/interfaces/Settings/Database/DiskSizeConfiguration.tsx +++ b/apps/studio/components/interfaces/Settings/Database/DiskSizeConfiguration.tsx @@ -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({ diff --git a/apps/studio/components/interfaces/Settings/Database/JitDatabaseAccess/JitDbAccessConfiguration.tsx b/apps/studio/components/interfaces/Settings/Database/JitDatabaseAccess/JitDbAccessConfiguration.tsx index 1bb16ef0642..f4fc762c88d 100644 --- a/apps/studio/components/interfaces/Settings/Database/JitDatabaseAccess/JitDbAccessConfiguration.tsx +++ b/apps/studio/components/interfaces/Settings/Database/JitDatabaseAccess/JitDbAccessConfiguration.tsx @@ -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 diff --git a/apps/studio/components/interfaces/Settings/Database/NetworkRestrictions/NetworkRestrictions.tsx b/apps/studio/components/interfaces/Settings/Database/NetworkRestrictions/NetworkRestrictions.tsx index 9c35cc0edcd..bf40d2a618c 100644 --- a/apps/studio/components/interfaces/Settings/Database/NetworkRestrictions/NetworkRestrictions.tsx +++ b/apps/studio/components/interfaces/Settings/Database/NetworkRestrictions/NetworkRestrictions.tsx @@ -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 diff --git a/apps/studio/components/interfaces/Settings/Database/SSLConfiguration.test.tsx b/apps/studio/components/interfaces/Settings/Database/SSLConfiguration.test.tsx index c13f810e32e..94c10a43904 100644 --- a/apps/studio/components/interfaces/Settings/Database/SSLConfiguration.test.tsx +++ b/apps/studio/components/interfaces/Settings/Database/SSLConfiguration.test.tsx @@ -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', () => ({ diff --git a/apps/studio/components/interfaces/Settings/Database/SSLConfiguration.tsx b/apps/studio/components/interfaces/Settings/Database/SSLConfiguration.tsx index 0714bfee41c..83060e0ef0b 100644 --- a/apps/studio/components/interfaces/Settings/Database/SSLConfiguration.tsx +++ b/apps/studio/components/interfaces/Settings/Database/SSLConfiguration.tsx @@ -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. diff --git a/apps/studio/components/interfaces/Settings/General/ComplianceConfig/ProjectComplianceMode.tsx b/apps/studio/components/interfaces/Settings/General/ComplianceConfig/ProjectComplianceMode.tsx index a5213b1b05a..0dcd71e2a7f 100644 --- a/apps/studio/components/interfaces/Settings/General/ComplianceConfig/ProjectComplianceMode.tsx +++ b/apps/studio/components/interfaces/Settings/General/ComplianceConfig/ProjectComplianceMode.tsx @@ -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 { diff --git a/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainsConfigureHostname.tsx b/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainsConfigureHostname.tsx index 4023f63a96b..11312734b91 100644 --- a/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainsConfigureHostname.tsx +++ b/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainsConfigureHostname.tsx @@ -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>({ diff --git a/apps/studio/components/interfaces/Settings/General/DeleteBranchPanel.tsx b/apps/studio/components/interfaces/Settings/General/DeleteBranchPanel.tsx index 7521c5556a4..f50abcb540d 100644 --- a/apps/studio/components/interfaces/Settings/General/DeleteBranchPanel.tsx +++ b/apps/studio/components/interfaces/Settings/General/DeleteBranchPanel.tsx @@ -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 }) diff --git a/apps/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectButton.tsx b/apps/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectButton.tsx index e0a3f990864..5690a73e018 100644 --- a/apps/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectButton.tsx +++ b/apps/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectButton.tsx @@ -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 ( <> diff --git a/apps/studio/components/interfaces/Settings/General/General.test.tsx b/apps/studio/components/interfaces/Settings/General/General.test.tsx index f62e3eb3be6..6624736a08b 100644 --- a/apps/studio/components/interfaces/Settings/General/General.test.tsx +++ b/apps/studio/components/interfaces/Settings/General/General.test.tsx @@ -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', () => ({ diff --git a/apps/studio/components/interfaces/Settings/General/General.tsx b/apps/studio/components/interfaces/Settings/General/General.tsx index 695b27d8f89..89fb3c5921f 100644 --- a/apps/studio/components/interfaces/Settings/General/General.tsx +++ b/apps/studio/components/interfaces/Settings/General/General.tsx @@ -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() diff --git a/apps/studio/components/interfaces/Settings/General/Infrastructure/PauseProjectButton.test.tsx b/apps/studio/components/interfaces/Settings/General/Infrastructure/PauseProjectButton.test.tsx index 9b6dc5a51f3..f7d11ffcb20 100644 --- a/apps/studio/components/interfaces/Settings/General/Infrastructure/PauseProjectButton.test.tsx +++ b/apps/studio/components/interfaces/Settings/General/Infrastructure/PauseProjectButton.test.tsx @@ -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', () => ({ diff --git a/apps/studio/components/interfaces/Settings/General/Infrastructure/PauseProjectButton.tsx b/apps/studio/components/interfaces/Settings/General/Infrastructure/PauseProjectButton.tsx index 3ee6613ef22..c024fa63666 100644 --- a/apps/studio/components/interfaces/Settings/General/Infrastructure/PauseProjectButton.tsx +++ b/apps/studio/components/interfaces/Settings/General/Infrastructure/PauseProjectButton.tsx @@ -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' diff --git a/apps/studio/components/interfaces/Settings/General/Infrastructure/RestartServerButton.test.tsx b/apps/studio/components/interfaces/Settings/General/Infrastructure/RestartServerButton.test.tsx index 9f73d09524b..df0d02c0b4b 100644 --- a/apps/studio/components/interfaces/Settings/General/Infrastructure/RestartServerButton.test.tsx +++ b/apps/studio/components/interfaces/Settings/General/Infrastructure/RestartServerButton.test.tsx @@ -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', () => ({ diff --git a/apps/studio/components/interfaces/Settings/General/Infrastructure/RestartServerButton.tsx b/apps/studio/components/interfaces/Settings/General/Infrastructure/RestartServerButton.tsx index 68213ca961d..8d02ee13c1b 100644 --- a/apps/studio/components/interfaces/Settings/General/Infrastructure/RestartServerButton.tsx +++ b/apps/studio/components/interfaces/Settings/General/Infrastructure/RestartServerButton.tsx @@ -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({ diff --git a/apps/studio/components/interfaces/Settings/General/TransferProjectPanel/TransferProjectButton.tsx b/apps/studio/components/interfaces/Settings/General/TransferProjectPanel/TransferProjectButton.tsx index 9e5c1e23eba..bea17e1a497 100644 --- a/apps/studio/components/interfaces/Settings/General/TransferProjectPanel/TransferProjectButton.tsx +++ b/apps/studio/components/interfaces/Settings/General/TransferProjectPanel/TransferProjectButton.tsx @@ -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() { diff --git a/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GitHubIntegrationConnectionForm.tsx b/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GitHubIntegrationConnectionForm.tsx index a9d0c4a28a0..3c7be201941 100644 --- a/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GitHubIntegrationConnectionForm.tsx +++ b/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GitHubIntegrationConnectionForm.tsx @@ -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 { diff --git a/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GithubSection.tsx b/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GithubSection.tsx index 39a8244c032..ca4e11ac222 100644 --- a/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GithubSection.tsx +++ b/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GithubSection.tsx @@ -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({ diff --git a/apps/studio/components/interfaces/Settings/Integrations/VercelIntegration/VercelSection.tsx b/apps/studio/components/interfaces/Settings/Integrations/VercelIntegration/VercelSection.tsx index e7f48840b45..20215307f2d 100644 --- a/apps/studio/components/interfaces/Settings/Integrations/VercelIntegration/VercelSection.tsx +++ b/apps/studio/components/interfaces/Settings/Integrations/VercelIntegration/VercelSection.tsx @@ -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( diff --git a/apps/studio/components/interfaces/Settings/Logs/LogTable.tsx b/apps/studio/components/interfaces/Settings/Logs/LogTable.tsx index 52826144ea3..b2da136d620 100644 --- a/apps/studio/components/interfaces/Settings/Logs/LogTable.tsx +++ b/apps/studio/components/interfaces/Settings/Logs/LogTable.tsx @@ -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(null) const [selectedRows, setSelectedRows] = useState>(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] diff --git a/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/SimpleConfigurationDetails.tsx b/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/SimpleConfigurationDetails.tsx index 357ed760bcd..8f1edc7c96c 100644 --- a/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/SimpleConfigurationDetails.tsx +++ b/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/SimpleConfigurationDetails.tsx @@ -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 diff --git a/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/UpdateCatalogTokenDialog.tsx b/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/UpdateCatalogTokenDialog.tsx index 10d93546846..7cbcd64885b 100644 --- a/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/UpdateCatalogTokenDialog.tsx +++ b/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/UpdateCatalogTokenDialog.tsx @@ -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() diff --git a/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/useAnalyticsBucketAssociatedEntities.tsx b/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/useAnalyticsBucketAssociatedEntities.tsx index bcf9737d16b..4fc34fa58ab 100644 --- a/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/useAnalyticsBucketAssociatedEntities.tsx +++ b/apps/studio/components/interfaces/Storage/AnalyticsBuckets/AnalyticsBucketDetails/useAnalyticsBucketAssociatedEntities.tsx @@ -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 { diff --git a/apps/studio/components/interfaces/Storage/BucketFilePickerDialog/BucketFilePickerColumn.tsx b/apps/studio/components/interfaces/Storage/BucketFilePickerDialog/BucketFilePickerColumn.tsx index 9b0da9e47cf..2ce7d58fc25 100644 --- a/apps/studio/components/interfaces/Storage/BucketFilePickerDialog/BucketFilePickerColumn.tsx +++ b/apps/studio/components/interfaces/Storage/BucketFilePickerDialog/BucketFilePickerColumn.tsx @@ -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(null) const { hostEndpoint } = useProjectApiUrl({ projectRef: projectRef! }) - const { can: canUpdateStorage } = useAsyncCheckPermissions(PermissionAction.STORAGE_WRITE, '*') + const { can: canUpdateStorage } = useAsyncCheckPermissionsV2( + FGA_PERMISSIONS.PROJECT.STORAGE_WRITE + ) const { columns, diff --git a/apps/studio/components/interfaces/Storage/BucketFilePickerDialog/BucketFilePickerHeader.tsx b/apps/studio/components/interfaces/Storage/BucketFilePickerDialog/BucketFilePickerHeader.tsx index a55f093d2ef..4e614a857fd 100644 --- a/apps/studio/components/interfaces/Storage/BucketFilePickerDialog/BucketFilePickerHeader.tsx +++ b/apps/studio/components/interfaces/Storage/BucketFilePickerDialog/BucketFilePickerHeader.tsx @@ -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 diff --git a/apps/studio/components/interfaces/Storage/FilesBuckets/useFilesBucketsShortcuts.ts b/apps/studio/components/interfaces/Storage/FilesBuckets/useFilesBucketsShortcuts.ts index 76373d915f3..16f2d9d4669 100644 --- a/apps/studio/components/interfaces/Storage/FilesBuckets/useFilesBucketsShortcuts.ts +++ b/apps/studio/components/interfaces/Storage/FilesBuckets/useFilesBucketsShortcuts.ts @@ -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 @@ -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, diff --git a/apps/studio/components/interfaces/Storage/NewBucketButton.tsx b/apps/studio/components/interfaces/Storage/NewBucketButton.tsx index 4a9b39b2183..73f8a8b47ec 100644 --- a/apps/studio/components/interfaces/Storage/NewBucketButton.tsx +++ b/apps/studio/components/interfaces/Storage/NewBucketButton.tsx @@ -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 }) => { - const { can: canCreateBuckets } = useAsyncCheckPermissions(PermissionAction.STORAGE_WRITE, '*') + const { can: canCreateBuckets } = useAsyncCheckPermissionsV2( + FGA_PERMISSIONS.PROJECT.STORAGE_WRITE + ) return ( { 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) {