import { PermissionAction } from '@supabase/shared-types/out/constants' import { JwtSecretUpdateStatus } from '@supabase/shared-types/out/events' import { useFlag, useParams } from 'common' import { AlertCircle, Loader2 } from 'lucide-react' import Link from 'next/link' import { useMemo } from 'react' import { toast } from 'sonner' import { Input } from 'ui-patterns/DataInputs/Input' import { FormLayout } from 'ui-patterns/form/Layout/FormLayout' import { getLastUsedAPIKeys, useLastUsedAPIKeysLogQuery } from './DisplayApiSettings.utils' import Panel from '@/components/ui/Panel' import { useJwtSecretUpdatingStatusQuery } from '@/data/config/jwt-secret-updating-status-query' import { useProjectSettingsV2Query } from '@/data/config/project-settings-v2-query' import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions' export const DisplayApiSettings = ({ showTitle = true, showNotice = true, showLegacyText = true, }: { showTitle?: boolean showNotice?: boolean showLegacyText?: boolean }) => { const { ref: projectRef } = useParams() const { data: settings, isError: isProjectSettingsError, isPending: isProjectSettingsLoading, } = useProjectSettingsV2Query({ projectRef }) const { data, isError: isJwtSecretUpdateStatusError, isPending: isJwtSecretUpdateStatusLoading, } = useJwtSecretUpdatingStatusQuery({ projectRef }) const jwtSecretUpdateStatus = data?.jwtSecretUpdateStatus const { isLoading: isLoadingPermissions, can: canReadAPIKeys } = useAsyncCheckPermissions( PermissionAction.READ, 'service_api_keys' ) const isLoading = isProjectSettingsLoading || isLoadingPermissions const isNotUpdatingJwtSecret = jwtSecretUpdateStatus === undefined || jwtSecretUpdateStatus === JwtSecretUpdateStatus.Updated const apiKeys = useMemo(() => settings?.service_api_keys ?? [], [settings]) // api keys should not be empty. However it can be populated with a delay on project creation const isApiKeysEmpty = apiKeys.length === 0 const showApiKeyLastUsed = useFlag('showApiKeysLastUsed') const { isLoading: isLoadingLastUsed, logData: lastUsedLogData } = useLastUsedAPIKeysLogQuery({ projectRef: projectRef ?? '', enabled: showApiKeyLastUsed, }) const lastUsedAPIKeys = useMemo(() => { if ( apiKeys.length < 1 || !lastUsedLogData || lastUsedLogData.length < 1 || !showApiKeyLastUsed ) { return {} } try { return getLastUsedAPIKeys(apiKeys, lastUsedLogData) } catch (e: any) { toast.error('Failed to identify when the anon and service_role keys were last used') console.error(e) return {} } }, [lastUsedLogData, apiKeys, showApiKeyLastUsed]) return (
Project API Keys

Your API is secured behind an API gateway which requires an API Key for every request.
You can use the keys below in the Briven client libraries.

) } > {isLoading ? (

Retrieving API keys

) : !canReadAPIKeys ? (

You don't have permission to view API keys. These keys restricted to users with higher access levels.

) : isProjectSettingsError || isJwtSecretUpdateStatusError ? (

{isProjectSettingsError ? 'Failed to retrieve API keys' : 'Failed to update JWT secret'}

) : isApiKeysEmpty || isProjectSettingsLoading || isJwtSecretUpdateStatusLoading ? (

{isProjectSettingsLoading || isApiKeysEmpty ? 'Retrieving API keys' : 'JWT secret is being updated'}

) : ( apiKeys.map((x, i: number) => ( = 1 && 'border-t border-panel-border-interior-light in-data-[theme*=dark]:border-panel-border-interior-dark' } > {x.tags?.split(',').map((x, i: number) => ( {x} ))} {x.tags === 'service_role' && ( <> secret )} {x.tags === 'anon' && public} } description={ x.tags === 'service_role' ? ( <> This key has the ability to bypass Row Level Security. Never share it publicly. If leaked, generate a new JWT secret immediately.{' '} {showLegacyText && ( Prefer using{' '} Secret API keys {' '} instead. )} ) : ( <> This key is safe to use in a browser if you have enabled Row Level Security for your tables and configured policies.{' '} {showLegacyText && ( Prefer using{' '} Publishable API keys {' '} instead. )} ) } > {}} /> {showApiKeyLastUsed && (
{lastUsedAPIKeys[x.api_key] ? `Last request was ${lastUsedAPIKeys[x.api_key]} ago.` : 'No requests in the past 24 hours.'}
)}
)) )} {showNotice ? ( ) : null}
) }