mirror of
https://github.com/langgenius/dify.git
synced 2026-10-04 13:47:55 +08:00
fix: preserve Swagger tool authorization after refresh (#41656)
This commit is contained in:
2 files changed
+81
-4
No files matched your search
+76
-1
@@ -24,6 +24,7 @@ import { AgentTools } from '../index'
|
||||
|
||||
const toolProviderState = vi.hoisted(() => ({
|
||||
builtInTools: [] as ToolWithProvider[] | undefined,
|
||||
customTools: [] as ToolWithProvider[] | undefined,
|
||||
}))
|
||||
const pluginAuthState = vi.hoisted(() => ({
|
||||
canOAuth: true as boolean | undefined,
|
||||
@@ -159,7 +160,7 @@ vi.mock('@/app/components/header/account-setting/model-provider-page/model-modal
|
||||
|
||||
vi.mock('@/service/use-tools', () => ({
|
||||
useAllBuiltInTools: () => ({ data: toolProviderState.builtInTools }),
|
||||
useAllCustomTools: () => ({ data: [] }),
|
||||
useAllCustomTools: () => ({ data: toolProviderState.customTools }),
|
||||
useAllWorkflowTools: () => ({ data: [] }),
|
||||
useAllMCPTools: () => ({ data: [] }),
|
||||
useInvalidateAllBuiltInTools: () => pluginInstallState.invalidateBuiltInTools,
|
||||
@@ -292,6 +293,29 @@ const reflectedUnauthorizedOAuthCredentialTypeDraft = {
|
||||
],
|
||||
} satisfies AgentSoulConfigFormState
|
||||
|
||||
const reflectedAuthorizedSwaggerDraft = {
|
||||
...defaultAgentSoulConfigFormState,
|
||||
tools: [
|
||||
{
|
||||
id: 'weather-api',
|
||||
kind: 'provider',
|
||||
name: 'weather-api',
|
||||
iconClassName: 'i-custom-public-other-default-tool-icon',
|
||||
providerType: CollectionType.custom,
|
||||
credentialType: 'unauthorized',
|
||||
credentialVariant: 'unauthorized',
|
||||
actions: [
|
||||
{
|
||||
id: 'weather-api:forecast',
|
||||
name: 'forecast',
|
||||
toolName: 'forecast',
|
||||
description: '',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
} satisfies AgentSoulConfigFormState
|
||||
|
||||
const googleProvider = {
|
||||
id: 'google',
|
||||
name: 'google',
|
||||
@@ -384,6 +408,40 @@ const duckDuckGoProvider = {
|
||||
],
|
||||
} satisfies ToolWithProvider
|
||||
|
||||
const authorizedSwaggerProvider = {
|
||||
...googleProvider,
|
||||
id: 'weather-api',
|
||||
name: 'weather-api',
|
||||
label: {
|
||||
en_US: 'Weather API',
|
||||
zh_Hans: '天气 API',
|
||||
},
|
||||
type: CollectionType.custom,
|
||||
team_credentials: {
|
||||
api_key: {
|
||||
type: 'secret-input',
|
||||
},
|
||||
},
|
||||
is_team_authorization: true,
|
||||
tools: [
|
||||
{
|
||||
name: 'forecast',
|
||||
author: 'Weather API',
|
||||
label: {
|
||||
en_US: 'Forecast',
|
||||
zh_Hans: '天气预报',
|
||||
},
|
||||
description: {
|
||||
en_US: 'Get the weather forecast.',
|
||||
zh_Hans: '获取天气预报。',
|
||||
},
|
||||
parameters: [],
|
||||
labels: [],
|
||||
output_schema: {},
|
||||
},
|
||||
],
|
||||
} satisfies ToolWithProvider
|
||||
|
||||
function renderAgentTools(initialDraft: AgentSoulConfigFormState = agentToolsDraft) {
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
@@ -464,6 +522,7 @@ describe('AgentTools', () => {
|
||||
cleanup()
|
||||
vi.clearAllMocks()
|
||||
toolProviderState.builtInTools = []
|
||||
toolProviderState.customTools = []
|
||||
pluginAuthState.canOAuth = true
|
||||
pluginAuthState.canApiKey = false
|
||||
pluginAuthState.credentials = []
|
||||
@@ -724,6 +783,22 @@ describe('AgentTools', () => {
|
||||
expect(screen.queryByText('tools.notAuthorized')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should use current team authorization for reflected Swagger API tools', () => {
|
||||
toolProviderState.customTools = [authorizedSwaggerProvider]
|
||||
renderAgentTools(reflectedAuthorizedSwaggerDraft)
|
||||
|
||||
expect(
|
||||
screen.getByRole('button', {
|
||||
name: 'Weather API',
|
||||
}),
|
||||
).toBeInTheDocument()
|
||||
expect(
|
||||
screen.queryByRole('button', {
|
||||
name: 'tools.notAuthorized',
|
||||
}),
|
||||
).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should keep provider credential metadata display-only without dirtying the composer draft', () => {
|
||||
toolProviderState.builtInTools = [duckDuckGoProvider]
|
||||
const { store } = renderAgentToolsWithStore(reflectedUnauthorizedNoCredentialDraft)
|
||||
|
||||
@@ -215,11 +215,13 @@ export function getProviderCredentialVariant(
|
||||
) {
|
||||
if (!providerCredentialType) return 'none' as const
|
||||
|
||||
// Team-scoped credentials have no credential reference in the saved agent config,
|
||||
// so the current provider authorization must override a reflected unauthorized state.
|
||||
if (tool.credentialId || provider.is_team_authorization) return 'authorized' as const
|
||||
|
||||
if (tool.credentialVariant !== 'none') return tool.credentialVariant
|
||||
|
||||
return tool.credentialId || provider.is_team_authorization
|
||||
? ('authorized' as const)
|
||||
: ('unauthorized' as const)
|
||||
return 'unauthorized' as const
|
||||
}
|
||||
|
||||
export type AgentToolPublishIssue = {
|
||||
|
||||
Reference in new issue
Block a user