import { PermissionAction } from '@supabase/shared-types/out/constants' import { InputVariants } from '@ui/components/shadcn/ui/input' import { useParams } from 'common' import { Eye, EyeOff } from 'lucide-react' import { useEffect, useState } from 'react' import { toast } from 'sonner' import { Button, cn, Tooltip, TooltipContent, TooltipTrigger } from 'ui' 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' export function ApiKeyPill({ apiKey, }: { apiKey: Extract }) { const { ref: projectRef } = useParams() const [show, setShow] = useState(false) const isSecret = apiKey.type === 'secret' const { can: canManageSecretKeys, isLoading: isLoadingPermission } = useAsyncCheckPermissions( PermissionAction.READ, 'service_api_keys' ) const { data: revealedKey, isLoading, reveal, clear, } = useRevealedSecret({ projectRef, id: apiKey.id as string, }) // Auto-hide timer for the API key (security feature) useEffect(() => { if (show && revealedKey) { const timer = setTimeout(() => { setShow(false) clear() }, 10000) return () => clearTimeout(timer) } }, [show, revealedKey, clear]) async function onToggleShow() { if (isSecret && !canManageSecretKeys) return if (isLoadingPermission) return if (show) { setShow(false) clear() } else { setShow(true) try { await reveal() } catch { toast.error('Failed to reveal secret API key') setShow(false) } } } async function onCopy() { if (!isSecret) return apiKey.api_key if (revealedKey) return revealedKey try { const key = await reveal() clear() return key ?? '' } catch { toast.error('Failed to copy secret API key') return '' } } const isRestricted = isSecret && !canManageSecretKeys return ( <>
{isSecret ? ( <> {apiKey?.api_key.slice(0, 15)} {show && revealedKey ? revealedKey.slice(15) : '••••••••••••••••'} ) : ( {apiKey.api_key} )}
{/* Toggle button */} {isSecret && (