mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-08-11 12:59:02 +08:00
Web app now supports SSO config (#7137)
This commit is contained in:
parent
741c548f3c
commit
23cedc3f1c
@ -15,13 +15,14 @@ import {
|
|||||||
} from '@remixicon/react'
|
} from '@remixicon/react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useShallow } from 'zustand/react/shallow'
|
import { useShallow } from 'zustand/react/shallow'
|
||||||
|
import { useContextSelector } from 'use-context-selector'
|
||||||
import s from './style.module.css'
|
import s from './style.module.css'
|
||||||
import cn from '@/utils/classnames'
|
import cn from '@/utils/classnames'
|
||||||
import { useStore } from '@/app/components/app/store'
|
import { useStore } from '@/app/components/app/store'
|
||||||
import AppSideBar from '@/app/components/app-sidebar'
|
import AppSideBar from '@/app/components/app-sidebar'
|
||||||
import type { NavIcon } from '@/app/components/app-sidebar/navLink'
|
import type { NavIcon } from '@/app/components/app-sidebar/navLink'
|
||||||
import { fetchAppDetail } from '@/service/apps'
|
import { fetchAppDetail, fetchAppSSO } from '@/service/apps'
|
||||||
import { useAppContext } from '@/context/app-context'
|
import AppContext, { useAppContext } from '@/context/app-context'
|
||||||
import Loading from '@/app/components/base/loading'
|
import Loading from '@/app/components/base/loading'
|
||||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||||
|
|
||||||
@ -52,6 +53,7 @@ const AppDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
|
|||||||
icon: NavIcon
|
icon: NavIcon
|
||||||
selectedIcon: NavIcon
|
selectedIcon: NavIcon
|
||||||
}>>([])
|
}>>([])
|
||||||
|
const systemFeatures = useContextSelector(AppContext, state => state.systemFeatures)
|
||||||
|
|
||||||
const getNavigations = useCallback((appId: string, isCurrentWorkspaceEditor: boolean, mode: string) => {
|
const getNavigations = useCallback((appId: string, isCurrentWorkspaceEditor: boolean, mode: string) => {
|
||||||
const navs = [
|
const navs = [
|
||||||
@ -114,8 +116,13 @@ const AppDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
|
|||||||
router.replace(`/app/${appId}/configuration`)
|
router.replace(`/app/${appId}/configuration`)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
setAppDetail(res)
|
setAppDetail({ ...res, enable_sso: false })
|
||||||
setNavigation(getNavigations(appId, isCurrentWorkspaceEditor, res.mode))
|
setNavigation(getNavigations(appId, isCurrentWorkspaceEditor, res.mode))
|
||||||
|
if (systemFeatures.enable_web_sso_switch_component) {
|
||||||
|
fetchAppSSO({ appId }).then((ssoRes) => {
|
||||||
|
setAppDetail({ ...res, enable_sso: ssoRes.enabled })
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}).catch((e: any) => {
|
}).catch((e: any) => {
|
||||||
if (e.status === 404)
|
if (e.status === 404)
|
||||||
|
@ -2,22 +2,25 @@
|
|||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useContext } from 'use-context-selector'
|
import { useContext, useContextSelector } from 'use-context-selector'
|
||||||
import AppCard from '@/app/components/app/overview/appCard'
|
import AppCard from '@/app/components/app/overview/appCard'
|
||||||
import Loading from '@/app/components/base/loading'
|
import Loading from '@/app/components/base/loading'
|
||||||
import { ToastContext } from '@/app/components/base/toast'
|
import { ToastContext } from '@/app/components/base/toast'
|
||||||
import {
|
import {
|
||||||
fetchAppDetail,
|
fetchAppDetail,
|
||||||
|
fetchAppSSO,
|
||||||
|
updateAppSSO,
|
||||||
updateAppSiteAccessToken,
|
updateAppSiteAccessToken,
|
||||||
updateAppSiteConfig,
|
updateAppSiteConfig,
|
||||||
updateAppSiteStatus,
|
updateAppSiteStatus,
|
||||||
} from '@/service/apps'
|
} from '@/service/apps'
|
||||||
import type { App } from '@/types/app'
|
import type { App, AppSSO } from '@/types/app'
|
||||||
import type { UpdateAppSiteCodeResponse } from '@/models/app'
|
import type { UpdateAppSiteCodeResponse } from '@/models/app'
|
||||||
import { asyncRunSafe } from '@/utils'
|
import { asyncRunSafe } from '@/utils'
|
||||||
import { NEED_REFRESH_APP_LIST_KEY } from '@/config'
|
import { NEED_REFRESH_APP_LIST_KEY } from '@/config'
|
||||||
import type { IAppCardProps } from '@/app/components/app/overview/appCard'
|
import type { IAppCardProps } from '@/app/components/app/overview/appCard'
|
||||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||||
|
import AppContext from '@/context/app-context'
|
||||||
|
|
||||||
export type ICardViewProps = {
|
export type ICardViewProps = {
|
||||||
appId: string
|
appId: string
|
||||||
@ -28,11 +31,20 @@ const CardView: FC<ICardViewProps> = ({ appId }) => {
|
|||||||
const { notify } = useContext(ToastContext)
|
const { notify } = useContext(ToastContext)
|
||||||
const appDetail = useAppStore(state => state.appDetail)
|
const appDetail = useAppStore(state => state.appDetail)
|
||||||
const setAppDetail = useAppStore(state => state.setAppDetail)
|
const setAppDetail = useAppStore(state => state.setAppDetail)
|
||||||
|
const systemFeatures = useContextSelector(AppContext, state => state.systemFeatures)
|
||||||
|
|
||||||
const updateAppDetail = async () => {
|
const updateAppDetail = async () => {
|
||||||
fetchAppDetail({ url: '/apps', id: appId }).then((res) => {
|
try {
|
||||||
setAppDetail(res)
|
const res = await fetchAppDetail({ url: '/apps', id: appId })
|
||||||
})
|
if (systemFeatures.enable_web_sso_switch_component) {
|
||||||
|
const ssoRes = await fetchAppSSO({ appId })
|
||||||
|
setAppDetail({ ...res, enable_sso: ssoRes.enabled })
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setAppDetail({ ...res })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (error) { console.error(error) }
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleCallbackResult = (err: Error | null, message?: string) => {
|
const handleCallbackResult = (err: Error | null, message?: string) => {
|
||||||
@ -81,6 +93,16 @@ const CardView: FC<ICardViewProps> = ({ appId }) => {
|
|||||||
if (!err)
|
if (!err)
|
||||||
localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1')
|
localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1')
|
||||||
|
|
||||||
|
if (systemFeatures.enable_web_sso_switch_component) {
|
||||||
|
const [sso_err] = await asyncRunSafe<AppSSO>(
|
||||||
|
updateAppSSO({ id: appId, enabled: params.enable_sso }) as Promise<AppSSO>,
|
||||||
|
)
|
||||||
|
if (sso_err) {
|
||||||
|
handleCallbackResult(sso_err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handleCallbackResult(err)
|
handleCallbackResult(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,10 +27,11 @@ import ShareQRCode from '@/app/components/base/qrcode'
|
|||||||
import SecretKeyButton from '@/app/components/develop/secret-key/secret-key-button'
|
import SecretKeyButton from '@/app/components/develop/secret-key/secret-key-button'
|
||||||
import type { AppDetailResponse } from '@/models/app'
|
import type { AppDetailResponse } from '@/models/app'
|
||||||
import { useAppContext } from '@/context/app-context'
|
import { useAppContext } from '@/context/app-context'
|
||||||
|
import type { AppSSO } from '@/types/app'
|
||||||
|
|
||||||
export type IAppCardProps = {
|
export type IAppCardProps = {
|
||||||
className?: string
|
className?: string
|
||||||
appInfo: AppDetailResponse
|
appInfo: AppDetailResponse & Partial<AppSSO>
|
||||||
cardType?: 'api' | 'webapp'
|
cardType?: 'api' | 'webapp'
|
||||||
customBgColor?: string
|
customBgColor?: string
|
||||||
onChangeStatus: (val: boolean) => Promise<void>
|
onChangeStatus: (val: boolean) => Promise<void>
|
||||||
|
@ -4,21 +4,25 @@ import React, { useEffect, useState } from 'react'
|
|||||||
import { ChevronRightIcon } from '@heroicons/react/20/solid'
|
import { ChevronRightIcon } from '@heroicons/react/20/solid'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { Trans, useTranslation } from 'react-i18next'
|
import { Trans, useTranslation } from 'react-i18next'
|
||||||
|
import { useContextSelector } from 'use-context-selector'
|
||||||
import s from './style.module.css'
|
import s from './style.module.css'
|
||||||
import Modal from '@/app/components/base/modal'
|
import Modal from '@/app/components/base/modal'
|
||||||
import Button from '@/app/components/base/button'
|
import Button from '@/app/components/base/button'
|
||||||
import AppIcon from '@/app/components/base/app-icon'
|
import AppIcon from '@/app/components/base/app-icon'
|
||||||
|
import Switch from '@/app/components/base/switch'
|
||||||
import { SimpleSelect } from '@/app/components/base/select'
|
import { SimpleSelect } from '@/app/components/base/select'
|
||||||
import type { AppDetailResponse } from '@/models/app'
|
import type { AppDetailResponse } from '@/models/app'
|
||||||
import type { AppIconType, Language } from '@/types/app'
|
import type { AppIconType, AppSSO, Language } from '@/types/app'
|
||||||
import { useToastContext } from '@/app/components/base/toast'
|
import { useToastContext } from '@/app/components/base/toast'
|
||||||
import { languages } from '@/i18n/language'
|
import { languages } from '@/i18n/language'
|
||||||
|
import TooltipPlus from '@/app/components/base/tooltip-plus'
|
||||||
|
import AppContext from '@/context/app-context'
|
||||||
import type { AppIconSelection } from '@/app/components/base/app-icon-picker'
|
import type { AppIconSelection } from '@/app/components/base/app-icon-picker'
|
||||||
import AppIconPicker from '@/app/components/base/app-icon-picker'
|
import AppIconPicker from '@/app/components/base/app-icon-picker'
|
||||||
|
|
||||||
export type ISettingsModalProps = {
|
export type ISettingsModalProps = {
|
||||||
isChat: boolean
|
isChat: boolean
|
||||||
appInfo: AppDetailResponse
|
appInfo: AppDetailResponse & Partial<AppSSO>
|
||||||
isShow: boolean
|
isShow: boolean
|
||||||
defaultValue?: string
|
defaultValue?: string
|
||||||
onClose: () => void
|
onClose: () => void
|
||||||
@ -39,6 +43,7 @@ export type ConfigParams = {
|
|||||||
icon: string
|
icon: string
|
||||||
icon_background?: string
|
icon_background?: string
|
||||||
show_workflow_steps: boolean
|
show_workflow_steps: boolean
|
||||||
|
enable_sso?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const prefixSettings = 'appOverview.overview.appInfo.settings'
|
const prefixSettings = 'appOverview.overview.appInfo.settings'
|
||||||
@ -50,6 +55,7 @@ const SettingsModal: FC<ISettingsModalProps> = ({
|
|||||||
onClose,
|
onClose,
|
||||||
onSave,
|
onSave,
|
||||||
}) => {
|
}) => {
|
||||||
|
const systemFeatures = useContextSelector(AppContext, state => state.systemFeatures)
|
||||||
const { notify } = useToastContext()
|
const { notify } = useToastContext()
|
||||||
const [isShowMore, setIsShowMore] = useState(false)
|
const [isShowMore, setIsShowMore] = useState(false)
|
||||||
const {
|
const {
|
||||||
@ -76,6 +82,7 @@ const SettingsModal: FC<ISettingsModalProps> = ({
|
|||||||
privacyPolicy: privacy_policy,
|
privacyPolicy: privacy_policy,
|
||||||
customDisclaimer: custom_disclaimer,
|
customDisclaimer: custom_disclaimer,
|
||||||
show_workflow_steps,
|
show_workflow_steps,
|
||||||
|
enable_sso: appInfo.enable_sso,
|
||||||
})
|
})
|
||||||
const [language, setLanguage] = useState(default_language)
|
const [language, setLanguage] = useState(default_language)
|
||||||
const [saveLoading, setSaveLoading] = useState(false)
|
const [saveLoading, setSaveLoading] = useState(false)
|
||||||
@ -98,6 +105,7 @@ const SettingsModal: FC<ISettingsModalProps> = ({
|
|||||||
privacyPolicy: privacy_policy,
|
privacyPolicy: privacy_policy,
|
||||||
customDisclaimer: custom_disclaimer,
|
customDisclaimer: custom_disclaimer,
|
||||||
show_workflow_steps,
|
show_workflow_steps,
|
||||||
|
enable_sso: appInfo.enable_sso,
|
||||||
})
|
})
|
||||||
setLanguage(default_language)
|
setLanguage(default_language)
|
||||||
setAppIcon(icon_type === 'image'
|
setAppIcon(icon_type === 'image'
|
||||||
@ -149,6 +157,7 @@ const SettingsModal: FC<ISettingsModalProps> = ({
|
|||||||
icon: appIcon.type === 'emoji' ? appIcon.icon : appIcon.fileId,
|
icon: appIcon.type === 'emoji' ? appIcon.icon : appIcon.fileId,
|
||||||
icon_background: appIcon.type === 'emoji' ? appIcon.background : undefined,
|
icon_background: appIcon.type === 'emoji' ? appIcon.background : undefined,
|
||||||
show_workflow_steps: inputInfo.show_workflow_steps,
|
show_workflow_steps: inputInfo.show_workflow_steps,
|
||||||
|
enable_sso: inputInfo.enable_sso,
|
||||||
}
|
}
|
||||||
await onSave?.(params)
|
await onSave?.(params)
|
||||||
setSaveLoading(false)
|
setSaveLoading(false)
|
||||||
@ -219,9 +228,19 @@ const SettingsModal: FC<ISettingsModalProps> = ({
|
|||||||
<input className={`w-full mt-2 rounded-lg h-10 box-border px-3 ${s.projectName} bg-gray-100`}
|
<input className={`w-full mt-2 rounded-lg h-10 box-border px-3 ${s.projectName} bg-gray-100`}
|
||||||
value={inputInfo.chatColorTheme ?? ''}
|
value={inputInfo.chatColorTheme ?? ''}
|
||||||
onChange={onChange('chatColorTheme')}
|
onChange={onChange('chatColorTheme')}
|
||||||
placeholder= 'E.g #A020F0'
|
placeholder='E.g #A020F0'
|
||||||
/>
|
/>
|
||||||
</>}
|
</>}
|
||||||
|
{systemFeatures.enable_web_sso_switch_component && <div className='w-full mt-8'>
|
||||||
|
<p className='system-xs-medium text-gray-500'>{t(`${prefixSettings}.sso.label`)}</p>
|
||||||
|
<div className='flex justify-between items-center'>
|
||||||
|
<div className='font-medium system-sm-semibold flex-grow text-gray-900'>{t(`${prefixSettings}.sso.title`)}</div>
|
||||||
|
<TooltipPlus disabled={systemFeatures.sso_enforced_for_web} popupContent={<div className='w-[180px]'>{t(`${prefixSettings}.sso.tooltip`)}</div>}>
|
||||||
|
<Switch disabled={!systemFeatures.sso_enforced_for_web} defaultValue={systemFeatures.sso_enforced_for_web && inputInfo.enable_sso} onChange={v => setInputInfo({ ...inputInfo, enable_sso: v })}></Switch>
|
||||||
|
</TooltipPlus>
|
||||||
|
</div>
|
||||||
|
<p className='body-xs-regular text-gray-500'>{t(`${prefixSettings}.sso.description`)}</p>
|
||||||
|
</div>}
|
||||||
{!isShowMore && <div className='w-full cursor-pointer mt-8' onClick={() => setIsShowMore(true)}>
|
{!isShowMore && <div className='w-full cursor-pointer mt-8' onClick={() => setIsShowMore(true)}>
|
||||||
<div className='flex justify-between'>
|
<div className='flex justify-between'>
|
||||||
<div className={`font-medium ${s.settingTitle} flex-grow text-gray-900`}>{t(`${prefixSettings}.more.entry`)}</div>
|
<div className={`font-medium ${s.settingTitle} flex-grow text-gray-900`}>{t(`${prefixSettings}.more.entry`)}</div>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { create } from 'zustand'
|
import { create } from 'zustand'
|
||||||
import type { App } from '@/types/app'
|
import type { App, AppSSO } from '@/types/app'
|
||||||
import type { IChatItem } from '@/app/components/base/chat/chat/type'
|
import type { IChatItem } from '@/app/components/base/chat/chat/type'
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
appDetail?: App
|
appDetail?: App & Partial<AppSSO>
|
||||||
appSidebarExpand: string
|
appSidebarExpand: string
|
||||||
currentLogItem?: IChatItem
|
currentLogItem?: IChatItem
|
||||||
currentLogModalActiveTab: string
|
currentLogModalActiveTab: string
|
||||||
@ -13,7 +13,7 @@ type State = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Action = {
|
type Action = {
|
||||||
setAppDetail: (appDetail?: App) => void
|
setAppDetail: (appDetail?: App & Partial<AppSSO>) => void
|
||||||
setAppSiderbarExpand: (state: string) => void
|
setAppSiderbarExpand: (state: string) => void
|
||||||
setCurrentLogItem: (item?: IChatItem) => void
|
setCurrentLogItem: (item?: IChatItem) => void
|
||||||
setCurrentLogModalActiveTab: (tab: string) => void
|
setCurrentLogModalActiveTab: (tab: string) => void
|
||||||
|
@ -6,16 +6,19 @@ import { createContext, useContext, useContextSelector } from 'use-context-selec
|
|||||||
import type { FC, ReactNode } from 'react'
|
import type { FC, ReactNode } from 'react'
|
||||||
import { fetchAppList } from '@/service/apps'
|
import { fetchAppList } from '@/service/apps'
|
||||||
import Loading from '@/app/components/base/loading'
|
import Loading from '@/app/components/base/loading'
|
||||||
import { fetchCurrentWorkspace, fetchLanggeniusVersion, fetchUserProfile } from '@/service/common'
|
import { fetchCurrentWorkspace, fetchLanggeniusVersion, fetchUserProfile, getSystemFeatures } from '@/service/common'
|
||||||
import type { App } from '@/types/app'
|
import type { App } from '@/types/app'
|
||||||
import { Theme } from '@/types/app'
|
import { Theme } from '@/types/app'
|
||||||
import type { ICurrentWorkspace, LangGeniusVersionResponse, UserProfileResponse } from '@/models/common'
|
import type { ICurrentWorkspace, LangGeniusVersionResponse, UserProfileResponse } from '@/models/common'
|
||||||
import MaintenanceNotice from '@/app/components/header/maintenance-notice'
|
import MaintenanceNotice from '@/app/components/header/maintenance-notice'
|
||||||
|
import type { SystemFeatures } from '@/types/feature'
|
||||||
|
import { defaultSystemFeatures } from '@/types/feature'
|
||||||
|
|
||||||
export type AppContextValue = {
|
export type AppContextValue = {
|
||||||
theme: Theme
|
theme: Theme
|
||||||
setTheme: (theme: Theme) => void
|
setTheme: (theme: Theme) => void
|
||||||
apps: App[]
|
apps: App[]
|
||||||
|
systemFeatures: SystemFeatures
|
||||||
mutateApps: VoidFunction
|
mutateApps: VoidFunction
|
||||||
userProfile: UserProfileResponse
|
userProfile: UserProfileResponse
|
||||||
mutateUserProfile: VoidFunction
|
mutateUserProfile: VoidFunction
|
||||||
@ -53,6 +56,7 @@ const initialWorkspaceInfo: ICurrentWorkspace = {
|
|||||||
|
|
||||||
const AppContext = createContext<AppContextValue>({
|
const AppContext = createContext<AppContextValue>({
|
||||||
theme: Theme.light,
|
theme: Theme.light,
|
||||||
|
systemFeatures: defaultSystemFeatures,
|
||||||
setTheme: () => { },
|
setTheme: () => { },
|
||||||
apps: [],
|
apps: [],
|
||||||
mutateApps: () => { },
|
mutateApps: () => { },
|
||||||
@ -90,6 +94,10 @@ export const AppContextProvider: FC<AppContextProviderProps> = ({ children }) =>
|
|||||||
const { data: userProfileResponse, mutate: mutateUserProfile } = useSWR({ url: '/account/profile', params: {} }, fetchUserProfile)
|
const { data: userProfileResponse, mutate: mutateUserProfile } = useSWR({ url: '/account/profile', params: {} }, fetchUserProfile)
|
||||||
const { data: currentWorkspaceResponse, mutate: mutateCurrentWorkspace } = useSWR({ url: '/workspaces/current', params: {} }, fetchCurrentWorkspace)
|
const { data: currentWorkspaceResponse, mutate: mutateCurrentWorkspace } = useSWR({ url: '/workspaces/current', params: {} }, fetchCurrentWorkspace)
|
||||||
|
|
||||||
|
const { data: systemFeatures } = useSWR({ url: '/console/system-features' }, getSystemFeatures, {
|
||||||
|
fallbackData: defaultSystemFeatures,
|
||||||
|
})
|
||||||
|
|
||||||
const [userProfile, setUserProfile] = useState<UserProfileResponse>()
|
const [userProfile, setUserProfile] = useState<UserProfileResponse>()
|
||||||
const [langeniusVersionInfo, setLangeniusVersionInfo] = useState<LangGeniusVersionResponse>(initialLangeniusVersionInfo)
|
const [langeniusVersionInfo, setLangeniusVersionInfo] = useState<LangGeniusVersionResponse>(initialLangeniusVersionInfo)
|
||||||
const [currentWorkspace, setCurrentWorkspace] = useState<ICurrentWorkspace>(initialWorkspaceInfo)
|
const [currentWorkspace, setCurrentWorkspace] = useState<ICurrentWorkspace>(initialWorkspaceInfo)
|
||||||
@ -136,6 +144,7 @@ export const AppContextProvider: FC<AppContextProviderProps> = ({ children }) =>
|
|||||||
theme,
|
theme,
|
||||||
setTheme: handleSetTheme,
|
setTheme: handleSetTheme,
|
||||||
apps: appList.data,
|
apps: appList.data,
|
||||||
|
systemFeatures,
|
||||||
mutateApps,
|
mutateApps,
|
||||||
userProfile,
|
userProfile,
|
||||||
mutateUserProfile,
|
mutateUserProfile,
|
||||||
|
@ -53,6 +53,12 @@ const translation = {
|
|||||||
chatColorThemeDesc: 'Set the color theme of the chatbot',
|
chatColorThemeDesc: 'Set the color theme of the chatbot',
|
||||||
chatColorThemeInverted: 'Inverted',
|
chatColorThemeInverted: 'Inverted',
|
||||||
invalidHexMessage: 'Invalid hex value',
|
invalidHexMessage: 'Invalid hex value',
|
||||||
|
sso: {
|
||||||
|
label: 'SSO Authentication',
|
||||||
|
title: 'WebApp SSO',
|
||||||
|
description: 'All users are required to login with SSO before using WebApp',
|
||||||
|
tooltip: 'Contact the administrator to enable WebApp SSO',
|
||||||
|
},
|
||||||
more: {
|
more: {
|
||||||
entry: 'Show more settings',
|
entry: 'Show more settings',
|
||||||
copyright: 'Copyright',
|
copyright: 'Copyright',
|
||||||
|
@ -53,6 +53,12 @@ const translation = {
|
|||||||
chatColorThemeDesc: '设置聊天机器人的颜色主题',
|
chatColorThemeDesc: '设置聊天机器人的颜色主题',
|
||||||
chatColorThemeInverted: '反转',
|
chatColorThemeInverted: '反转',
|
||||||
invalidHexMessage: '无效的十六进制值',
|
invalidHexMessage: '无效的十六进制值',
|
||||||
|
sso: {
|
||||||
|
label: '单点登录认证',
|
||||||
|
title: 'WebApp SSO 认证',
|
||||||
|
description: '启用后,所有用户都需要先进行 SSO 认证才能访问',
|
||||||
|
tooltip: '联系管理员以开启 WebApp SSO 认证',
|
||||||
|
},
|
||||||
more: {
|
more: {
|
||||||
entry: '展示更多设置',
|
entry: '展示更多设置',
|
||||||
copyright: '版权',
|
copyright: '版权',
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import type { LangFuseConfig, LangSmithConfig, TracingProvider } from '@/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/type'
|
import type { LangFuseConfig, LangSmithConfig, TracingProvider } from '@/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/type'
|
||||||
import type { App, AppTemplate, SiteConfig } from '@/types/app'
|
import type { App, AppSSO, AppTemplate, SiteConfig } from '@/types/app'
|
||||||
|
|
||||||
/* export type App = {
|
/* export type App = {
|
||||||
id: string
|
id: string
|
||||||
@ -67,6 +67,7 @@ export type AppListResponse = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type AppDetailResponse = App
|
export type AppDetailResponse = App
|
||||||
|
export type AppSSOResponse = { enabled: AppSSO['enable_sso'] }
|
||||||
|
|
||||||
export type AppTemplatesResponse = {
|
export type AppTemplatesResponse = {
|
||||||
data: AppTemplate[]
|
data: AppTemplate[]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import type { Fetcher } from 'swr'
|
import type { Fetcher } from 'swr'
|
||||||
import { del, get, patch, post, put } from './base'
|
import { del, get, patch, post, put } from './base'
|
||||||
import type { ApikeysListResponse, AppDailyConversationsResponse, AppDailyEndUsersResponse, AppDetailResponse, AppListResponse, AppStatisticsResponse, AppTemplatesResponse, AppTokenCostsResponse, AppVoicesListResponse, CreateApiKeyResponse, GenerationIntroductionResponse, TracingConfig, TracingStatus, UpdateAppModelConfigResponse, UpdateAppSiteCodeResponse, UpdateOpenAIKeyResponse, ValidateOpenAIKeyResponse, WorkflowDailyConversationsResponse } from '@/models/app'
|
import type { ApikeysListResponse, AppDailyConversationsResponse, AppDailyEndUsersResponse, AppDetailResponse, AppListResponse, AppSSOResponse, AppStatisticsResponse, AppTemplatesResponse, AppTokenCostsResponse, AppVoicesListResponse, CreateApiKeyResponse, GenerationIntroductionResponse, TracingConfig, TracingStatus, UpdateAppModelConfigResponse, UpdateAppSiteCodeResponse, UpdateOpenAIKeyResponse, ValidateOpenAIKeyResponse, WorkflowDailyConversationsResponse } from '@/models/app'
|
||||||
import type { CommonResponse } from '@/models/common'
|
import type { CommonResponse } from '@/models/common'
|
||||||
import type { AppIconType, AppMode, ModelConfig } from '@/types/app'
|
import type { AppIconType, AppMode, ModelConfig } from '@/types/app'
|
||||||
import type { TracingProvider } from '@/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/type'
|
import type { TracingProvider } from '@/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/type'
|
||||||
@ -13,6 +13,13 @@ export const fetchAppDetail = ({ url, id }: { url: string; id: string }) => {
|
|||||||
return get<AppDetailResponse>(`${url}/${id}`)
|
return get<AppDetailResponse>(`${url}/${id}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const fetchAppSSO = async ({ appId }: { appId: string }) => {
|
||||||
|
return get<AppSSOResponse>(`/enterprise/app-setting/sso?appID=${appId}`)
|
||||||
|
}
|
||||||
|
export const updateAppSSO = async ({ id, enabled }: { id: string; enabled: boolean }) => {
|
||||||
|
return post('/enterprise/app-setting/sso', { body: { app_id: id, enabled } })
|
||||||
|
}
|
||||||
|
|
||||||
export const fetchAppTemplates: Fetcher<AppTemplatesResponse, { url: string }> = ({ url }) => {
|
export const fetchAppTemplates: Fetcher<AppTemplatesResponse, { url: string }> = ({ url }) => {
|
||||||
return get<AppTemplatesResponse>(url)
|
return get<AppTemplatesResponse>(url)
|
||||||
}
|
}
|
||||||
|
@ -348,6 +348,10 @@ export type App = {
|
|||||||
tags: Tag[]
|
tags: Tag[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type AppSSO = {
|
||||||
|
enable_sso: boolean
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* App Template
|
* App Template
|
||||||
*/
|
*/
|
||||||
|
@ -3,6 +3,7 @@ export type SystemFeatures = {
|
|||||||
sso_enforced_for_signin_protocol: string
|
sso_enforced_for_signin_protocol: string
|
||||||
sso_enforced_for_web: boolean
|
sso_enforced_for_web: boolean
|
||||||
sso_enforced_for_web_protocol: string
|
sso_enforced_for_web_protocol: string
|
||||||
|
enable_web_sso_switch_component: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export const defaultSystemFeatures: SystemFeatures = {
|
export const defaultSystemFeatures: SystemFeatures = {
|
||||||
@ -10,4 +11,5 @@ export const defaultSystemFeatures: SystemFeatures = {
|
|||||||
sso_enforced_for_signin_protocol: '',
|
sso_enforced_for_signin_protocol: '',
|
||||||
sso_enforced_for_web: false,
|
sso_enforced_for_web: false,
|
||||||
sso_enforced_for_web_protocol: '',
|
sso_enforced_for_web_protocol: '',
|
||||||
|
enable_web_sso_switch_component: false,
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user