Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
D
dify
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ai-tech
dify
Commits
d44b05a9
Unverified
Commit
d44b05a9
authored
Feb 28, 2024
by
Yeuoly
Committed by
GitHub
Feb 28, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: support auth type like basic bearer and custom (#2613)
parent
5bd3b02b
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
122 additions
and
10 deletions
+122
-10
api_tool_provider.py
api/core/tools/provider/api_tool_provider.py
+15
-0
api_tool.py
api/core/tools/tool/api_tool.py
+11
-0
config-credentials.tsx
...tools/edit-custom-collection-modal/config-credentials.tsx
+48
-8
index.tsx
...p/components/tools/edit-custom-collection-modal/index.tsx
+4
-1
index.tsx
web/app/components/tools/tool-list/index.tsx
+5
-1
types.ts
web/app/components/tools/types.ts
+7
-0
tools.ts
web/i18n/en-US/tools.ts
+9
-0
tools.ts
web/i18n/pt-BR/tools.ts
+7
-0
tools.ts
web/i18n/uk-UA/tools.ts
+7
-0
tools.ts
web/i18n/zh-Hans/tools.ts
+9
-0
No files found.
api/core/tools/provider/api_tool_provider.py
View file @
d44b05a9
...
@@ -55,6 +55,21 @@ class ApiBasedToolProviderController(ToolProviderController):
...
@@ -55,6 +55,21 @@ class ApiBasedToolProviderController(ToolProviderController):
en_US
=
'The api key'
,
en_US
=
'The api key'
,
zh_Hans
=
'api key的值'
zh_Hans
=
'api key的值'
)
)
),
'api_key_header_prefix'
:
ToolProviderCredentials
(
name
=
'api_key_header_prefix'
,
required
=
False
,
default
=
'basic'
,
type
=
ToolProviderCredentials
.
CredentialsType
.
SELECT
,
help
=
I18nObject
(
en_US
=
'The prefix of the api key header'
,
zh_Hans
=
'api key header 的前缀'
),
options
=
[
ToolCredentialsOption
(
value
=
'basic'
,
label
=
I18nObject
(
en_US
=
'Basic'
,
zh_Hans
=
'Basic'
)),
ToolCredentialsOption
(
value
=
'bearer'
,
label
=
I18nObject
(
en_US
=
'Bearer'
,
zh_Hans
=
'Bearer'
)),
ToolCredentialsOption
(
value
=
'custom'
,
label
=
I18nObject
(
en_US
=
'Custom'
,
zh_Hans
=
'Custom'
))
]
)
)
}
}
elif
auth_type
==
ApiProviderAuthType
.
NONE
:
elif
auth_type
==
ApiProviderAuthType
.
NONE
:
...
...
api/core/tools/tool/api_tool.py
View file @
d44b05a9
...
@@ -62,6 +62,17 @@ class ApiTool(Tool):
...
@@ -62,6 +62,17 @@ class ApiTool(Tool):
if
'api_key_value'
not
in
credentials
:
if
'api_key_value'
not
in
credentials
:
raise
ToolProviderCredentialValidationError
(
'Missing api_key_value'
)
raise
ToolProviderCredentialValidationError
(
'Missing api_key_value'
)
elif
not
isinstance
(
credentials
[
'api_key_value'
],
str
):
raise
ToolProviderCredentialValidationError
(
'api_key_value must be a string'
)
if
'api_key_header_prefix'
in
credentials
:
api_key_header_prefix
=
credentials
[
'api_key_header_prefix'
]
if
api_key_header_prefix
==
'basic'
:
credentials
[
'api_key_value'
]
=
f
'Basic {credentials["api_key_value"]}'
elif
api_key_header_prefix
==
'bearer'
:
credentials
[
'api_key_value'
]
=
f
'Bearer {credentials["api_key_value"]}'
elif
api_key_header_prefix
==
'custom'
:
pass
headers
[
api_key_header
]
=
credentials
[
'api_key_value'
]
headers
[
api_key_header
]
=
credentials
[
'api_key_value'
]
...
...
web/app/components/tools/edit-custom-collection-modal/config-credentials.tsx
View file @
d44b05a9
...
@@ -3,11 +3,13 @@ import type { FC } from 'react'
...
@@ -3,11 +3,13 @@ import type { FC } from 'react'
import
React
from
'react'
import
React
from
'react'
import
{
useTranslation
}
from
'react-i18next'
import
{
useTranslation
}
from
'react-i18next'
import
cn
from
'classnames'
import
cn
from
'classnames'
import
Tooltip
from
'../../base/tooltip'
import
{
HelpCircle
}
from
'../../base/icons/src/vender/line/general'
import
type
{
Credential
}
from
'@/app/components/tools/types'
import
type
{
Credential
}
from
'@/app/components/tools/types'
import
Drawer
from
'@/app/components/base/drawer-plus'
import
Drawer
from
'@/app/components/base/drawer-plus'
import
Button
from
'@/app/components/base/button'
import
Button
from
'@/app/components/base/button'
import
Radio
from
'@/app/components/base/radio/ui'
import
Radio
from
'@/app/components/base/radio/ui'
import
{
AuthType
}
from
'@/app/components/tools/types'
import
{
Auth
HeaderPrefix
,
Auth
Type
}
from
'@/app/components/tools/types'
type
Props
=
{
type
Props
=
{
credential
:
Credential
credential
:
Credential
...
@@ -18,9 +20,9 @@ const keyClassNames = 'py-2 leading-5 text-sm font-medium text-gray-900'
...
@@ -18,9 +20,9 @@ const keyClassNames = 'py-2 leading-5 text-sm font-medium text-gray-900'
type
ItemProps
=
{
type
ItemProps
=
{
text
:
string
text
:
string
value
:
AuthType
value
:
AuthType
|
AuthHeaderPrefix
isChecked
:
boolean
isChecked
:
boolean
onClick
:
(
value
:
AuthType
)
=>
void
onClick
:
(
value
:
AuthType
|
AuthHeaderPrefix
)
=>
void
}
}
const
SelectItem
:
FC
<
ItemProps
>
=
({
text
,
value
,
isChecked
,
onClick
})
=>
{
const
SelectItem
:
FC
<
ItemProps
>
=
({
text
,
value
,
isChecked
,
onClick
})
=>
{
...
@@ -31,7 +33,6 @@ const SelectItem: FC<ItemProps> = ({ text, value, isChecked, onClick }) => {
...
@@ -31,7 +33,6 @@ const SelectItem: FC<ItemProps> = ({ text, value, isChecked, onClick }) => {
>
>
<
Radio
isChecked=
{
isChecked
}
/>
<
Radio
isChecked=
{
isChecked
}
/>
<
div
className=
'text-sm font-normal text-gray-900'
>
{
text
}
</
div
>
<
div
className=
'text-sm font-normal text-gray-900'
>
{
text
}
</
div
>
</
div
>
</
div
>
)
)
}
}
...
@@ -43,6 +44,7 @@ const ConfigCredential: FC<Props> = ({
...
@@ -43,6 +44,7 @@ const ConfigCredential: FC<Props> = ({
})
=>
{
})
=>
{
const
{
t
}
=
useTranslation
()
const
{
t
}
=
useTranslation
()
const
[
tempCredential
,
setTempCredential
]
=
React
.
useState
<
Credential
>
(
credential
)
const
[
tempCredential
,
setTempCredential
]
=
React
.
useState
<
Credential
>
(
credential
)
return
(
return
(
<
Drawer
<
Drawer
isShow
isShow
...
@@ -62,20 +64,59 @@ const ConfigCredential: FC<Props> = ({
...
@@ -62,20 +64,59 @@ const ConfigCredential: FC<Props> = ({
text=
{
t
(
'tools.createTool.authMethod.types.none'
)
}
text=
{
t
(
'tools.createTool.authMethod.types.none'
)
}
value=
{
AuthType
.
none
}
value=
{
AuthType
.
none
}
isChecked=
{
tempCredential
.
auth_type
===
AuthType
.
none
}
isChecked=
{
tempCredential
.
auth_type
===
AuthType
.
none
}
onClick=
{
value
=>
setTempCredential
({
...
tempCredential
,
auth_type
:
value
})
}
onClick=
{
value
=>
setTempCredential
({
...
tempCredential
,
auth_type
:
value
as
AuthType
})
}
/>
/>
<
SelectItem
<
SelectItem
text=
{
t
(
'tools.createTool.authMethod.types.api_key'
)
}
text=
{
t
(
'tools.createTool.authMethod.types.api_key'
)
}
value=
{
AuthType
.
apiKey
}
value=
{
AuthType
.
apiKey
}
isChecked=
{
tempCredential
.
auth_type
===
AuthType
.
apiKey
}
isChecked=
{
tempCredential
.
auth_type
===
AuthType
.
apiKey
}
onClick=
{
value
=>
setTempCredential
({
...
tempCredential
,
auth_type
:
value
})
}
onClick=
{
value
=>
setTempCredential
({
...
tempCredential
,
auth_type
:
value
as
AuthType
,
api_key_header
:
tempCredential
.
api_key_header
||
'Authorization'
,
api_key_value
:
tempCredential
.
api_key_value
||
''
,
api_key_header_prefix
:
tempCredential
.
api_key_header_prefix
||
AuthHeaderPrefix
.
custom
,
})
}
/>
/>
</
div
>
</
div
>
</
div
>
</
div
>
{
tempCredential
.
auth_type
===
AuthType
.
apiKey
&&
(
{
tempCredential
.
auth_type
===
AuthType
.
apiKey
&&
(
<>
<>
<
div
className=
{
keyClassNames
}
>
{
t
(
'tools.createTool.authHeaderPrefix.title'
)
}
</
div
>
<
div
className=
'flex space-x-3'
>
<
SelectItem
text=
{
t
(
'tools.createTool.authHeaderPrefix.types.basic'
)
}
value=
{
AuthHeaderPrefix
.
basic
}
isChecked=
{
tempCredential
.
api_key_header_prefix
===
AuthHeaderPrefix
.
basic
}
onClick=
{
value
=>
setTempCredential
({
...
tempCredential
,
api_key_header_prefix
:
value
as
AuthHeaderPrefix
})
}
/>
<
SelectItem
text=
{
t
(
'tools.createTool.authHeaderPrefix.types.bearer'
)
}
value=
{
AuthHeaderPrefix
.
bearer
}
isChecked=
{
tempCredential
.
api_key_header_prefix
===
AuthHeaderPrefix
.
bearer
}
onClick=
{
value
=>
setTempCredential
({
...
tempCredential
,
api_key_header_prefix
:
value
as
AuthHeaderPrefix
})
}
/>
<
SelectItem
text=
{
t
(
'tools.createTool.authHeaderPrefix.types.custom'
)
}
value=
{
AuthHeaderPrefix
.
custom
}
isChecked=
{
tempCredential
.
api_key_header_prefix
===
AuthHeaderPrefix
.
custom
}
onClick=
{
value
=>
setTempCredential
({
...
tempCredential
,
api_key_header_prefix
:
value
as
AuthHeaderPrefix
})
}
/>
</
div
>
<
div
>
<
div
>
<
div
className=
{
keyClassNames
}
>
{
t
(
'tools.createTool.authMethod.key'
)
}
</
div
>
<
div
className=
'flex items-center h-8 text-[13px] font-medium text-gray-900'
>
{
t
(
'tools.createTool.authMethod.key'
)
}
<
Tooltip
selector=
'model-page-system-reasoning-model-tip'
htmlContent=
{
<
div
className=
'w-[261px] text-gray-500'
>
{
t
(
'tools.createTool.authMethod.keyTooltip'
)
}
</
div
>
}
>
<
HelpCircle
className=
'ml-0.5 w-[14px] h-[14px] text-gray-400'
/>
</
Tooltip
>
</
div
>
<
input
<
input
value=
{
tempCredential
.
api_key_header
}
value=
{
tempCredential
.
api_key_header
}
onChange=
{
e
=>
setTempCredential
({
...
tempCredential
,
api_key_header
:
e
.
target
.
value
})
}
onChange=
{
e
=>
setTempCredential
({
...
tempCredential
,
api_key_header
:
e
.
target
.
value
})
}
...
@@ -83,7 +124,6 @@ const ConfigCredential: FC<Props> = ({
...
@@ -83,7 +124,6 @@ const ConfigCredential: FC<Props> = ({
placeholder=
{
t
(
'tools.createTool.authMethod.types.apiKeyPlaceholder'
)
!
}
placeholder=
{
t
(
'tools.createTool.authMethod.types.apiKeyPlaceholder'
)
!
}
/>
/>
</
div
>
</
div
>
<
div
>
<
div
>
<
div
className=
{
keyClassNames
}
>
{
t
(
'tools.createTool.authMethod.value'
)
}
</
div
>
<
div
className=
{
keyClassNames
}
>
{
t
(
'tools.createTool.authMethod.value'
)
}
</
div
>
<
input
<
input
...
...
web/app/components/tools/edit-custom-collection-modal/index.tsx
View file @
d44b05a9
...
@@ -8,7 +8,7 @@ import { clone } from 'lodash-es'
...
@@ -8,7 +8,7 @@ import { clone } from 'lodash-es'
import
cn
from
'classnames'
import
cn
from
'classnames'
import
{
LinkExternal02
,
Settings01
}
from
'../../base/icons/src/vender/line/general'
import
{
LinkExternal02
,
Settings01
}
from
'../../base/icons/src/vender/line/general'
import
type
{
Credential
,
CustomCollectionBackend
,
CustomParamSchema
,
Emoji
}
from
'../types'
import
type
{
Credential
,
CustomCollectionBackend
,
CustomParamSchema
,
Emoji
}
from
'../types'
import
{
AuthType
}
from
'../types'
import
{
Auth
HeaderPrefix
,
Auth
Type
}
from
'../types'
import
GetSchema
from
'./get-schema'
import
GetSchema
from
'./get-schema'
import
ConfigCredentials
from
'./config-credentials'
import
ConfigCredentials
from
'./config-credentials'
import
TestApi
from
'./test-api'
import
TestApi
from
'./test-api'
...
@@ -37,6 +37,7 @@ const EditCustomCollectionModal: FC<Props> = ({
...
@@ -37,6 +37,7 @@ const EditCustomCollectionModal: FC<Props> = ({
const
{
t
}
=
useTranslation
()
const
{
t
}
=
useTranslation
()
const
isAdd
=
!
payload
const
isAdd
=
!
payload
const
isEdit
=
!!
payload
const
isEdit
=
!!
payload
const
[
editFirst
,
setEditFirst
]
=
useState
(
!
isAdd
)
const
[
editFirst
,
setEditFirst
]
=
useState
(
!
isAdd
)
const
[
paramsSchemas
,
setParamsSchemas
]
=
useState
<
CustomParamSchema
[]
>
(
payload
?.
tools
||
[])
const
[
paramsSchemas
,
setParamsSchemas
]
=
useState
<
CustomParamSchema
[]
>
(
payload
?.
tools
||
[])
const
[
customCollection
,
setCustomCollection
,
getCustomCollection
]
=
useGetState
<
CustomCollectionBackend
>
(
isAdd
const
[
customCollection
,
setCustomCollection
,
getCustomCollection
]
=
useGetState
<
CustomCollectionBackend
>
(
isAdd
...
@@ -44,6 +45,8 @@ const EditCustomCollectionModal: FC<Props> = ({
...
@@ -44,6 +45,8 @@ const EditCustomCollectionModal: FC<Props> = ({
provider
:
''
,
provider
:
''
,
credentials
:
{
credentials
:
{
auth_type
:
AuthType
.
none
,
auth_type
:
AuthType
.
none
,
api_key_header
:
'Authorization'
,
api_key_header_prefix
:
AuthHeaderPrefix
.
basic
,
},
},
icon
:
{
icon
:
{
content
:
'🕵️'
,
content
:
'🕵️'
,
...
...
web/app/components/tools/tool-list/index.tsx
View file @
d44b05a9
...
@@ -3,7 +3,7 @@ import type { FC } from 'react'
...
@@ -3,7 +3,7 @@ import type { FC } from 'react'
import
React
,
{
useEffect
,
useState
}
from
'react'
import
React
,
{
useEffect
,
useState
}
from
'react'
import
{
useTranslation
}
from
'react-i18next'
import
{
useTranslation
}
from
'react-i18next'
import
cn
from
'classnames'
import
cn
from
'classnames'
import
{
CollectionType
,
LOC
}
from
'../types'
import
{
AuthHeaderPrefix
,
AuthType
,
CollectionType
,
LOC
}
from
'../types'
import
type
{
Collection
,
CustomCollectionBackend
,
Tool
}
from
'../types'
import
type
{
Collection
,
CustomCollectionBackend
,
Tool
}
from
'../types'
import
Loading
from
'../../base/loading'
import
Loading
from
'../../base/loading'
import
{
ArrowNarrowRight
}
from
'../../base/icons/src/vender/line/arrows'
import
{
ArrowNarrowRight
}
from
'../../base/icons/src/vender/line/arrows'
...
@@ -53,6 +53,10 @@ const ToolList: FC<Props> = ({
...
@@ -53,6 +53,10 @@ const ToolList: FC<Props> = ({
(
async
()
=>
{
(
async
()
=>
{
if
(
collection
.
type
===
CollectionType
.
custom
)
{
if
(
collection
.
type
===
CollectionType
.
custom
)
{
const
res
=
await
fetchCustomCollection
(
collection
.
name
)
const
res
=
await
fetchCustomCollection
(
collection
.
name
)
if
(
res
.
credentials
.
auth_type
===
AuthType
.
apiKey
&&
!
res
.
credentials
.
api_key_header_prefix
)
{
if
(
res
.
credentials
.
api_key_value
)
res
.
credentials
.
api_key_header_prefix
=
AuthHeaderPrefix
.
custom
}
setCustomCollection
({
setCustomCollection
({
...
res
,
...
res
,
provider
:
collection
.
name
,
provider
:
collection
.
name
,
...
...
web/app/components/tools/types.ts
View file @
d44b05a9
...
@@ -9,10 +9,17 @@ export enum AuthType {
...
@@ -9,10 +9,17 @@ export enum AuthType {
apiKey
=
'api_key'
,
apiKey
=
'api_key'
,
}
}
export
enum
AuthHeaderPrefix
{
basic
=
'basic'
,
bearer
=
'bearer'
,
custom
=
'custom'
,
}
export
type
Credential
=
{
export
type
Credential
=
{
'auth_type'
:
AuthType
'auth_type'
:
AuthType
'api_key_header'
?:
string
'api_key_header'
?:
string
'api_key_value'
?:
string
'api_key_value'
?:
string
'api_key_header_prefix'
?:
AuthHeaderPrefix
}
}
export
enum
CollectionType
{
export
enum
CollectionType
{
...
...
web/i18n/en-US/tools.ts
View file @
d44b05a9
...
@@ -51,6 +51,7 @@ const translation = {
...
@@ -51,6 +51,7 @@ const translation = {
authMethod
:
{
authMethod
:
{
title
:
'Authorization method'
,
title
:
'Authorization method'
,
type
:
'Authorization type'
,
type
:
'Authorization type'
,
keyTooltip
:
'Http Header Key, You can leave it with "Authorization" if you have no idea what it is or set it to a custom value'
,
types
:
{
types
:
{
none
:
'None'
,
none
:
'None'
,
api_key
:
'API Key'
,
api_key
:
'API Key'
,
...
@@ -60,6 +61,14 @@ const translation = {
...
@@ -60,6 +61,14 @@ const translation = {
key
:
'Key'
,
key
:
'Key'
,
value
:
'Value'
,
value
:
'Value'
,
},
},
authHeaderPrefix
:
{
title
:
'Auth Type'
,
types
:
{
basic
:
'Basic'
,
bearer
:
'Bearer'
,
custom
:
'Custom'
,
},
},
privacyPolicy
:
'Privacy policy'
,
privacyPolicy
:
'Privacy policy'
,
privacyPolicyPlaceholder
:
'Please enter privacy policy'
,
privacyPolicyPlaceholder
:
'Please enter privacy policy'
,
},
},
...
...
web/i18n/pt-BR/tools.ts
View file @
d44b05a9
...
@@ -58,6 +58,13 @@ const translation = {
...
@@ -58,6 +58,13 @@ const translation = {
key
:
'Chave'
,
key
:
'Chave'
,
value
:
'Valor'
,
value
:
'Valor'
,
},
},
authHeaderPrefix
:
{
types
:
{
basic
:
'Basic'
,
bearer
:
'Bearer'
,
custom
:
'Custom'
,
},
},
privacyPolicy
:
'Política de Privacidade'
,
privacyPolicy
:
'Política de Privacidade'
,
privacyPolicyPlaceholder
:
'Digite a política de privacidade'
,
privacyPolicyPlaceholder
:
'Digite a política de privacidade'
,
},
},
...
...
web/i18n/uk-UA/tools.ts
View file @
d44b05a9
...
@@ -58,6 +58,13 @@ const translation = {
...
@@ -58,6 +58,13 @@ const translation = {
key
:
'Ключ'
,
key
:
'Ключ'
,
value
:
'Значення'
,
value
:
'Значення'
,
},
},
authHeaderPrefix
:
{
types
:
{
basic
:
'Basic'
,
bearer
:
'Bearer'
,
custom
:
'Custom'
,
},
},
privacyPolicy
:
'Політика конфіденційності'
,
privacyPolicy
:
'Політика конфіденційності'
,
privacyPolicyPlaceholder
:
'Введіть політику конфіденційності'
,
privacyPolicyPlaceholder
:
'Введіть політику конфіденційності'
,
},
},
...
...
web/i18n/zh-Hans/tools.ts
View file @
d44b05a9
...
@@ -51,6 +51,7 @@ const translation = {
...
@@ -51,6 +51,7 @@ const translation = {
authMethod
:
{
authMethod
:
{
title
:
'鉴权方法'
,
title
:
'鉴权方法'
,
type
:
'鉴权类型'
,
type
:
'鉴权类型'
,
keyTooltip
:
'HTTP 头部名称,如果你不知道是什么,可以将其保留为 Authorization 或设置为自定义值'
,
types
:
{
types
:
{
none
:
'无'
,
none
:
'无'
,
api_key
:
'API Key'
,
api_key
:
'API Key'
,
...
@@ -60,6 +61,14 @@ const translation = {
...
@@ -60,6 +61,14 @@ const translation = {
key
:
'键'
,
key
:
'键'
,
value
:
'值'
,
value
:
'值'
,
},
},
authHeaderPrefix
:
{
title
:
'鉴权头部前缀'
,
types
:
{
basic
:
'Basic'
,
bearer
:
'Bearer'
,
custom
:
'Custom'
,
},
},
privacyPolicy
:
'隐私协议'
,
privacyPolicy
:
'隐私协议'
,
privacyPolicyPlaceholder
:
'请输入隐私协议'
,
privacyPolicyPlaceholder
:
'请输入隐私协议'
,
},
},
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment