refactor: use useAsyncCheckPermissionsV2 in api keys

This commit is contained in:
phamhieu committed 2026-09-29 11:29:43 +07:00
1 parent 5b49fef163
commit eced4c2851
8 files changed
+32 -38

No files matched your search

@@ -1,9 +1,8 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { Trash2 } from 'lucide-react'
import { DropdownMenuItemTooltip } from '@/components/ui/DropdownMenuItemTooltip'
import type { APIKeysData } from '@/data/api-keys/api-keys-query'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
interface APIKeyDeleteDialogProps {
apiKey: Extract<APIKeysData[number], { type: 'secret' | 'publishable' }>
@@ -11,9 +10,8 @@ interface APIKeyDeleteDialogProps {
}
export const APIKeyDeleteDialog = ({ apiKey, setKeyToDelete }: APIKeyDeleteDialogProps) => {
const { can: canDeleteAPIKeys } = useAsyncCheckPermissions(
PermissionAction.TENANT_SQL_ADMIN_WRITE,
'*'
const { can: canDeleteAPIKeys } = useAsyncCheckPermissionsV2(
FGA_PERMISSIONS.PROJECT.API_GATEWAY_KEYS_WRITE
)
return (
@@ -12,11 +12,12 @@ type ApiKeyResponse = components['schemas']['ApiKeyResponse_Output']
// Permissions are non-network global state — mock the hook (the skill's allowed
// exception), matching the neighboring PublishableAPIKeys.test.tsx.
const { mockUseAsyncCheckPermissions } = vi.hoisted(() => ({
mockUseAsyncCheckPermissions: vi.fn(),
const { mockUseAsyncCheckPermissionsV2 } = vi.hoisted(() => ({
mockUseAsyncCheckPermissionsV2: vi.fn(),
}))
vi.mock('@/hooks/misc/useCheckPermissions', () => ({
useAsyncCheckPermissions: mockUseAsyncCheckPermissions,
vi.mock('@/hooks/misc/useCheckPermissionsV2', async (importOriginal) => ({
...(await importOriginal<typeof import('@/hooks/misc/useCheckPermissionsV2')>()),
useAsyncCheckPermissionsV2: mockUseAsyncCheckPermissionsV2,
}))
// CopyButton writes via copyToClipboard from 'ui'. Stub just that export so we can
@@ -60,7 +61,7 @@ function mockRevealById() {
describe('ApiKeyPill', () => {
beforeEach(() => {
mockUseAsyncCheckPermissions.mockReturnValue({ can: true, isLoading: false })
mockUseAsyncCheckPermissionsV2.mockReturnValue({ can: true, isLoading: false, isSuccess: true })
mockCopyToClipboard.mockClear()
})
@@ -1,4 +1,3 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useParams } from 'common'
import { Eye, EyeOff } from 'lucide-react'
import { useEffect, useState } from 'react'
@@ -8,7 +7,7 @@ import { Button, cn, InputVariants, Tooltip, TooltipContent, TooltipTrigger } fr
import { useRevealedSecret } from './useRevealedSecret'
import CopyButton from '@/components/ui/CopyButton'
import { APIKeysData } from '@/data/api-keys/api-keys-query'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
export function ApiKeyPill({
apiKey,
@@ -20,9 +19,8 @@ export function ApiKeyPill({
const isSecret = apiKey.type === 'secret'
const { can: canManageSecretKeys, isLoading: isLoadingPermission } = useAsyncCheckPermissions(
PermissionAction.READ,
'service_api_keys'
const { can: canManageSecretKeys, isLoading: isLoadingPermission } = useAsyncCheckPermissionsV2(
[FGA_PERMISSIONS.PROJECT.API_GATEWAY_KEYS_SECRET_READ]
)
const {
@@ -7,12 +7,12 @@ import { customRender as render } from '@/tests/lib/custom-render'
const {
mockIsPlatform,
mockUseAPIKeysQuery,
mockUseAsyncCheckPermissions,
mockUseAsyncCheckPermissionsV2,
mockUseAPIKeyDeleteMutation,
} = vi.hoisted(() => ({
mockIsPlatform: { value: true },
mockUseAPIKeysQuery: vi.fn(),
mockUseAsyncCheckPermissions: vi.fn(),
mockUseAsyncCheckPermissionsV2: vi.fn(),
mockUseAPIKeyDeleteMutation: vi.fn(),
}))
@@ -35,8 +35,9 @@ vi.mock('@/data/api-keys/api-key-delete-mutation', () => ({
useAPIKeyDeleteMutation: mockUseAPIKeyDeleteMutation,
}))
vi.mock('@/hooks/misc/useCheckPermissions', () => ({
useAsyncCheckPermissions: mockUseAsyncCheckPermissions,
vi.mock('@/hooks/misc/useCheckPermissionsV2', async (importOriginal) => ({
...(await importOriginal<typeof import('@/hooks/misc/useCheckPermissionsV2')>()),
useAsyncCheckPermissionsV2: mockUseAsyncCheckPermissionsV2,
}))
vi.mock('./CreatePublishableAPIKeyDialog', () => ({
@@ -68,7 +69,7 @@ const secretKey = {
describe('PublishableAPIKeys', () => {
beforeEach(() => {
mockIsPlatform.value = true
mockUseAsyncCheckPermissions.mockReturnValue({ can: true, isLoading: false })
mockUseAsyncCheckPermissionsV2.mockReturnValue({ can: true, isLoading: false, isSuccess: true })
mockUseAPIKeyDeleteMutation.mockReturnValue({
mutate: vi.fn(),
isPending: false,
@@ -1,4 +1,3 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { IS_PLATFORM, useParams } from 'common'
import { parseAsString, useQueryState } from 'nuqs'
import { useEffect, useMemo } from 'react'
@@ -23,13 +22,12 @@ import { FormHeader } from '@/components/ui/Forms/FormHeader'
import { NoPermission } from '@/components/ui/NoPermission'
import { useAPIKeyDeleteMutation } from '@/data/api-keys/api-key-delete-mutation'
import { APIKeysData, useAPIKeysQuery } from '@/data/api-keys/api-keys-query'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
export const PublishableAPIKeys = () => {
const { ref: projectRef } = useParams()
const { can: canReadAPIKeys, isLoading: isLoadingPermissions } = useAsyncCheckPermissions(
PermissionAction.SECRETS_READ,
'*'
const { can: canReadAPIKeys, isLoading: isLoadingPermissions } = useAsyncCheckPermissionsV2(
FGA_PERMISSIONS.PROJECT.API_GATEWAY_KEYS_READ
)
const {
@@ -1,4 +1,3 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { IS_PLATFORM, useParams } from 'common'
import { parseAsString, useQueryState } from 'nuqs'
import { useEffect, useMemo } from 'react'
@@ -14,13 +13,12 @@ import { NoPermission } from '@/components/ui/NoPermission'
import { useAPIKeyDeleteMutation } from '@/data/api-keys/api-key-delete-mutation'
import type { APIKeysData } from '@/data/api-keys/api-keys-query'
import { useAPIKeysQuery } from '@/data/api-keys/api-keys-query'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
export const SecretAPIKeys = () => {
const { ref: projectRef } = useParams()
const { can: canReadAPIKeys, isLoading: isLoadingPermissions } = useAsyncCheckPermissions(
PermissionAction.SECRETS_READ,
'*'
const { can: canReadAPIKeys, isLoading: isLoadingPermissions } = useAsyncCheckPermissionsV2(
FGA_PERMISSIONS.PROJECT.API_GATEWAY_KEYS_READ
)
const {
@@ -12,15 +12,16 @@ import { addAPIMock } from '@/tests/lib/msw'
type ApiKeyResponse = components['schemas']['ApiKeyResponse_Output']
const { mockUseAsyncCheckPermissions, mockUseHighAvailability, mockUseSelectedProjectQuery } =
const { mockUseAsyncCheckPermissionsV2, mockUseHighAvailability, mockUseSelectedProjectQuery } =
vi.hoisted(() => ({
mockUseAsyncCheckPermissions: vi.fn(),
mockUseAsyncCheckPermissionsV2: vi.fn(),
mockUseHighAvailability: vi.fn(),
mockUseSelectedProjectQuery: vi.fn(),
}))
vi.mock('@/hooks/misc/useCheckPermissions', () => ({
useAsyncCheckPermissions: mockUseAsyncCheckPermissions,
vi.mock('@/hooks/misc/useCheckPermissionsV2', async (importOriginal) => ({
...(await importOriginal<typeof import('@/hooks/misc/useCheckPermissionsV2')>()),
useAsyncCheckPermissionsV2: mockUseAsyncCheckPermissionsV2,
}))
vi.mock('@/hooks/misc/useHighAvailability', () => ({
@@ -80,7 +81,7 @@ async function renderCommandPage() {
describe('useApiKeysCommands', () => {
beforeEach(() => {
mockUseAsyncCheckPermissions.mockReturnValue({ can: true })
mockUseAsyncCheckPermissionsV2.mockReturnValue({ can: true, isLoading: false, isSuccess: true })
mockUseSelectedProjectQuery.mockReturnValue({
data: { id: 1, ref: 'default', name: 'default' },
})
@@ -1,4 +1,3 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { Key } from 'lucide-react'
import { useMemo } from 'react'
import { toast } from 'sonner'
@@ -16,9 +15,9 @@ import {
import { COMMAND_MENU_SECTIONS } from './CommandMenu.utils'
import { orderCommandSectionsByPriority } from './ordering'
import { useAPIKeys } from '@/data/api-keys/api-keys-query'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useHighAvailability } from '@/hooks/misc/useHighAvailability'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { FGA_PERMISSIONS, useAsyncCheckPermissionsV2 } from '@/hooks/misc/useCheckPermissionsV2'
const API_KEYS_PAGE_NAME = 'API Keys'
@@ -30,7 +29,7 @@ export function useApiKeysCommands() {
const { data: project } = useSelectedProjectQuery()
const ref = project?.ref || '_'
const { can: canReadAPIKeys } = useAsyncCheckPermissions(PermissionAction.SECRETS_READ, '*')
const { can: canReadAPIKeys } = useAsyncCheckPermissionsV2(FGA_PERMISSIONS.PROJECT.API_GATEWAY_KEYS_READ)
const { isHighAvailability } = useHighAvailability()
const { data: apiKeysData } = useAPIKeys(