mirror of https://github.com/langgenius/dify.git
enterprise model credential
This commit is contained in:
parent
ca0d04b841
commit
b3e5a4ecb7
|
|
@ -187,7 +187,7 @@ export type Credential = {
|
|||
credential_id: string
|
||||
credential_name?: string
|
||||
from_enterprise?: boolean
|
||||
allowed_to_use?: boolean
|
||||
not_allowed_to_use?: boolean
|
||||
}
|
||||
|
||||
export type CustomModel = {
|
||||
|
|
@ -242,6 +242,7 @@ export type ModelProvider = {
|
|||
current_quota_type: CurrentSystemQuotaTypeEnum
|
||||
quota_configurations: QuotaConfiguration[]
|
||||
}
|
||||
allow_custom_token?: boolean
|
||||
}
|
||||
|
||||
export type Model = {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import type {
|
|||
ModelProvider,
|
||||
} from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import { ConfigurationMethodEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
|
||||
type AddCredentialInLoadBalancingProps = {
|
||||
provider: ModelProvider
|
||||
|
|
@ -35,11 +36,13 @@ const AddCredentialInLoadBalancing = ({
|
|||
available_credentials,
|
||||
} = modelCredential
|
||||
const customModel = configurationMethod === ConfigurationMethodEnum.customizableModel
|
||||
const notAllowCustomCredential = provider.allow_custom_token === false
|
||||
const renderTrigger = useCallback((open?: boolean) => {
|
||||
return (
|
||||
const Item = (
|
||||
<div className={cn(
|
||||
'system-sm-medium flex h-8 items-center rounded-lg px-3 text-text-accent hover:bg-state-base-hover',
|
||||
open && 'bg-state-base-hover',
|
||||
notAllowCustomCredential && 'cursor-not-allowed opacity-50',
|
||||
)}>
|
||||
<RiAddLine className='mr-2 h-4 w-4' />
|
||||
{
|
||||
|
|
@ -49,7 +52,19 @@ const AddCredentialInLoadBalancing = ({
|
|||
}
|
||||
</div>
|
||||
)
|
||||
}, [])
|
||||
|
||||
if (notAllowCustomCredential) {
|
||||
return (
|
||||
<Tooltip
|
||||
asChild
|
||||
popupContent={t('plugin.auth.credentialUnavailable')}
|
||||
>
|
||||
{Item}
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
return Item
|
||||
}, [notAllowCustomCredential, t, customModel])
|
||||
|
||||
return (
|
||||
<Authorized
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import {
|
|||
useCustomModels,
|
||||
} from './hooks'
|
||||
import cn from '@/utils/classnames'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
|
||||
type AddCustomModelProps = {
|
||||
provider: ModelProvider,
|
||||
|
|
@ -41,8 +42,9 @@ const AddCustomModel = ({
|
|||
const handleClick = useCallback(() => {
|
||||
handleOpenModal()
|
||||
}, [handleOpenModal])
|
||||
const notAllowCustomCredential = provider.allow_custom_token === false
|
||||
const ButtonComponent = useMemo(() => {
|
||||
return (
|
||||
const Item = (
|
||||
<Button
|
||||
variant='ghost-accent'
|
||||
size='small'
|
||||
|
|
@ -52,10 +54,21 @@ const AddCustomModel = ({
|
|||
{t('common.modelProvider.addModel')}
|
||||
</Button>
|
||||
)
|
||||
}, [handleClick])
|
||||
if (notAllowCustomCredential) {
|
||||
return (
|
||||
<Tooltip
|
||||
asChild
|
||||
popupContent={t('plugin.auth.credentialUnavailable')}
|
||||
>
|
||||
{Item}
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
return Item
|
||||
}, [handleClick, notAllowCustomCredential, t])
|
||||
|
||||
const renderTrigger = useCallback((open?: boolean) => {
|
||||
return (
|
||||
const Item = (
|
||||
<Button
|
||||
variant='ghost'
|
||||
size='small'
|
||||
|
|
@ -65,7 +78,18 @@ const AddCustomModel = ({
|
|||
{t('common.modelProvider.addModel')}
|
||||
</Button>
|
||||
)
|
||||
}, [t])
|
||||
if (notAllowCustomCredential) {
|
||||
return (
|
||||
<Tooltip
|
||||
asChild
|
||||
popupContent={t('plugin.auth.credentialUnavailable')}
|
||||
>
|
||||
{Item}
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
return Item
|
||||
}, [notAllowCustomCredential, t])
|
||||
|
||||
if (noModels)
|
||||
return ButtonComponent
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ type AuthorizedItemProps = {
|
|||
credentials: Credential[]
|
||||
onItemClick?: (credential: Credential, model?: CustomModel) => void
|
||||
enableAddModelCredential?: boolean
|
||||
notAllowCustomCredential?: boolean
|
||||
}
|
||||
export const AuthorizedItem = ({
|
||||
model,
|
||||
|
|
@ -36,6 +37,7 @@ export const AuthorizedItem = ({
|
|||
selectedCredentialId,
|
||||
onItemClick,
|
||||
enableAddModelCredential,
|
||||
notAllowCustomCredential,
|
||||
}: AuthorizedItemProps) => {
|
||||
const { t } = useTranslation()
|
||||
const handleEdit = useCallback((credential?: Credential) => {
|
||||
|
|
@ -61,7 +63,7 @@ export const AuthorizedItem = ({
|
|||
{title ?? model?.model}
|
||||
</div>
|
||||
{
|
||||
enableAddModelCredential && (
|
||||
enableAddModelCredential && !notAllowCustomCredential && (
|
||||
<Tooltip
|
||||
asChild
|
||||
popupContent={t('common.modelProvider.auth.addModelCredential')}
|
||||
|
|
|
|||
|
|
@ -44,13 +44,16 @@ const CredentialItem = ({
|
|||
return !(disableRename && disableEdit && disableDelete)
|
||||
}, [disableRename, disableEdit, disableDelete])
|
||||
|
||||
return (
|
||||
const Item = (
|
||||
<div
|
||||
key={credential.credential_id}
|
||||
className={cn(
|
||||
'group flex h-8 items-center rounded-lg p-1 hover:bg-state-base-hover',
|
||||
(disabled || credential.not_allowed_to_use) && 'cursor-not-allowed opacity-50',
|
||||
)}
|
||||
onClick={() => {
|
||||
if (disabled || credential.not_allowed_to_use)
|
||||
return
|
||||
onItemClick?.(credential)
|
||||
}}
|
||||
>
|
||||
|
|
@ -85,7 +88,7 @@ const CredentialItem = ({
|
|||
showAction && (
|
||||
<div className='ml-2 hidden shrink-0 items-center group-hover:flex'>
|
||||
{
|
||||
!disableEdit && (
|
||||
!disableEdit && !credential.not_allowed_to_use && !credential.from_enterprise && (
|
||||
<Tooltip popupContent={t('common.operation.edit')}>
|
||||
<ActionButton
|
||||
disabled={disabled}
|
||||
|
|
@ -100,7 +103,7 @@ const CredentialItem = ({
|
|||
)
|
||||
}
|
||||
{
|
||||
!disableDelete && (
|
||||
!disableDelete && !credential.from_enterprise && (
|
||||
<Tooltip popupContent={t('common.operation.delete')}>
|
||||
<ActionButton
|
||||
className='hover:bg-transparent'
|
||||
|
|
@ -120,6 +123,15 @@ const CredentialItem = ({
|
|||
}
|
||||
</div>
|
||||
)
|
||||
|
||||
if (credential.not_allowed_to_use) {
|
||||
return (
|
||||
<Tooltip popupContent={t('plugin.auth.customCredentialUnavailable')}>
|
||||
{Item}
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
return Item
|
||||
}
|
||||
|
||||
export default memo(CredentialItem)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import {
|
||||
memo,
|
||||
useCallback,
|
||||
useMemo,
|
||||
useState,
|
||||
} from 'react'
|
||||
import {
|
||||
|
|
@ -28,6 +29,7 @@ import type {
|
|||
} from '../../declarations'
|
||||
import { useAuth } from '../hooks'
|
||||
import AuthorizedItem from './authorized-item'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
|
||||
type AuthorizedProps = {
|
||||
provider: ModelProvider,
|
||||
|
|
@ -107,6 +109,33 @@ const Authorized = ({
|
|||
|
||||
setMergedIsOpen(false)
|
||||
}, [handleActiveCredential, onItemClick, setMergedIsOpen])
|
||||
const notAllowCustomCredential = provider.allow_custom_token === false
|
||||
|
||||
const Trigger = useMemo(() => {
|
||||
const hasValidCredential = items.some(item => item.credentials.some(credential => !credential.not_allowed_to_use))
|
||||
const Item = (
|
||||
<Button
|
||||
className='grow'
|
||||
size='small'
|
||||
disabled={notAllowCustomCredential && !hasValidCredential}
|
||||
>
|
||||
<RiEqualizer2Line className='mr-1 h-3.5 w-3.5' />
|
||||
{t('common.operation.config')}
|
||||
</Button>
|
||||
)
|
||||
|
||||
if (notAllowCustomCredential && !hasValidCredential) {
|
||||
return (
|
||||
<Tooltip
|
||||
asChild
|
||||
popupContent={t('plugin.auth.credentialUnavailable')}
|
||||
>
|
||||
{Item}
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
return Item
|
||||
}, [notAllowCustomCredential, t, items])
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -118,21 +147,20 @@ const Authorized = ({
|
|||
triggerPopupSameWidth={triggerPopupSameWidth}
|
||||
>
|
||||
<PortalToFollowElemTrigger
|
||||
onClick={() => setMergedIsOpen(!mergedIsOpen)}
|
||||
onClick={() => {
|
||||
if (notAllowCustomCredential) {
|
||||
const hasValidCredential = items.some(item => item.credentials.some(credential => !credential.not_allowed_to_use))
|
||||
if (!hasValidCredential)
|
||||
return
|
||||
}
|
||||
setMergedIsOpen(!mergedIsOpen)
|
||||
}}
|
||||
asChild
|
||||
>
|
||||
{
|
||||
renderTrigger
|
||||
? renderTrigger(mergedIsOpen)
|
||||
: (
|
||||
<Button
|
||||
className='grow'
|
||||
size='small'
|
||||
>
|
||||
<RiEqualizer2Line className='mr-1 h-3.5 w-3.5' />
|
||||
{t('common.operation.config')}
|
||||
</Button>
|
||||
)
|
||||
: Trigger
|
||||
}
|
||||
</PortalToFollowElemTrigger>
|
||||
<PortalToFollowElemContent className='z-[100]'>
|
||||
|
|
@ -155,13 +183,14 @@ const Authorized = ({
|
|||
selectedCredentialId={selectedCredential?.credential_id}
|
||||
onItemClick={handleItemClick}
|
||||
enableAddModelCredential={enableAddModelCredential}
|
||||
notAllowCustomCredential={notAllowCustomCredential}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
<div className='h-[1px] bg-divider-subtle'></div>
|
||||
{
|
||||
isModelCredential && (
|
||||
isModelCredential && !notAllowCustomCredential && (
|
||||
<div
|
||||
onClick={() => handleEdit(
|
||||
undefined,
|
||||
|
|
@ -180,7 +209,7 @@ const Authorized = ({
|
|||
)
|
||||
}
|
||||
{
|
||||
!isModelCredential && (
|
||||
!isModelCredential && !notAllowCustomCredential && (
|
||||
<div className='p-2'>
|
||||
<Button
|
||||
onClick={() => handleEdit()}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ const ConfigModel = ({
|
|||
}: ConfigModelProps) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
if (loadBalancingEnabled && loadBalancingInvalid && !credentialRemoved) {
|
||||
if (loadBalancingInvalid) {
|
||||
return (
|
||||
<div
|
||||
className='system-2xs-medium-uppercase relative flex h-[18px] items-center rounded-[5px] border border-text-warning bg-components-badge-bg-dimm px-1.5 text-text-warning'
|
||||
|
|
@ -54,7 +54,7 @@ const ConfigModel = ({
|
|||
)
|
||||
}
|
||||
{
|
||||
!loadBalancingEnabled && !credentialRemoved && (
|
||||
!loadBalancingEnabled && !credentialRemoved && !loadBalancingInvalid && (
|
||||
<>
|
||||
<RiEqualizer2Line className='mr-1 h-4 w-4' />
|
||||
{t('common.operation.config')}
|
||||
|
|
@ -62,7 +62,7 @@ const ConfigModel = ({
|
|||
)
|
||||
}
|
||||
{
|
||||
loadBalancingEnabled && !loadBalancingInvalid && !credentialRemoved && (
|
||||
loadBalancingEnabled && !credentialRemoved && !loadBalancingInvalid && (
|
||||
<>
|
||||
<RiScales3Line className='mr-1 h-4 w-4' />
|
||||
{t('common.modelProvider.auth.configLoadBalancing')}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import type {
|
|||
import { ConfigurationMethodEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import Authorized from './authorized'
|
||||
import { useAuth, useCredentialStatus } from './hooks'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
|
||||
type ConfigProviderProps = {
|
||||
provider: ModelProvider,
|
||||
|
|
@ -39,24 +40,36 @@ const ConfigProvider = ({
|
|||
current_credential_name,
|
||||
available_credentials,
|
||||
} = useCredentialStatus(provider)
|
||||
const notAllowCustomCredential = provider.allow_custom_token === false
|
||||
const handleClick = useCallback(() => {
|
||||
if (!hasCredential)
|
||||
if (!hasCredential && !notAllowCustomCredential)
|
||||
handleOpenModal()
|
||||
}, [handleOpenModal, hasCredential])
|
||||
|
||||
}, [handleOpenModal, hasCredential, notAllowCustomCredential])
|
||||
const ButtonComponent = useMemo(() => {
|
||||
return (
|
||||
const Item = (
|
||||
<Button
|
||||
className='grow'
|
||||
size='small'
|
||||
onClick={handleClick}
|
||||
variant={!authorized ? 'secondary-accent' : 'secondary'}
|
||||
disabled={notAllowCustomCredential}
|
||||
>
|
||||
<RiEqualizer2Line className='mr-1 h-3.5 w-3.5' />
|
||||
{t('common.operation.setup')}
|
||||
</Button>
|
||||
)
|
||||
}, [handleClick, authorized])
|
||||
if (notAllowCustomCredential) {
|
||||
return (
|
||||
<Tooltip
|
||||
asChild
|
||||
popupContent={t('plugin.auth.credentialUnavailable')}
|
||||
>
|
||||
{Item}
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
return Item
|
||||
}, [handleClick, authorized, notAllowCustomCredential, t])
|
||||
|
||||
if (!hasCredential)
|
||||
return ButtonComponent
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ const ModelListItem = ({ model, provider, isConfigurable, onModifyLoadBalancing
|
|||
>
|
||||
</ModelName>
|
||||
<div className='flex shrink-0 items-center'>
|
||||
{modelLoadBalancingEnabled && !model.deprecated && model.load_balancing_enabled && (
|
||||
{modelLoadBalancingEnabled && !model.deprecated && model.load_balancing_enabled && !model.has_invalid_load_balancing_configs && (
|
||||
<Badge className='mr-1 h-[18px] w-[18px] items-center justify-center border-text-accent-secondary p-0'>
|
||||
<Balance className='h-3 w-3 text-text-accent-secondary' />
|
||||
</Badge>
|
||||
|
|
|
|||
|
|
@ -125,15 +125,7 @@ const ModelLoadBalancingConfigs = ({
|
|||
const validDraftConfigList = useMemo(() => {
|
||||
if (!draftConfig)
|
||||
return []
|
||||
return draftConfig.configs.filter((config) => {
|
||||
if (config.name === '__inherit__')
|
||||
return true
|
||||
|
||||
if (config.credential_id)
|
||||
return true
|
||||
|
||||
return false
|
||||
})
|
||||
return draftConfig.configs
|
||||
}, [draftConfig])
|
||||
|
||||
if (!draftConfig)
|
||||
|
|
@ -206,40 +198,50 @@ const ModelLoadBalancingConfigs = ({
|
|||
{!isProviderManaged && (
|
||||
<>
|
||||
<div className='flex items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100'>
|
||||
<span
|
||||
className='flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg bg-components-button-secondary-bg text-text-tertiary transition-colors hover:bg-components-button-secondary-bg-hover'
|
||||
onClick={() => {
|
||||
handleOpenModal(
|
||||
provider,
|
||||
configurationMethod,
|
||||
currentCustomConfigurationModelFixedFields,
|
||||
configurationMethod === ConfigurationMethodEnum.customizableModel,
|
||||
(config.credential_id && config.name) ? {
|
||||
credential_id: config.credential_id,
|
||||
credential_name: config.name,
|
||||
} : undefined,
|
||||
model,
|
||||
)
|
||||
}}
|
||||
>
|
||||
<RiEqualizer2Line className='h-4 w-4' />
|
||||
</span>
|
||||
{
|
||||
config.credential_id && (
|
||||
<span
|
||||
className='flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg bg-components-button-secondary-bg text-text-tertiary transition-colors hover:bg-components-button-secondary-bg-hover'
|
||||
onClick={() => {
|
||||
handleOpenModal(
|
||||
provider,
|
||||
configurationMethod,
|
||||
currentCustomConfigurationModelFixedFields,
|
||||
configurationMethod === ConfigurationMethodEnum.customizableModel,
|
||||
(config.credential_id && config.name) ? {
|
||||
credential_id: config.credential_id,
|
||||
credential_name: config.name,
|
||||
} : undefined,
|
||||
model,
|
||||
)
|
||||
}}
|
||||
>
|
||||
<RiEqualizer2Line className='h-4 w-4' />
|
||||
</span>
|
||||
)
|
||||
}
|
||||
<span
|
||||
className='flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg bg-components-button-secondary-bg text-text-tertiary transition-colors hover:bg-components-button-secondary-bg-hover'
|
||||
onClick={() => updateConfigEntry(index, () => undefined)}
|
||||
>
|
||||
<RiDeleteBinLine className='h-4 w-4' />
|
||||
</span>
|
||||
<span className='mr-2 h-3 border-r border-r-divider-subtle' />
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<Switch
|
||||
defaultValue={Boolean(config.enabled)}
|
||||
size='md'
|
||||
className='justify-self-end'
|
||||
onChange={value => toggleConfigEntryEnabled(index, value)}
|
||||
/>
|
||||
{
|
||||
(config.credential_id || config.name === '__inherit__') && (
|
||||
<>
|
||||
<span className='mr-2 h-3 border-r border-r-divider-subtle' />
|
||||
<Switch
|
||||
defaultValue={Boolean(config.enabled)}
|
||||
size='md'
|
||||
className='justify-self-end'
|
||||
onChange={value => toggleConfigEntryEnabled(index, value)}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import type { AddOAuthButtonProps } from './add-oauth-button'
|
|||
import AddApiKeyButton from './add-api-key-button'
|
||||
import type { AddApiKeyButtonProps } from './add-api-key-button'
|
||||
import type { PluginPayload } from '../types'
|
||||
import cn from '@/utils/classnames'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
|
||||
type AuthorizeProps = {
|
||||
pluginPayload: PluginPayload
|
||||
|
|
@ -17,6 +19,7 @@ type AuthorizeProps = {
|
|||
canApiKey?: boolean
|
||||
disabled?: boolean
|
||||
onUpdate?: () => void
|
||||
notAllowCustomCredential?: boolean
|
||||
}
|
||||
const Authorize = ({
|
||||
pluginPayload,
|
||||
|
|
@ -26,6 +29,7 @@ const Authorize = ({
|
|||
canApiKey,
|
||||
disabled,
|
||||
onUpdate,
|
||||
notAllowCustomCredential,
|
||||
}: AuthorizeProps) => {
|
||||
const { t } = useTranslation()
|
||||
const oAuthButtonProps: AddOAuthButtonProps = useMemo(() => {
|
||||
|
|
@ -62,18 +66,54 @@ const Authorize = ({
|
|||
}
|
||||
}, [canOAuth, theme, pluginPayload, t])
|
||||
|
||||
const OAuthButton = useMemo(() => {
|
||||
const Item = (
|
||||
<div className={cn('min-w-0 flex-[1]', notAllowCustomCredential && 'opacity-50')}>
|
||||
<AddOAuthButton
|
||||
{...oAuthButtonProps}
|
||||
disabled={disabled || notAllowCustomCredential}
|
||||
onUpdate={onUpdate}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
if (notAllowCustomCredential) {
|
||||
return (
|
||||
<Tooltip popupContent={t('plugin.auth.credentialUnavailable')}>
|
||||
{Item}
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
return Item
|
||||
}, [notAllowCustomCredential, oAuthButtonProps, disabled, onUpdate, t])
|
||||
|
||||
const ApiKeyButton = useMemo(() => {
|
||||
const Item = (
|
||||
<div className={cn('min-w-0 flex-[1]', notAllowCustomCredential && 'opacity-50')}>
|
||||
<AddApiKeyButton
|
||||
{...apiKeyButtonProps}
|
||||
disabled={disabled || notAllowCustomCredential}
|
||||
onUpdate={onUpdate}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
if (notAllowCustomCredential) {
|
||||
return (
|
||||
<Tooltip popupContent={t('plugin.auth.credentialUnavailable')}>
|
||||
{Item}
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
return Item
|
||||
}, [notAllowCustomCredential, apiKeyButtonProps, disabled, onUpdate, t])
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className='flex items-center space-x-1.5'>
|
||||
{
|
||||
canOAuth && (
|
||||
<div className='min-w-0 flex-[1]'>
|
||||
<AddOAuthButton
|
||||
{...oAuthButtonProps}
|
||||
disabled={disabled}
|
||||
onUpdate={onUpdate}
|
||||
/>
|
||||
</div>
|
||||
OAuthButton
|
||||
)
|
||||
}
|
||||
{
|
||||
|
|
@ -87,13 +127,7 @@ const Authorize = ({
|
|||
}
|
||||
{
|
||||
canApiKey && (
|
||||
<div className='min-w-0 flex-[1]'>
|
||||
<AddApiKeyButton
|
||||
{...apiKeyButtonProps}
|
||||
disabled={disabled}
|
||||
onUpdate={onUpdate}
|
||||
/>
|
||||
</div>
|
||||
ApiKeyButton
|
||||
)
|
||||
}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -35,10 +35,12 @@ const AuthorizedInNode = ({
|
|||
credentials,
|
||||
disabled,
|
||||
invalidPluginCredentialInfo,
|
||||
notAllowCustomCredential,
|
||||
} = usePluginAuth(pluginPayload, isOpen || !!credentialId)
|
||||
const renderTrigger = useCallback((open?: boolean) => {
|
||||
let label = ''
|
||||
let removed = false
|
||||
let unavailable = false
|
||||
if (!credentialId) {
|
||||
label = t('plugin.auth.workspaceDefault')
|
||||
}
|
||||
|
|
@ -46,6 +48,7 @@ const AuthorizedInNode = ({
|
|||
const credential = credentials.find(c => c.id === credentialId)
|
||||
label = credential ? credential.name : t('plugin.auth.authRemoved')
|
||||
removed = !credential
|
||||
unavailable = !!credential?.not_allowed_to_use
|
||||
}
|
||||
return (
|
||||
<Button
|
||||
|
|
@ -60,6 +63,9 @@ const AuthorizedInNode = ({
|
|||
color={removed ? 'red' : 'green'}
|
||||
/>
|
||||
{label}
|
||||
{
|
||||
!unavailable && t('plugin.auth.unavailable')
|
||||
}
|
||||
<RiArrowDownSLine
|
||||
className={cn(
|
||||
'h-3.5 w-3.5 text-components-button-ghost-text',
|
||||
|
|
@ -106,6 +112,7 @@ const AuthorizedInNode = ({
|
|||
showItemSelectedIcon
|
||||
selectedCredentialId={credentialId || '__workspace_default__'}
|
||||
onUpdate={invalidPluginCredentialInfo}
|
||||
notAllowCustomCredential={notAllowCustomCredential}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ type AuthorizedProps = {
|
|||
showItemSelectedIcon?: boolean
|
||||
selectedCredentialId?: string
|
||||
onUpdate?: () => void
|
||||
notAllowCustomCredential?: boolean
|
||||
}
|
||||
const Authorized = ({
|
||||
pluginPayload,
|
||||
|
|
@ -72,6 +73,7 @@ const Authorized = ({
|
|||
showItemSelectedIcon,
|
||||
selectedCredentialId,
|
||||
onUpdate,
|
||||
notAllowCustomCredential,
|
||||
}: AuthorizedProps) => {
|
||||
const { t } = useTranslation()
|
||||
const { notify } = useToastContext()
|
||||
|
|
@ -171,6 +173,7 @@ const Authorized = ({
|
|||
handleSetDoingAction(false)
|
||||
}
|
||||
}, [updatePluginCredential, notify, t, handleSetDoingAction, onUpdate])
|
||||
const unavailableCredentials = credentials.filter(credential => credential.not_allowed_to_use)
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -201,6 +204,11 @@ const Authorized = ({
|
|||
? t('plugin.auth.authorizations')
|
||||
: t('plugin.auth.authorization')
|
||||
}
|
||||
{
|
||||
!!unavailableCredentials.length && (
|
||||
` (${unavailableCredentials.length} ${t('plugin.auth.unavailable')})`
|
||||
)
|
||||
}
|
||||
<RiArrowDownSLine className='ml-0.5 h-4 w-4' />
|
||||
</Button>
|
||||
)
|
||||
|
|
@ -294,18 +302,24 @@ const Authorized = ({
|
|||
)
|
||||
}
|
||||
</div>
|
||||
<div className='h-[1px] bg-divider-subtle'></div>
|
||||
<div className='p-2'>
|
||||
<Authorize
|
||||
pluginPayload={pluginPayload}
|
||||
theme='secondary'
|
||||
showDivider={false}
|
||||
canOAuth={canOAuth}
|
||||
canApiKey={canApiKey}
|
||||
disabled={disabled}
|
||||
onUpdate={onUpdate}
|
||||
/>
|
||||
</div>
|
||||
{
|
||||
!notAllowCustomCredential && (
|
||||
<>
|
||||
<div className='h-[1px] bg-divider-subtle'></div>
|
||||
<div className='p-2'>
|
||||
<Authorize
|
||||
pluginPayload={pluginPayload}
|
||||
theme='secondary'
|
||||
showDivider={false}
|
||||
canOAuth={canOAuth}
|
||||
canApiKey={canApiKey}
|
||||
disabled={disabled}
|
||||
onUpdate={onUpdate}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</PortalToFollowElemContent>
|
||||
</PortalToFollowElem>
|
||||
|
|
|
|||
|
|
@ -61,14 +61,19 @@ const Item = ({
|
|||
return !(disableRename && disableEdit && disableDelete && disableSetDefault)
|
||||
}, [disableRename, disableEdit, disableDelete, disableSetDefault])
|
||||
|
||||
return (
|
||||
const CredentialItem = (
|
||||
<div
|
||||
key={credential.id}
|
||||
className={cn(
|
||||
'group flex h-8 items-center rounded-lg p-1 hover:bg-state-base-hover',
|
||||
renaming && 'bg-state-base-hover',
|
||||
(disabled || credential.not_allowed_to_use) && 'cursor-not-allowed opacity-50',
|
||||
)}
|
||||
onClick={() => onItemClick?.(credential.id === '__workspace_default__' ? '' : credential.id)}
|
||||
onClick={() => {
|
||||
if (credential.not_allowed_to_use || disabled)
|
||||
return
|
||||
onItemClick?.(credential.id === '__workspace_default__' ? '' : credential.id)
|
||||
}}
|
||||
>
|
||||
{
|
||||
renaming && (
|
||||
|
|
@ -121,35 +126,31 @@ const Item = ({
|
|||
</div>
|
||||
)
|
||||
}
|
||||
<Indicator className='ml-2 mr-1.5 shrink-0' />
|
||||
<Indicator
|
||||
className='ml-2 mr-1.5 shrink-0'
|
||||
color={credential.not_allowed_to_use ? 'gray' : 'green'}
|
||||
/>
|
||||
<div
|
||||
className='system-md-regular truncate text-text-secondary'
|
||||
title={credential.name}
|
||||
>
|
||||
{credential.name}
|
||||
</div>
|
||||
{
|
||||
credential.is_default && (
|
||||
<Badge className='shrink-0'>
|
||||
{t('plugin.auth.default')}
|
||||
</Badge>
|
||||
)
|
||||
}
|
||||
{
|
||||
credential.from_enterprise && (
|
||||
<Badge className='shrink-0'>
|
||||
Enterprise
|
||||
</Badge>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{
|
||||
credential.from_enterprise && (
|
||||
<Badge className='shrink-0'>
|
||||
Enterprise
|
||||
</Badge>
|
||||
)
|
||||
}
|
||||
{
|
||||
showAction && !renaming && (
|
||||
<div className='ml-2 hidden shrink-0 items-center group-hover:flex'>
|
||||
{
|
||||
!credential.is_default && !disableSetDefault && (
|
||||
!credential.is_default && !disableSetDefault && !credential.not_allowed_to_use && (
|
||||
<Button
|
||||
size='small'
|
||||
disabled={disabled}
|
||||
|
|
@ -163,7 +164,7 @@ const Item = ({
|
|||
)
|
||||
}
|
||||
{
|
||||
!disableRename && (
|
||||
!disableRename && !credential.from_enterprise && !credential.not_allowed_to_use && (
|
||||
<Tooltip popupContent={t('common.operation.rename')}>
|
||||
<ActionButton
|
||||
disabled={disabled}
|
||||
|
|
@ -179,7 +180,7 @@ const Item = ({
|
|||
)
|
||||
}
|
||||
{
|
||||
!isOAuth && !disableEdit && !credential.from_enterprise && (
|
||||
!isOAuth && !disableEdit && !credential.from_enterprise && !credential.not_allowed_to_use && (
|
||||
<Tooltip popupContent={t('common.operation.edit')}>
|
||||
<ActionButton
|
||||
disabled={disabled}
|
||||
|
|
@ -221,6 +222,18 @@ const Item = ({
|
|||
}
|
||||
</div>
|
||||
)
|
||||
|
||||
if (credential.not_allowed_to_use) {
|
||||
return (
|
||||
<Tooltip popupContent={t('plugin.auth.customCredentialUnavailable')}>
|
||||
{CredentialItem}
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
CredentialItem
|
||||
)
|
||||
}
|
||||
|
||||
export default memo(Item)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ export const usePluginAuth = (pluginPayload: PluginPayload, enable?: boolean) =>
|
|||
canApiKey,
|
||||
credentials: data?.credentials || [],
|
||||
disabled: !isCurrentWorkspaceManager,
|
||||
notAllowCustomCredential: data?.allow_custom_token === false,
|
||||
invalidPluginCredentialInfo,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ const PluginAuthInAgent = ({
|
|||
credentials,
|
||||
disabled,
|
||||
invalidPluginCredentialInfo,
|
||||
notAllowCustomCredential,
|
||||
} = usePluginAuth(pluginPayload, true)
|
||||
|
||||
const extraAuthorizationItems: Credential[] = [
|
||||
|
|
@ -58,6 +59,7 @@ const PluginAuthInAgent = ({
|
|||
const renderTrigger = useCallback((isOpen?: boolean) => {
|
||||
let label = ''
|
||||
let removed = false
|
||||
let unavailable = false
|
||||
if (!credentialId) {
|
||||
label = t('plugin.auth.workspaceDefault')
|
||||
}
|
||||
|
|
@ -65,6 +67,7 @@ const PluginAuthInAgent = ({
|
|||
const credential = credentials.find(c => c.id === credentialId)
|
||||
label = credential ? credential.name : t('plugin.auth.authRemoved')
|
||||
removed = !credential
|
||||
unavailable = !!credential?.not_allowed_to_use
|
||||
}
|
||||
return (
|
||||
<Button
|
||||
|
|
@ -78,6 +81,9 @@ const PluginAuthInAgent = ({
|
|||
color={removed ? 'red' : 'green'}
|
||||
/>
|
||||
{label}
|
||||
{
|
||||
!unavailable && t('plugin.auth.unavailable')
|
||||
}
|
||||
<RiArrowDownSLine className='ml-0.5 h-4 w-4' />
|
||||
</Button>
|
||||
)
|
||||
|
|
@ -93,6 +99,7 @@ const PluginAuthInAgent = ({
|
|||
canApiKey={canApiKey}
|
||||
disabled={disabled}
|
||||
onUpdate={invalidPluginCredentialInfo}
|
||||
notAllowCustomCredential={notAllowCustomCredential}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
@ -113,6 +120,7 @@ const PluginAuthInAgent = ({
|
|||
onOpenChange={setIsOpen}
|
||||
selectedCredentialId={credentialId || '__workspace_default__'}
|
||||
onUpdate={invalidPluginCredentialInfo}
|
||||
notAllowCustomCredential={notAllowCustomCredential}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ const PluginAuth = ({
|
|||
credentials,
|
||||
disabled,
|
||||
invalidPluginCredentialInfo,
|
||||
notAllowCustomCredential,
|
||||
} = usePluginAuth(pluginPayload, !!pluginPayload.provider)
|
||||
|
||||
return (
|
||||
|
|
@ -34,6 +35,7 @@ const PluginAuth = ({
|
|||
canApiKey={canApiKey}
|
||||
disabled={disabled}
|
||||
onUpdate={invalidPluginCredentialInfo}
|
||||
notAllowCustomCredential={notAllowCustomCredential}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
@ -46,6 +48,7 @@ const PluginAuth = ({
|
|||
canApiKey={canApiKey}
|
||||
disabled={disabled}
|
||||
onUpdate={invalidPluginCredentialInfo}
|
||||
notAllowCustomCredential={notAllowCustomCredential}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,5 +23,5 @@ export type Credential = {
|
|||
credentials?: Record<string, any>
|
||||
isWorkspaceDefault?: boolean
|
||||
from_enterprise?: boolean
|
||||
allowed_to_use?: boolean
|
||||
not_allowed_to_use?: boolean
|
||||
}
|
||||
|
|
|
|||
|
|
@ -297,6 +297,9 @@ const translation = {
|
|||
authRemoved: 'Auth removed',
|
||||
clientInfo: 'As no system client secrets found for this tool provider, setup it manually is required, for redirect_uri, please use',
|
||||
oauthClient: 'OAuth Client',
|
||||
credentialUnavailable: 'Credentials currently unavailable. Please contact admin.',
|
||||
customCredentialUnavailable: 'Custom credentials currently unavailable',
|
||||
unavailable: 'Unavailable',
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -297,6 +297,9 @@ const translation = {
|
|||
authRemoved: '凭据已移除',
|
||||
clientInfo: '由于未找到此工具提供者的系统客户端密钥,因此需要手动设置,对于 redirect_uri,请使用',
|
||||
oauthClient: 'OAuth 客户端',
|
||||
credentialUnavailable: '凭据当前不可用,请联系管理员。',
|
||||
customCredentialUnavailable: '自定义凭据当前不可用',
|
||||
unavailable: '不可用',
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ export const useGetPluginCredentialInfo = (
|
|||
enabled: !!url,
|
||||
queryKey: [NAME_SPACE, 'credential-info', url],
|
||||
queryFn: () => get<{
|
||||
allow_custom_token?: boolean
|
||||
supported_credential_types: string[]
|
||||
credentials: Credential[]
|
||||
is_oauth_custom_client_enabled: boolean
|
||||
|
|
|
|||
Loading…
Reference in New Issue