import { PermissionAction } from '@supabase/shared-types/out/constants' import { Search } from 'lucide-react' import { useRef, useState } from 'react' import { toast } from 'sonner' import { useParams } from 'common' import AlertError from 'components/ui/AlertError' import NoPermission from 'components/ui/NoPermission' import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import { useSecretsDeleteMutation } from 'data/secrets/secrets-delete-mutation' import { useSecretsQuery } from 'data/secrets/secrets-query' import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions' import { handleErrorOnDelete, useQueryStateWithSelect } from 'hooks/misc/useQueryStateWithSelect' import { Badge, Card, Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from 'ui' import { Input } from 'ui-patterns/DataInputs/Input' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import AddNewSecretForm from './AddNewSecretForm' import EdgeFunctionSecret from './EdgeFunctionSecret' import { EditSecretSheet } from './EditSecretSheet' export const EdgeFunctionSecrets = () => { const { ref: projectRef } = useParams() const [searchString, setSearchString] = useState('') // Track the ID being deleted to exclude it from error checking const deletingSecretNameRef = useRef(null) const { can: canReadSecrets, isLoading: isLoadingSecretsPermissions } = useAsyncCheckPermissions( PermissionAction.FUNCTIONS_SECRET_READ, '*' ) const { can: canUpdateSecrets } = useAsyncCheckPermissions(PermissionAction.SECRETS_WRITE, '*') const { data, error, isLoading, isSuccess, isError } = useSecretsQuery( { projectRef: projectRef, }, { enabled: canReadSecrets } ) const { setValue: setSelectedSecretToEdit, value: selectedSecretToEdit } = useQueryStateWithSelect({ urlKey: 'edit', select: (secretName: string) => secretName ? data?.find((secret) => secret.name === secretName) : undefined, enabled: !!data, onError: () => toast.error(`Secret not found`), }) const { setValue: setSelectedSecretToDelete, value: selectedSecretToDelete } = useQueryStateWithSelect({ urlKey: 'delete', select: (secretName: string) => secretName ? data?.find((secret) => secret.name === secretName) : undefined, enabled: !!data, onError: (_error, selectedId) => handleErrorOnDelete(deletingSecretNameRef, selectedId, `Secret not found`), }) const { mutate: deleteSecret, isPending: isDeleting } = useSecretsDeleteMutation({ onSuccess: (_, variables) => { toast.success(`Successfully deleted ${variables.secrets[0]}`) setSelectedSecretToDelete(null) }, onError: () => { deletingSecretNameRef.current = null }, }) const secrets = searchString.length > 0 ? data?.filter((secret) => secret.name.toLowerCase().includes(searchString.toLowerCase())) ?? [] : data ?? [] const headers = [ Name, Digest SHA256 , Updated at, , ] const showLoadingState = isLoadingSecretsPermissions || (canReadSecrets && isLoading) return ( <> {showLoadingState ? ( ) : !canReadSecrets ? ( ) : ( <> {isError && } {isSuccess && ( <>
{!canUpdateSecrets ? ( ) : ( )}
{canUpdateSecrets && !canReadSecrets ? ( ) : canReadSecrets ? (
setSearchString(e.target.value)} icon={} />
{headers} {secrets.length > 0 ? ( secrets.map((secret) => ( setSelectedSecretToEdit(secret.name)} onSelectDelete={() => setSelectedSecretToDelete(secret.name)} /> )) ) : secrets.length === 0 && searchString.length > 0 ? (

No results found

Your search for "{searchString}" did not return any results

) : (

No secrets created

There are no secrets associated with your project yet

)}
) : null} )} )} setSelectedSecretToEdit(null)} /> setSelectedSecretToDelete(null)} onConfirm={() => { if (selectedSecretToDelete) { deletingSecretNameRef.current = selectedSecretToDelete.name deleteSecret({ projectRef, secrets: [selectedSecretToDelete.name] }) } }} >

Before removing this secret, ensure none of your Edge Functions are actively using it. This action cannot be undone.

) }