mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
chore: consolidate useAPIKeysQuery + getKeys into a single useAPIKeys hook (#46761)
## Problem - API may return a non-array shape that can crash `getKeys` because of an hard coded cast - getting API keys is cumbersome as consumers have to call two functions ## Solution - consolidate `useAPIKeysQuery` + `getKeys` into a single `useAPIKeys` hook - guard `getKeys` so that it doesn't crash if passed a non array value - update usages <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Unified how project API keys are retrieved across the studio, resulting in more consistent loading/error handling and slight responsiveness improvements when showing keys and related command snippets. UI and permissions behavior remain unchanged for end users. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
1 parent
f622bc6ea0
commit
43300d43ce
18 files changed
+93
-62
No files matched your search
@@ -15,7 +15,7 @@ import {
|
||||
|
||||
import { COMMAND_MENU_SECTIONS } from './CommandMenu.utils'
|
||||
import { orderCommandSectionsByPriority } from './ordering'
|
||||
import { getKeys, useAPIKeysQuery } from '@/data/api-keys/api-keys-query'
|
||||
import { useAPIKeys } from '@/data/api-keys/api-keys-query'
|
||||
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
|
||||
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
|
||||
|
||||
@@ -31,13 +31,13 @@ export function useApiKeysCommands() {
|
||||
|
||||
const { can: canReadAPIKeys } = useAsyncCheckPermissions(PermissionAction.SECRETS_READ, '*')
|
||||
|
||||
const { data: apiKeys } = useAPIKeysQuery(
|
||||
const { data: apiKeysData } = useAPIKeys(
|
||||
{ projectRef: project?.ref, reveal: true },
|
||||
{ enabled: canReadAPIKeys }
|
||||
)
|
||||
const commands = useMemo(() => {
|
||||
const { anonKey, serviceKey, publishableKey, allSecretKeys } = canReadAPIKeys
|
||||
? getKeys(apiKeys)
|
||||
? (apiKeysData ?? {})
|
||||
: {}
|
||||
|
||||
return [
|
||||
@@ -127,7 +127,7 @@ export function useApiKeysCommands() {
|
||||
icon: () => <Key />,
|
||||
},
|
||||
].filter(Boolean) as ICommand[]
|
||||
}, [apiKeys, canReadAPIKeys, project, ref, resetCommandMenu, setIsOpen])
|
||||
}, [canReadAPIKeys, apiKeysData, project, ref, resetCommandMenu, setIsOpen])
|
||||
|
||||
useRegisterPage(
|
||||
API_KEYS_PAGE_NAME,
|
||||
|
||||
@@ -12,7 +12,7 @@ import { useAvailableConnectModes } from './useAvailableConnectModes'
|
||||
import { useConnectSheetParams } from './useConnectSheetParams'
|
||||
import { useConnectSheetShortcut } from './useConnectSheetShortcut'
|
||||
import { useConnectState } from './useConnectState'
|
||||
import { getKeys, useAPIKeysQuery } from '@/data/api-keys/api-keys-query'
|
||||
import { useAPIKeys } from '@/data/api-keys/api-keys-query'
|
||||
import { useProjectApiUrl } from '@/data/config/project-endpoint-query'
|
||||
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
|
||||
import { useTrack } from '@/lib/telemetry/track'
|
||||
@@ -159,18 +159,16 @@ export const ConnectSheet = () => {
|
||||
PermissionAction.READ,
|
||||
'service_api_keys'
|
||||
)
|
||||
const { data: apiKeys } = useAPIKeysQuery({ projectRef }, { enabled: canReadAPIKeys })
|
||||
const { anonKey, publishableKey } = canReadAPIKeys
|
||||
? getKeys(apiKeys)
|
||||
: { anonKey: null, publishableKey: null }
|
||||
const { data: apiKeysData } = useAPIKeys({ projectRef }, { enabled: canReadAPIKeys })
|
||||
|
||||
const projectKeys: ProjectKeys = useMemo(() => {
|
||||
const { anonKey, publishableKey } = apiKeysData ?? {}
|
||||
return {
|
||||
apiUrl: endpoint,
|
||||
anonKey: anonKey?.api_key ?? null,
|
||||
publishableKey: publishableKey?.api_key ?? null,
|
||||
}
|
||||
}, [endpoint, anonKey?.api_key, publishableKey?.api_key])
|
||||
}, [endpoint, apiKeysData])
|
||||
|
||||
const availableModes = useMemo(
|
||||
() => schema.modes.filter((m) => availableModeIds.includes(m.id)),
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
FormSectionContent,
|
||||
FormSectionLabel,
|
||||
} from '@/components/ui/Forms/FormSection'
|
||||
import { getKeys, useAPIKeysQuery } from '@/data/api-keys/api-keys-query'
|
||||
import { useAPIKeys } from '@/data/api-keys/api-keys-query'
|
||||
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
|
||||
import { uuidv4 } from '@/lib/helpers'
|
||||
|
||||
@@ -23,12 +23,14 @@ export const HTTPHeaders = ({ form }: HTTPHeadersProps) => {
|
||||
const { ref } = useParams()
|
||||
const { can: canReadAPIKeys } = useAsyncCheckPermissions(PermissionAction.SECRETS_READ, '*')
|
||||
|
||||
const { data: apiKeys } = useAPIKeysQuery(
|
||||
{ projectRef: ref, reveal: true },
|
||||
const { data: apiKeyData } = useAPIKeys(
|
||||
{
|
||||
projectRef: ref,
|
||||
reveal: true,
|
||||
},
|
||||
{ enabled: canReadAPIKeys }
|
||||
)
|
||||
|
||||
const { serviceKey, secretKey } = getKeys(apiKeys)
|
||||
const { serviceKey, secretKey } = apiKeyData ?? {}
|
||||
const apiKey = secretKey?.api_key ?? serviceKey?.api_key ?? '[YOUR API KEY]'
|
||||
|
||||
const functionType = useWatch({ control: form.control, name: 'function_type' })
|
||||
|
||||
+3
-3
@@ -24,7 +24,7 @@ import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
|
||||
import { CREATE_NEW_KEY, CREATE_NEW_NAMESPACE } from './DestinationForm.constants'
|
||||
import type { DestinationPanelSchemaType } from './DestinationForm.schema'
|
||||
import { InlineLink } from '@/components/ui/InlineLink'
|
||||
import { getKeys, useAPIKeysQuery } from '@/data/api-keys/api-keys-query'
|
||||
import { useAPIKeys } from '@/data/api-keys/api-keys-query'
|
||||
import { useAnalyticsBucketsQuery } from '@/data/storage/analytics-buckets-query'
|
||||
import { useIcebergNamespacesQuery } from '@/data/storage/iceberg-namespaces-query'
|
||||
import { useStorageCredentialsQuery } from '@/data/storage/s3-access-key-query'
|
||||
@@ -370,11 +370,11 @@ export const AnalyticsBucketFields = ({
|
||||
const { ref: projectRef } = useParams()
|
||||
|
||||
const { can: canReadAPIKeys } = useAsyncCheckPermissions(PermissionAction.SECRETS_READ, '*')
|
||||
const { data: apiKeys } = useAPIKeysQuery(
|
||||
const { data: apiKeysData } = useAPIKeys(
|
||||
{ projectRef, reveal: true },
|
||||
{ enabled: canReadAPIKeys }
|
||||
)
|
||||
const { serviceKey } = getKeys(apiKeys)
|
||||
const { serviceKey } = apiKeysData ?? {}
|
||||
const serviceApiKey = serviceKey?.api_key ?? ''
|
||||
|
||||
const {
|
||||
|
||||
+4
-3
@@ -31,7 +31,7 @@ import { PublicationSelection } from './PublicationSelection'
|
||||
import { ReplicationDisclaimerDialog } from './ReplicationDisclaimerDialog'
|
||||
import { ValidationFailuresSection } from './ValidationFailuresSection'
|
||||
import { CreateAnalyticsBucketSheet } from '@/components/interfaces/Storage/AnalyticsBuckets/CreateAnalyticsBucketSheet'
|
||||
import { getKeys, useAPIKeysQuery } from '@/data/api-keys/api-keys-query'
|
||||
import { useAPIKeys } from '@/data/api-keys/api-keys-query'
|
||||
import { useProjectSettingsV2Query } from '@/data/config/project-settings-v2-query'
|
||||
import {
|
||||
BatchConfig,
|
||||
@@ -149,11 +149,12 @@ export const DestinationForm = ({
|
||||
pipelineId: existingDestination?.pipelineId,
|
||||
})
|
||||
|
||||
const { data: apiKeys } = useAPIKeysQuery(
|
||||
const { data: apiKeysData } = useAPIKeys(
|
||||
{ projectRef, reveal: true },
|
||||
{ enabled: canReadAPIKeys }
|
||||
)
|
||||
const { serviceKey } = getKeys(apiKeys)
|
||||
const { serviceKey } = apiKeysData ?? {}
|
||||
|
||||
const catalogToken = serviceKey?.api_key ?? ''
|
||||
|
||||
const { data: projectSettings } = useProjectSettingsV2Query({ projectRef })
|
||||
|
||||
@@ -5,7 +5,7 @@ import CodeSnippet from './CodeSnippet'
|
||||
import { DocSection } from './DocSection'
|
||||
import Snippets from './Snippets'
|
||||
import { InlineLink } from '@/components/ui/InlineLink'
|
||||
import { getKeys, useAPIKeysQuery } from '@/data/api-keys/api-keys-query'
|
||||
import { useAPIKeys } from '@/data/api-keys/api-keys-query'
|
||||
import { useProjectSettingsV2Query } from '@/data/config/project-settings-v2-query'
|
||||
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
|
||||
|
||||
@@ -17,10 +17,11 @@ interface AuthenticationProps {
|
||||
const Authentication = ({ selectedLang, showApiKey }: AuthenticationProps) => {
|
||||
const { ref: projectRef } = useParams()
|
||||
const { can: canReadAPIKeys } = useAsyncCheckPermissions(PermissionAction.SECRETS_READ, '*')
|
||||
const { data: apiKeys } = useAPIKeysQuery({ projectRef }, { enabled: canReadAPIKeys })
|
||||
const { data: apiKeyData } = useAPIKeys({ projectRef }, { enabled: canReadAPIKeys })
|
||||
const { anonKey, serviceKey } = apiKeyData ?? {}
|
||||
|
||||
const { data: settings } = useProjectSettingsV2Query({ projectRef })
|
||||
|
||||
const { anonKey, serviceKey } = getKeys(apiKeys)
|
||||
const protocol = settings?.app_config?.protocol ?? 'https'
|
||||
const hostEndpoint = settings?.app_config?.endpoint
|
||||
const endpoint = `${protocol}://${hostEndpoint ?? ''}`
|
||||
|
||||
+3
-3
@@ -42,7 +42,7 @@ import z from 'zod'
|
||||
import CommandRender from '../CommandRender'
|
||||
import { INVOCATION_TABS } from './EdgeFunctionDetails.constants'
|
||||
import { generateCLICommands } from './EdgeFunctionDetails.utils'
|
||||
import { getKeys, useAPIKeysQuery } from '@/data/api-keys/api-keys-query'
|
||||
import { useAPIKeys } from '@/data/api-keys/api-keys-query'
|
||||
import { useProjectApiUrl } from '@/data/config/project-endpoint-query'
|
||||
import { useEdgeFunctionQuery } from '@/data/edge-functions/edge-function-query'
|
||||
import { useEdgeFunctionDeleteMutation } from '@/data/edge-functions/edge-functions-delete-mutation'
|
||||
@@ -79,7 +79,8 @@ export const EdgeFunctionDetails = () => {
|
||||
const canUpdateEdgeFunction = IS_PLATFORM && canUpdateEdgeFunctionPermission
|
||||
|
||||
const { can: canReadAPIKeys } = useAsyncCheckPermissions(PermissionAction.SECRETS_READ, '*')
|
||||
const { data: apiKeys } = useAPIKeysQuery({ projectRef }, { enabled: canReadAPIKeys })
|
||||
const { data: apiKeyData } = useAPIKeys({ projectRef }, { enabled: canReadAPIKeys })
|
||||
const { anonKey, publishableKey } = apiKeyData ?? {}
|
||||
|
||||
const { data: selectedFunction } = useEdgeFunctionQuery({ projectRef, slug: functionSlug })
|
||||
|
||||
@@ -99,7 +100,6 @@ export const EdgeFunctionDetails = () => {
|
||||
defaultValues: { name: '', verify_jwt: false },
|
||||
})
|
||||
|
||||
const { anonKey, publishableKey } = getKeys(apiKeys)
|
||||
const apiKey = publishableKey?.api_key ?? anonKey?.api_key ?? '[YOUR ANON KEY]'
|
||||
|
||||
const { managementCommands } = generateCLICommands({
|
||||
|
||||
+3
-3
@@ -39,7 +39,7 @@ import { HTTP_METHODS } from './EdgeFunctionDetails.constants'
|
||||
import { ErrorWithStatus, ResponseData } from './EdgeFunctionDetails.types'
|
||||
import { RoleImpersonationPopover } from '@/components/interfaces/RoleImpersonationSelector/RoleImpersonationPopover'
|
||||
import { ShortcutTooltip } from '@/components/ui/ShortcutTooltip'
|
||||
import { getKeys, useAPIKeysQuery } from '@/data/api-keys/api-keys-query'
|
||||
import { useAPIKeys } from '@/data/api-keys/api-keys-query'
|
||||
import { useSessionAccessTokenQuery } from '@/data/auth/session-access-token-query'
|
||||
import { useProjectPostgrestConfigQuery } from '@/data/config/project-postgrest-config-query'
|
||||
import { useProjectSettingsV2Query } from '@/data/config/project-settings-v2-query'
|
||||
@@ -102,11 +102,11 @@ const EdgeFunctionTesterSheetContent = ({ visible, onClose }: EdgeFunctionTester
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
|
||||
const { can: canReadAPIKeys } = useAsyncCheckPermissions(PermissionAction.SECRETS_READ, '*')
|
||||
const { data: apiKeys } = useAPIKeysQuery({ projectRef }, { enabled: canReadAPIKeys })
|
||||
const { data: apiKeysData } = useAPIKeys({ projectRef }, { enabled: canReadAPIKeys })
|
||||
const { serviceKey } = apiKeysData ?? {}
|
||||
const { data: config } = useProjectPostgrestConfigQuery({ projectRef })
|
||||
const { data: settings } = useProjectSettingsV2Query({ projectRef })
|
||||
const { data: accessToken } = useSessionAccessTokenQuery({ enabled: IS_PLATFORM })
|
||||
const { serviceKey } = getKeys(apiKeys)
|
||||
|
||||
const track = useTrack()
|
||||
const { mutate: testEdgeFunction, isPending } = useEdgeFunctionTestMutation({
|
||||
|
||||
@@ -9,7 +9,7 @@ import type { Commands } from './Functions.types'
|
||||
import CommandRender from '@/components/interfaces/Functions/CommandRender'
|
||||
import { DocsButton } from '@/components/ui/DocsButton'
|
||||
import { useAccessTokensQuery } from '@/data/access-tokens/access-tokens-query'
|
||||
import { getKeys, useAPIKeysQuery } from '@/data/api-keys/api-keys-query'
|
||||
import { useAPIKeys } from '@/data/api-keys/api-keys-query'
|
||||
import { useProjectApiUrl } from '@/data/config/project-endpoint-query'
|
||||
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
|
||||
import { DOCS_URL } from '@/lib/constants'
|
||||
@@ -29,12 +29,12 @@ export const TerminalInstructions = forwardRef<
|
||||
|
||||
const { data: tokens } = useAccessTokensQuery()
|
||||
const { can: canReadAPIKeys } = useAsyncCheckPermissions(PermissionAction.SECRETS_READ, '*')
|
||||
const { data: apiKeys } = useAPIKeysQuery({ projectRef }, { enabled: canReadAPIKeys })
|
||||
const { data: apiKeyData } = useAPIKeys({ projectRef }, { enabled: canReadAPIKeys })
|
||||
const { anonKey, publishableKey } = apiKeyData ?? {}
|
||||
|
||||
const { data: endpoint } = useProjectApiUrl({ projectRef })
|
||||
const functionsEndpoint = `${endpoint}/functions/v1`
|
||||
|
||||
const { anonKey, publishableKey } = getKeys(apiKeys)
|
||||
const apiKey = publishableKey?.api_key ?? anonKey?.api_key ?? '[YOUR ANON KEY]'
|
||||
|
||||
// get the .co or .net TLD from the restUrl
|
||||
|
||||
@@ -11,7 +11,7 @@ import { ConnectionIcon } from '@/components/interfaces/Connect/ConnectionIcon'
|
||||
import { ConnectButton } from '@/components/interfaces/ConnectButton/ConnectButton'
|
||||
import { AlertError } from '@/components/ui/AlertError'
|
||||
import { InlineLink } from '@/components/ui/InlineLink'
|
||||
import { getKeys, useAPIKeysQuery } from '@/data/api-keys/api-keys-query'
|
||||
import { useAPIKeys } from '@/data/api-keys/api-keys-query'
|
||||
import { useLegacyAPIKeysStatusQuery } from '@/data/api-keys/legacy-api-keys-status-query'
|
||||
import { useJwtSecretUpdatingStatusQuery } from '@/data/config/jwt-secret-updating-status-query'
|
||||
import { useProjectSettingsV2Query } from '@/data/config/project-settings-v2-query'
|
||||
@@ -32,12 +32,12 @@ export const APIKeys = () => {
|
||||
useLegacyAPIKeysStatusQuery({ projectRef }, { enabled: canReadAPIKeys })
|
||||
|
||||
const {
|
||||
data: apiKeys,
|
||||
data: apiKeysData,
|
||||
error: errorAPIKeys,
|
||||
isError: isErrorAPIKeys,
|
||||
isPending: isLoadingAPIKeys,
|
||||
} = useAPIKeysQuery({ projectRef }, { enabled: canReadAPIKeys })
|
||||
const { anonKey, serviceKey, publishableKey, secretKey } = getKeys(apiKeys)
|
||||
} = useAPIKeys({ projectRef }, { enabled: canReadAPIKeys })
|
||||
const { anonKey, serviceKey, publishableKey, secretKey } = apiKeysData ?? {}
|
||||
|
||||
const hasNewAPIKeys = !!publishableKey && !!secretKey
|
||||
const isLegacyKeysEnabled = legacyAPIKeysStatusData?.enabled ?? false
|
||||
|
||||
@@ -6,7 +6,7 @@ import { KeyValueFieldArray } from 'ui-patterns/form/KeyValueFieldArray/KeyValue
|
||||
|
||||
import { CreateCronJobForm } from './CreateCronJobSheet/CreateCronJobSheet.constants'
|
||||
import { buildEdgeFunctionHeaderAddActions } from '@/components/interfaces/Functions/httpHeaderAddActions'
|
||||
import { getKeys, useAPIKeysQuery } from '@/data/api-keys/api-keys-query'
|
||||
import { useAPIKeys } from '@/data/api-keys/api-keys-query'
|
||||
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
|
||||
|
||||
interface HTTPHeaderFieldsSectionProps {
|
||||
@@ -18,12 +18,12 @@ export const HTTPHeaderFieldsSection = ({ variant }: HTTPHeaderFieldsSectionProp
|
||||
|
||||
const { ref } = useParams()
|
||||
const { can: canReadAPIKeys } = useAsyncCheckPermissions(PermissionAction.SECRETS_READ, '*')
|
||||
const { data: apiKeys } = useAPIKeysQuery(
|
||||
const { data: apiKeysData } = useAPIKeys(
|
||||
{ projectRef: ref, reveal: true },
|
||||
{ enabled: canReadAPIKeys }
|
||||
)
|
||||
const { serviceKey, secretKey } = apiKeysData ?? {}
|
||||
|
||||
const { serviceKey, secretKey } = getKeys(apiKeys)
|
||||
const apiKey = secretKey?.api_key ?? serviceKey?.api_key ?? '[YOUR API KEY]'
|
||||
const addActions =
|
||||
variant === 'edge_function'
|
||||
|
||||
@@ -9,7 +9,7 @@ import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
|
||||
import ContentSnippet from '../ContentSnippet'
|
||||
import { DOCS_CONTENT } from '../ProjectAPIDocs.constants'
|
||||
import type { ContentProps } from './Content.types'
|
||||
import { getKeys, useAPIKeysQuery } from '@/data/api-keys/api-keys-query'
|
||||
import { useAPIKeys } from '@/data/api-keys/api-keys-query'
|
||||
import { useProjectSettingsV2Query } from '@/data/config/project-settings-v2-query'
|
||||
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
|
||||
import { useTrack } from '@/lib/telemetry/track'
|
||||
@@ -17,8 +17,10 @@ import { useTrack } from '@/lib/telemetry/track'
|
||||
export const Introduction = ({ showKeys, language, apikey, endpoint }: ContentProps) => {
|
||||
const { ref } = useParams()
|
||||
const { can: canReadAPIKeys } = useAsyncCheckPermissions(PermissionAction.SECRETS_READ, '*')
|
||||
const { data: apiKeys } = useAPIKeysQuery({ projectRef: ref }, { enabled: canReadAPIKeys })
|
||||
const { data: apiKeysData } = useAPIKeys({ projectRef: ref }, { enabled: canReadAPIKeys })
|
||||
useProjectSettingsV2Query({ projectRef: ref })
|
||||
const { anonKey, serviceKey } = apiKeysData ?? {}
|
||||
|
||||
const track = useTrack()
|
||||
|
||||
const [copied, setCopied] = useState<'anon' | 'service'>()
|
||||
@@ -27,7 +29,6 @@ export const Introduction = ({ showKeys, language, apikey, endpoint }: ContentPr
|
||||
if (copied !== undefined) setTimeout(() => setCopied(undefined), 2000)
|
||||
}, [copied])
|
||||
|
||||
const { anonKey, serviceKey } = getKeys(apiKeys)
|
||||
const anonApiKey = anonKey?.api_key
|
||||
const serviceApiKey = serviceKey?.api_key ?? 'SUPABASE_CLIENT_SERVICE_KEY'
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import { UserManagement } from './Content/UserManagement'
|
||||
import { FirstLevelNav } from './FirstLevelNav'
|
||||
import LanguageSelector from './LanguageSelector'
|
||||
import { SecondLevelNav } from './SecondLevelNav'
|
||||
import { getKeys, useAPIKeysQuery } from '@/data/api-keys/api-keys-query'
|
||||
import { useAPIKeys } from '@/data/api-keys/api-keys-query'
|
||||
import { useProjectApiUrl } from '@/data/config/project-endpoint-query'
|
||||
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
|
||||
import { useAppStateSnapshot } from '@/state/app-state'
|
||||
@@ -45,17 +45,17 @@ export const ProjectAPIDocs = () => {
|
||||
const language = snap.docsLanguage
|
||||
|
||||
const { can: canReadAPIKeys } = useAsyncCheckPermissions(PermissionAction.SECRETS_READ, '*')
|
||||
const { data: apiKeys } = useAPIKeysQuery(
|
||||
const { data: apiKeysData } = useAPIKeys(
|
||||
{ projectRef: ref },
|
||||
{ enabled: snap.showProjectApiDocs && canReadAPIKeys }
|
||||
)
|
||||
const { anonKey } = apiKeysData ?? {}
|
||||
|
||||
const { data: endpoint } = useProjectApiUrl(
|
||||
{ projectRef: ref },
|
||||
{ enabled: snap.showProjectApiDocs }
|
||||
)
|
||||
|
||||
const { anonKey } = getKeys(apiKeys)
|
||||
const apikey = showKeys
|
||||
? (anonKey?.api_key ?? 'SUPABASE_CLIENT_ANON_KEY')
|
||||
: 'SUPABASE_CLIENT_ANON_KEY'
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
import { ShimmeringLoader } from 'ui-patterns'
|
||||
|
||||
import { getConnectionStrings } from '@/components/interfaces/Connect/DatabaseSettings.utils'
|
||||
import { getKeys, useAPIKeysQuery } from '@/data/api-keys/api-keys-query'
|
||||
import { useAPIKeys } from '@/data/api-keys/api-keys-query'
|
||||
import { useProjectApiUrl } from '@/data/config/project-endpoint-query'
|
||||
import { useReadReplicasQuery } from '@/data/read-replicas/replicas-query'
|
||||
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
|
||||
@@ -47,11 +47,11 @@ export const ProjectConnectionPopover = ({ projectRef }: ProjectConnectionPopove
|
||||
|
||||
const { data: projectUrl, isPending: isLoadingApiUrl } = useProjectApiUrl({ projectRef })
|
||||
|
||||
const { data: apiKeys, isLoading: isLoadingKeys } = useAPIKeysQuery(
|
||||
const { data, isLoading: isLoadingKeys } = useAPIKeys(
|
||||
{ projectRef },
|
||||
{ enabled: open && canReadAPIKeys }
|
||||
)
|
||||
const { publishableKey } = canReadAPIKeys ? getKeys(apiKeys) : { publishableKey: null }
|
||||
const { publishableKey } = data ?? {}
|
||||
|
||||
const { data: databases, isLoading: isLoadingDatabases } = useReadReplicasQuery(
|
||||
{ projectRef },
|
||||
|
||||
@@ -4,7 +4,7 @@ import { toast } from 'sonner'
|
||||
|
||||
import { RealtimeConfig } from './useRealtimeMessages'
|
||||
import { RoleImpersonationPopover } from '@/components/interfaces/RoleImpersonationSelector/RoleImpersonationPopover'
|
||||
import { getKeys, useAPIKeysQuery } from '@/data/api-keys/api-keys-query'
|
||||
import { useAPIKeys } from '@/data/api-keys/api-keys-query'
|
||||
import { getTemporaryAPIKey } from '@/data/api-keys/temp-api-keys-query'
|
||||
import { useProjectPostgrestConfigQuery } from '@/data/config/project-postgrest-config-query'
|
||||
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
|
||||
@@ -22,15 +22,13 @@ export const RealtimeTokensPopover = ({ config, onChangeConfig }: RealtimeTokens
|
||||
const snap = useRoleImpersonationStateSnapshot()
|
||||
|
||||
const { can: canReadAPIKeys } = useAsyncCheckPermissions(PermissionAction.SECRETS_READ, '*')
|
||||
const { data: apiKeys } = useAPIKeysQuery(
|
||||
const { data: apiKeysData } = useAPIKeys(
|
||||
{
|
||||
projectRef: config.projectRef,
|
||||
reveal: true,
|
||||
},
|
||||
{ enabled: canReadAPIKeys }
|
||||
)
|
||||
const { anonKey, publishableKey } = getKeys(apiKeys)
|
||||
|
||||
const { data: postgrestConfig } = useProjectPostgrestConfigQuery(
|
||||
{ projectRef: config.projectRef },
|
||||
{ enabled: IS_PLATFORM }
|
||||
@@ -55,6 +53,7 @@ export const RealtimeTokensPopover = ({ config, onChangeConfig }: RealtimeTokens
|
||||
}, [snap.role])
|
||||
|
||||
useEffect(() => {
|
||||
const { anonKey, publishableKey } = apiKeysData ?? {}
|
||||
const triggerUpdateTokenBearer = async () => {
|
||||
let token: string | undefined
|
||||
let bearer: string | null = null
|
||||
@@ -84,7 +83,7 @@ export const RealtimeTokensPopover = ({ config, onChangeConfig }: RealtimeTokens
|
||||
|
||||
triggerUpdateTokenBearer()
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [snap.role, anonKey])
|
||||
}, [snap.role, apiKeysData])
|
||||
|
||||
return <RoleImpersonationPopover align="start" variant="connected-on-both" />
|
||||
}
|
||||
+4
-4
@@ -28,7 +28,7 @@ import { CodeBlock } from 'ui-patterns/CodeBlock'
|
||||
import { useS3VectorsWrapperExtension } from '../useS3VectorsWrapper'
|
||||
import { useS3VectorsWrapperInstance } from '../useS3VectorsWrapperInstance'
|
||||
import { DocsButton } from '@/components/ui/DocsButton'
|
||||
import { getKeys, useAPIKeysQuery } from '@/data/api-keys/api-keys-query'
|
||||
import { useAPIKeys } from '@/data/api-keys/api-keys-query'
|
||||
import { VectorBucketIndex } from '@/data/storage/vector-buckets-indexes-query'
|
||||
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
|
||||
import { DOCS_URL } from '@/lib/constants'
|
||||
@@ -143,8 +143,8 @@ function VectorBucketIndexExamples({
|
||||
PermissionAction.READ,
|
||||
'service_api_keys'
|
||||
)
|
||||
const { data: apiKeys } = useAPIKeysQuery({ projectRef }, { enabled: canReadAPIKeys })
|
||||
const { secretKey } = canReadAPIKeys ? getKeys(apiKeys) : { secretKey: null }
|
||||
const { data: apiKeysData } = useAPIKeys({ projectRef }, { enabled: canReadAPIKeys })
|
||||
const { secretKey } = apiKeysData ?? {}
|
||||
|
||||
const { data: wrapperInstance } = useS3VectorsWrapperInstance({ bucketId })
|
||||
const foreignTable = wrapperInstance?.tables?.find((x) => x.name === indexName)
|
||||
@@ -177,7 +177,7 @@ values
|
||||
|
||||
const jsCode = `import { createClient } from '@supabase/supabase-js'
|
||||
|
||||
// Adding vector data requires a secret or service role key
|
||||
// Adding vector data requires a secret or service role key
|
||||
// This code SHOULD NOT be run on the client side as you will be vulnerable to a data leak
|
||||
const client = createClient(
|
||||
process.env.SUPABASE_URL,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useCallback } from 'react'
|
||||
|
||||
import { apiKeysKeys } from './keys'
|
||||
import { get, handleError } from '@/data/fetchers'
|
||||
@@ -78,7 +79,18 @@ export const useAPIKeysQuery = <TData = APIKeysData>(
|
||||
})
|
||||
}
|
||||
|
||||
const EmptyKey = {
|
||||
anonKey: undefined,
|
||||
serviceKey: undefined,
|
||||
publishableKey: undefined,
|
||||
secretKey: undefined,
|
||||
allSecretKeys: [],
|
||||
}
|
||||
|
||||
export const getKeys = (apiKeys: APIKey[] = []) => {
|
||||
if (!Array.isArray(apiKeys)) {
|
||||
return EmptyKey
|
||||
}
|
||||
const anonKey = apiKeys.find((x) => x.name === 'anon')
|
||||
const serviceKey = apiKeys.find((x) => x.name === 'service_role')
|
||||
|
||||
@@ -90,3 +102,21 @@ export const getKeys = (apiKeys: APIKey[] = []) => {
|
||||
|
||||
return { anonKey, serviceKey, publishableKey, secretKey, allSecretKeys }
|
||||
}
|
||||
|
||||
const PlaceholderData: APIKeysData = []
|
||||
|
||||
export const useAPIKeys = (
|
||||
variables: APIKeysVariables,
|
||||
options: UseCustomQueryOptions<APIKeysData, ResponseError, APIKeysData> = {}
|
||||
) => {
|
||||
const select = useCallback(
|
||||
(data: APIKeysData) => getKeys(options.enabled ? data : []),
|
||||
[options.enabled]
|
||||
)
|
||||
|
||||
return useAPIKeysQuery(variables, {
|
||||
...options,
|
||||
placeholderData: PlaceholderData,
|
||||
select,
|
||||
})
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
getCatalogURI,
|
||||
getConnectionURL,
|
||||
} from '@/components/interfaces/Storage/StorageSettings/StorageSettings.utils'
|
||||
import { getKeys, useAPIKeysQuery } from '@/data/api-keys/api-keys-query'
|
||||
import { useAPIKeys } from '@/data/api-keys/api-keys-query'
|
||||
import { useProjectSettingsV2Query } from '@/data/config/project-settings-v2-query'
|
||||
import { FDWCreateVariables, useFDWCreateMutation } from '@/data/fdw/fdw-create-mutation'
|
||||
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
|
||||
@@ -20,12 +20,11 @@ export const useIcebergWrapperCreateMutation = () => {
|
||||
const { data: project } = useSelectedProjectQuery()
|
||||
|
||||
const { can: canReadAPIKeys } = useAsyncCheckPermissions(PermissionAction.SECRETS_READ, '*')
|
||||
const { data: apiKeys } = useAPIKeysQuery(
|
||||
const { data: apiKeysData } = useAPIKeys(
|
||||
{ projectRef: project?.ref, reveal: true },
|
||||
{ enabled: canReadAPIKeys }
|
||||
)
|
||||
const { secretKey, serviceKey } = getKeys(apiKeys)
|
||||
|
||||
const { secretKey, serviceKey } = apiKeysData ?? {}
|
||||
const { data: settings } = useProjectSettingsV2Query({ projectRef: project?.ref })
|
||||
const protocol = settings?.app_config?.protocol ?? 'https'
|
||||
const endpoint = settings?.app_config?.storage_endpoint || settings?.app_config?.endpoint
|
||||
|
||||
Reference in new issue
Block a user