From b3e5a4ecb738597b5a959febade43c5f78ec63ec Mon Sep 17 00:00:00 2001 From: zxhlyh Date: Wed, 20 Aug 2025 15:12:20 +0800 Subject: [PATCH] enterprise model credential --- .../model-provider-page/declarations.ts | 3 +- .../add-credential-in-load-balancing.tsx | 19 ++++- .../model-auth/add-custom-model.tsx | 32 +++++++-- .../model-auth/authorized/authorized-item.tsx | 4 +- .../model-auth/authorized/credential-item.tsx | 18 ++++- .../model-auth/authorized/index.tsx | 53 ++++++++++---- .../model-auth/config-model.tsx | 6 +- .../model-auth/config-provider.tsx | 23 ++++-- .../provider-added-card/model-list-item.tsx | 2 +- .../model-load-balancing-configs.tsx | 70 ++++++++++--------- .../plugins/plugin-auth/authorize/index.tsx | 62 ++++++++++++---- .../plugin-auth/authorized-in-node.tsx | 7 ++ .../plugins/plugin-auth/authorized/index.tsx | 38 ++++++---- .../plugins/plugin-auth/authorized/item.tsx | 53 ++++++++------ .../plugin-auth/hooks/use-plugin-auth.ts | 1 + .../plugin-auth/plugin-auth-in-agent.tsx | 8 +++ .../plugins/plugin-auth/plugin-auth.tsx | 3 + .../components/plugins/plugin-auth/types.ts | 2 +- web/i18n/en-US/plugin.ts | 3 + web/i18n/zh-Hans/plugin.ts | 3 + web/service/use-plugins-auth.ts | 1 + 21 files changed, 298 insertions(+), 113 deletions(-) diff --git a/web/app/components/header/account-setting/model-provider-page/declarations.ts b/web/app/components/header/account-setting/model-provider-page/declarations.ts index 945806928a..74f47c9d1d 100644 --- a/web/app/components/header/account-setting/model-provider-page/declarations.ts +++ b/web/app/components/header/account-setting/model-provider-page/declarations.ts @@ -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 = { diff --git a/web/app/components/header/account-setting/model-provider-page/model-auth/add-credential-in-load-balancing.tsx b/web/app/components/header/account-setting/model-provider-page/model-auth/add-credential-in-load-balancing.tsx index 829ef25795..d6daa91dd9 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-auth/add-credential-in-load-balancing.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-auth/add-credential-in-load-balancing.tsx @@ -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 = (
{ @@ -49,7 +52,19 @@ const AddCredentialInLoadBalancing = ({ }
) - }, []) + + if (notAllowCustomCredential) { + return ( + + {Item} + + ) + } + return Item + }, [notAllowCustomCredential, t, customModel]) return ( { handleOpenModal() }, [handleOpenModal]) + const notAllowCustomCredential = provider.allow_custom_token === false const ButtonComponent = useMemo(() => { - return ( + const Item = ( + ) + + if (notAllowCustomCredential && !hasValidCredential) { + return ( + + {Item} + + ) + } + return Item + }, [notAllowCustomCredential, t, items]) return ( <> @@ -118,21 +147,20 @@ const Authorized = ({ triggerPopupSameWidth={triggerPopupSameWidth} > 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) - : ( - - ) + : Trigger } @@ -155,13 +183,14 @@ const Authorized = ({ selectedCredentialId={selectedCredential?.credential_id} onItemClick={handleItemClick} enableAddModelCredential={enableAddModelCredential} + notAllowCustomCredential={notAllowCustomCredential} /> )) }
{ - isModelCredential && ( + isModelCredential && !notAllowCustomCredential && (
handleEdit( undefined, @@ -180,7 +209,7 @@ const Authorized = ({ ) } { - !isModelCredential && ( + !isModelCredential && !notAllowCustomCredential && (
) - }, [handleClick, authorized]) + if (notAllowCustomCredential) { + return ( + + {Item} + + ) + } + return Item + }, [handleClick, authorized, notAllowCustomCredential, t]) if (!hasCredential) return ButtonComponent diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-list-item.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-list-item.tsx index 020cf83e43..bcd4832443 100644 --- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-list-item.tsx +++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-list-item.tsx @@ -65,7 +65,7 @@ const ModelListItem = ({ model, provider, isConfigurable, onModifyLoadBalancing >
- {modelLoadBalancingEnabled && !model.deprecated && model.load_balancing_enabled && ( + {modelLoadBalancingEnabled && !model.deprecated && model.load_balancing_enabled && !model.has_invalid_load_balancing_configs && ( diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx index 5402ba4d73..c7d81e382f 100644 --- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx +++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx @@ -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 && ( <>
- { - handleOpenModal( - provider, - configurationMethod, - currentCustomConfigurationModelFixedFields, - configurationMethod === ConfigurationMethodEnum.customizableModel, - (config.credential_id && config.name) ? { - credential_id: config.credential_id, - credential_name: config.name, - } : undefined, - model, - ) - }} - > - - + { + config.credential_id && ( + { + handleOpenModal( + provider, + configurationMethod, + currentCustomConfigurationModelFixedFields, + configurationMethod === ConfigurationMethodEnum.customizableModel, + (config.credential_id && config.name) ? { + credential_id: config.credential_id, + credential_name: config.name, + } : undefined, + model, + ) + }} + > + + + ) + } updateConfigEntry(index, () => undefined)} > -
)} - toggleConfigEntryEnabled(index, value)} - /> + { + (config.credential_id || config.name === '__inherit__') && ( + <> + + toggleConfigEntryEnabled(index, value)} + /> + + ) + }
) diff --git a/web/app/components/plugins/plugin-auth/authorize/index.tsx b/web/app/components/plugins/plugin-auth/authorize/index.tsx index f430d8d48e..1d41165147 100644 --- a/web/app/components/plugins/plugin-auth/authorize/index.tsx +++ b/web/app/components/plugins/plugin-auth/authorize/index.tsx @@ -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 = ( +
+ +
+ ) + + if (notAllowCustomCredential) { + return ( + + {Item} + + ) + } + return Item + }, [notAllowCustomCredential, oAuthButtonProps, disabled, onUpdate, t]) + + const ApiKeyButton = useMemo(() => { + const Item = ( +
+ +
+ ) + + if (notAllowCustomCredential) { + return ( + + {Item} + + ) + } + return Item + }, [notAllowCustomCredential, apiKeyButtonProps, disabled, onUpdate, t]) + return ( <>
{ canOAuth && ( -
- -
+ OAuthButton ) } { @@ -87,13 +127,7 @@ const Authorize = ({ } { canApiKey && ( -
- -
+ ApiKeyButton ) }
diff --git a/web/app/components/plugins/plugin-auth/authorized-in-node.tsx b/web/app/components/plugins/plugin-auth/authorized-in-node.tsx index 79189fa585..fe4e4b3dfa 100644 --- a/web/app/components/plugins/plugin-auth/authorized-in-node.tsx +++ b/web/app/components/plugins/plugin-auth/authorized-in-node.tsx @@ -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 ( ) @@ -294,18 +302,24 @@ const Authorized = ({ ) }
-
-
- -
+ { + !notAllowCustomCredential && ( + <> +
+
+ +
+ + ) + }
diff --git a/web/app/components/plugins/plugin-auth/authorized/item.tsx b/web/app/components/plugins/plugin-auth/authorized/item.tsx index 76d43310d4..47b6ce8c92 100644 --- a/web/app/components/plugins/plugin-auth/authorized/item.tsx +++ b/web/app/components/plugins/plugin-auth/authorized/item.tsx @@ -61,14 +61,19 @@ const Item = ({ return !(disableRename && disableEdit && disableDelete && disableSetDefault) }, [disableRename, disableEdit, disableDelete, disableSetDefault]) - return ( + const CredentialItem = (
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 = ({
) } - +
{credential.name}
- { - credential.is_default && ( - - {t('plugin.auth.default')} - - ) - } - { - credential.from_enterprise && ( - - Enterprise - - ) - } ) } + { + credential.from_enterprise && ( + + Enterprise + + ) + } { showAction && !renaming && (
{ - !credential.is_default && !disableSetDefault && ( + !credential.is_default && !disableSetDefault && !credential.not_allowed_to_use && ( ) @@ -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} /> ) } diff --git a/web/app/components/plugins/plugin-auth/plugin-auth.tsx b/web/app/components/plugins/plugin-auth/plugin-auth.tsx index 76b405a750..a9bb287cdf 100644 --- a/web/app/components/plugins/plugin-auth/plugin-auth.tsx +++ b/web/app/components/plugins/plugin-auth/plugin-auth.tsx @@ -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} /> ) } diff --git a/web/app/components/plugins/plugin-auth/types.ts b/web/app/components/plugins/plugin-auth/types.ts index 93ec4c8c1a..1fb2c1a531 100644 --- a/web/app/components/plugins/plugin-auth/types.ts +++ b/web/app/components/plugins/plugin-auth/types.ts @@ -23,5 +23,5 @@ export type Credential = { credentials?: Record isWorkspaceDefault?: boolean from_enterprise?: boolean - allowed_to_use?: boolean + not_allowed_to_use?: boolean } diff --git a/web/i18n/en-US/plugin.ts b/web/i18n/en-US/plugin.ts index aa127eaf13..85bbd44bd5 100644 --- a/web/i18n/en-US/plugin.ts +++ b/web/i18n/en-US/plugin.ts @@ -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', }, } diff --git a/web/i18n/zh-Hans/plugin.ts b/web/i18n/zh-Hans/plugin.ts index a080a26a8c..e014ac5ee6 100644 --- a/web/i18n/zh-Hans/plugin.ts +++ b/web/i18n/zh-Hans/plugin.ts @@ -297,6 +297,9 @@ const translation = { authRemoved: '凭据已移除', clientInfo: '由于未找到此工具提供者的系统客户端密钥,因此需要手动设置,对于 redirect_uri,请使用', oauthClient: 'OAuth 客户端', + credentialUnavailable: '凭据当前不可用,请联系管理员。', + customCredentialUnavailable: '自定义凭据当前不可用', + unavailable: '不可用', }, } diff --git a/web/service/use-plugins-auth.ts b/web/service/use-plugins-auth.ts index 2dc0260647..51992361eb 100644 --- a/web/service/use-plugins-auth.ts +++ b/web/service/use-plugins-auth.ts @@ -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