This commit is contained in:
Stephen Zhou 2026-05-08 17:24:18 +08:00
parent 10e567ebc6
commit ceec4b4962
No known key found for this signature in database
4 changed files with 55 additions and 71 deletions

View File

@ -13,7 +13,7 @@ import { useMutation } from '@tanstack/react-query'
import { useSetAtom } from 'jotai'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { consoleClient, consoleQuery } from '@/service/client'
import { consoleQuery } from '@/service/client'
import { createdDeveloperApiTokenAtom } from '../../store'
import { environmentName } from '../../utils'
import { useCopyFeedback } from './use-copy-feedback'
@ -25,21 +25,10 @@ function ApiKeyRow({ appInstanceId, apiKey }: {
const { t } = useTranslation('deployments')
const { copied, showCopied } = useCopyFeedback()
const revokeApiKey = useMutation(consoleQuery.enterprise.appDeploy.deleteDeveloperApiKey.mutationOptions())
const revealApiKey = useMutation(consoleQuery.enterprise.appDeploy.revealDeveloperApiKey.mutationOptions())
const displayValue = apiKey.maskedKey || apiKey.id || '—'
const environmentLabel = environmentName(apiKey.environment)
async function revealApiKey(apiKeyId: string) {
const response = await consoleClient.enterprise.appDeploy.revealDeveloperApiKey({
params: {
appInstanceId,
apiKeyId,
},
})
if (!response.token)
throw new Error('Reveal developer API key did not return a token.')
return response.token
}
function handleRevoke() {
if (!apiKey.id)
return
@ -57,7 +46,16 @@ function ApiKeyRow({ appInstanceId, apiKey }: {
return
try {
const token = await revealApiKey(apiKey.id)
const response = await revealApiKey.mutateAsync({
params: {
appInstanceId,
apiKeyId: apiKey.id,
},
})
if (!response.token)
throw new Error('Reveal developer API key did not return a token.')
const token = response.token
await navigator.clipboard.writeText(token)
showCopied()
toast.success(t('access.copyToast'))

View File

@ -1,19 +1,26 @@
'use client'
import type {
ConsoleEnvironment,
EnvironmentAccessRow,
} from '@dify/contracts/enterprise/types.gen'
import { Switch } from '@langgenius/dify-ui/switch'
import { useMutation } from '@tanstack/react-query'
import { useMutation, useQuery } from '@tanstack/react-query'
import { useAtomValue, useSetAtom } from 'jotai'
import { useTranslation } from 'react-i18next'
import { consoleQuery } from '@/service/client'
import { createdDeveloperApiTokenAtom } from '../../store'
import { ApiKeyGenerateMenu, ApiKeyList } from './api-keys'
import { CopyPill, Section } from './common'
import { useAccessEnvironmentScope } from './use-access-environment-scope'
type DeveloperApiSectionProps = {
appInstanceId: string
}
function permissionEnvironment(row: EnvironmentAccessRow): ConsoleEnvironment | undefined {
return row.environment?.id ? row.environment : undefined
}
function DeveloperApiSwitch({ appInstanceId, checked }: {
appInstanceId: string
checked: boolean
@ -78,10 +85,17 @@ export function DeveloperApiSection({
appInstanceId,
}: DeveloperApiSectionProps) {
const { t } = useTranslation('deployments')
const { accessConfig, environments } = useAccessEnvironmentScope(appInstanceId)
const { data: accessConfig } = useQuery(consoleQuery.enterprise.appDeploy.getAppInstanceAccess.queryOptions({
input: {
params: { appInstanceId },
},
}))
const apiEnabled = accessConfig?.developerApi?.enabled ?? false
const apiUrl = accessConfig?.developerApi?.apiUrl
const apiKeys = accessConfig?.developerApi?.apiKeys ?? []
const environments = accessConfig?.permissions
?.map(permissionEnvironment)
.filter((environment): environment is ConsoleEnvironment => Boolean(environment)) ?? []
return (
<Section

View File

@ -1,26 +1,41 @@
'use client'
import type {
EnvironmentAccessRow,
} from '@dify/contracts/enterprise/types.gen'
import { useQuery } from '@tanstack/react-query'
import { useTranslation } from 'react-i18next'
import { consoleQuery } from '@/service/client'
import { Section } from './common'
import { EnvironmentPermissionRow } from './permissions'
import { useAccessEnvironmentScope } from './use-access-environment-scope'
type AccessPermissionsSectionProps = {
appInstanceId: string
}
function hasEnvironment(row: EnvironmentAccessRow): row is EnvironmentAccessRow & {
environment: NonNullable<EnvironmentAccessRow['environment']>
} {
return Boolean(row.environment?.id)
}
export function AccessPermissionsSection({
appInstanceId,
}: AccessPermissionsSectionProps) {
const { t } = useTranslation('deployments')
const { environments, policies } = useAccessEnvironmentScope(appInstanceId)
const { data: accessConfig } = useQuery(consoleQuery.enterprise.appDeploy.getAppInstanceAccess.queryOptions({
input: {
params: { appInstanceId },
},
}))
const permissionRows = accessConfig?.permissions?.filter(hasEnvironment) ?? []
return (
<Section
title={t('access.permissions.title')}
description={t('access.permissions.description')}
>
{environments.length === 0
{permissionRows.length === 0
? (
<div className="rounded-lg border border-dashed border-components-panel-border bg-components-panel-bg-blur px-4 py-6 text-center system-sm-regular text-text-tertiary">
{t('access.runAccess.noEnvs')}
@ -28,17 +43,14 @@ export function AccessPermissionsSection({
)
: (
<div className="flex flex-col gap-3">
{environments.map((env) => {
const policy = policies.find(item => item.environment?.id === env.id)
return (
<EnvironmentPermissionRow
key={env.id}
appInstanceId={appInstanceId}
environment={env}
summaryPolicy={policy}
/>
)
})}
{permissionRows.map(row => (
<EnvironmentPermissionRow
key={row.environment.id}
appInstanceId={appInstanceId}
environment={row.environment}
summaryPolicy={row}
/>
))}
</div>
)}
</Section>

View File

@ -1,40 +0,0 @@
import type {
ConsoleEnvironment,
EnvironmentAccessRow,
} from '@dify/contracts/enterprise/types.gen'
import { useQuery } from '@tanstack/react-query'
import { consoleQuery } from '@/service/client'
import { deployedRows } from '../../utils'
const EMPTY_ACCESS_PERMISSIONS: EnvironmentAccessRow[] = []
function uniqueEnvironments(environments: (ConsoleEnvironment | undefined)[]) {
return environments.filter((environment, index): environment is ConsoleEnvironment => {
if (!environment?.id)
return false
return environments.findIndex(candidate => candidate?.id === environment.id) === index
})
}
export function useAccessEnvironmentScope(appInstanceId: string) {
const appInput = { params: { appInstanceId } }
const { data: accessConfig } = useQuery(consoleQuery.enterprise.appDeploy.getAppInstanceAccess.queryOptions({
input: appInput,
}))
const { data: environmentDeployments } = useQuery(consoleQuery.enterprise.appDeploy.listRuntimeInstances.queryOptions({
input: appInput,
}))
const deploymentRows = deployedRows(environmentDeployments?.data)
const policies = accessConfig?.permissions ?? EMPTY_ACCESS_PERMISSIONS
const environments = uniqueEnvironments([
...deploymentRows.map(row => row.environment),
...policies.map(policy => policy.environment),
...(accessConfig?.accessChannels?.webappRows?.map(row => row.environment) ?? []),
])
return {
accessConfig,
environments,
policies,
}
}