import type { ApiKeyItem } from '@dify/contracts/api/console/apps/types.gen' import type { EnvironmentApiKey } from '@dify/contracts/enterprise-app-deploy/types.gen' import { AlertDialogTrigger } from '@langgenius/dify-ui/alert-dialog' import { IconButton } from '@langgenius/dify-ui/icon-button' import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { useTranslation } from 'react-i18next' import { CopyFeedback } from '@/app/components/base/copy-feedback' import useTimestamp from '@/hooks/use-timestamp' import { maskApiKey } from './mask-api-key' export type ApiKeyDeleteTarget = Pick type ApiKeyTableProps = { apiKeys: Array canManage: boolean // Dataset keys carry a knowledge-base scope; enable the SCOPE column to surface it. showScope?: boolean allowCopy?: boolean } export function ApiKeyTable({ apiKeys, canManage, showScope = false, allowCopy = false, }: ApiKeyTableProps) { const { t } = useTranslation(['appApi', 'common', 'time']) const { formatTime } = useTimestamp() // Only dataset keys expose bound knowledge bases (legacy dataset_ids plus KnowledgeFS // knowledge_space_ids); both empty/absent means the key can access every knowledge base // in the workspace. const scopeLabel = (apiKey: ApiKeyItem | EnvironmentApiKey) => { const datasetIds = 'dataset_ids' in apiKey ? apiKey.dataset_ids : undefined const knowledgeSpaceIds = 'knowledge_space_ids' in apiKey ? apiKey.knowledge_space_ids : undefined const count = (datasetIds?.length ?? 0) + (knowledgeSpaceIds?.length ?? 0) if (!count) return t(($) => $['apiKeyModal.scopeAllDatasets'], { ns: 'appApi' }) return t(($) => $['apiKeyModal.scopeCount'], { ns: 'appApi', count }) } return (
{showScope && ( )} {apiKeys.length === 0 && ( )} {apiKeys.map((apiKey) => ( {showScope && } ))}
{t(($) => $['apiKeyModal.apiSecretKey'], { ns: 'appApi' })}
{t(($) => $['apiKeyModal.secretKey'], { ns: 'appApi' })} {t(($) => $['apiKeyModal.scope'], { ns: 'appApi' })} {t(($) => $['apiKeyModal.created'], { ns: 'appApi' })} {t(($) => $['apiKeyModal.lastUsed'], { ns: 'appApi' })} {t(($) => $['apiKeyModal.actions'], { ns: 'appApi' })}
{t(($) => $['apiKeyModal.emptyState'], { ns: 'appApi' })}
{maskApiKey(apiKey.token)}{scopeLabel(apiKey)} {apiKey.created_at == null ? '—' : formatTime( apiKey.created_at, t(($) => $['dateFormats.withSeconds'], { ns: 'time' }) as string, )} {apiKey.last_used_at ? formatTime( Number(apiKey.last_used_at), t(($) => $['dateFormats.withSeconds'], { ns: 'time' }) as string, ) : t(($) => $.never, { ns: 'appApi' })}
{allowCopy && } {canManage && ( $['operation.delete'], { ns: 'common' })} ${maskApiKey(apiKey.token)}`} > } /> } /> {t(($) => $['operation.delete'], { ns: 'common' })} )}
) }