diff --git a/web/app/(shareLayout)/webapp-signin/page.tsx b/web/app/(shareLayout)/webapp-signin/page.tsx
index 90f081f75f..adc1253ac8 100644
--- a/web/app/(shareLayout)/webapp-signin/page.tsx
+++ b/web/app/(shareLayout)/webapp-signin/page.tsx
@@ -23,10 +23,12 @@ const WebSSOForm: FC = () => {
const redirectUrl = searchParams.get('redirect_url')
const tokenFromUrl = searchParams.get('web_sso_token')
const message = searchParams.get('message')
+ const code = searchParams.get('code')
const getSigninUrl = useCallback(() => {
const params = new URLSearchParams(searchParams)
params.delete('message')
+ params.delete('code')
return `/webapp-signin?${params.toString()}`
}, [searchParams])
@@ -85,8 +87,8 @@ const WebSSOForm: FC = () => {
if (message) {
return
+
{appDetail?.access_mode === AccessMode.ORGANIZATION
&& <>
@@ -263,7 +263,9 @@ const AppPublisher = ({
{appDetail?.access_mode === AccessMode.SPECIFIC_GROUPS_MEMBERS
&& <>
-
{t('app.accessControlDialog.accessItems.specific')}
+
+ {t('app.accessControlDialog.accessItems.specific')}
+
>
}
{appDetail?.access_mode === AccessMode.PUBLIC
diff --git a/web/app/components/base/chat/chat-with-history/index.tsx b/web/app/components/base/chat/chat-with-history/index.tsx
index 0470389ec3..7c87975394 100644
--- a/web/app/components/base/chat/chat-with-history/index.tsx
+++ b/web/app/components/base/chat/chat-with-history/index.tsx
@@ -1,9 +1,13 @@
+'use client'
import type { FC } from 'react'
import {
+ useCallback,
useEffect,
useState,
} from 'react'
import { useAsyncEffect } from 'ahooks'
+import { useTranslation } from 'react-i18next'
+import { usePathname, useRouter, useSearchParams } from 'next/navigation'
import { useThemeContext } from '../embedded-chatbot/theme/theme-context'
import {
ChatWithHistoryContext,
@@ -17,8 +21,9 @@ import ChatWrapper from './chat-wrapper'
import type { InstalledApp } from '@/models/explore'
import Loading from '@/app/components/base/loading'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
-import { checkOrSetAccessToken } from '@/app/components/share/utils'
+import { checkOrSetAccessToken, removeAccessToken } from '@/app/components/share/utils'
import AppUnavailable from '@/app/components/base/app-unavailable'
+import useDocumentTitle from '@/hooks/use-document-title'
type ChatWithHistoryProps = {
className?: string
@@ -37,6 +42,7 @@ const ChatWithHistory: FC
= ({
chatShouldReloadKey,
isMobile,
themeBuilder,
+ isInstalledApp,
} = useChatWithHistoryContext()
const chatReady = (!showConfigPanelBeforeChat || !!appPrevChatTree.length)
@@ -53,13 +59,36 @@ const ChatWithHistory: FC = ({
}
}, [site, customConfig, themeBuilder])
+ useDocumentTitle(site?.title || 'Chat')
+
+ const { t } = useTranslation()
+ const searchParams = useSearchParams()
+ const router = useRouter()
+ const pathname = usePathname()
+ const getSigninUrl = useCallback(() => {
+ const params = new URLSearchParams(searchParams)
+ params.delete('message')
+ params.set('redirect_url', pathname)
+ return `/webapp-signin?${params.toString()}`
+ }, [searchParams, pathname])
+
+ const backToHome = useCallback(() => {
+ removeAccessToken()
+ const url = getSigninUrl()
+ router.replace(url)
+ }, [getSigninUrl, router])
+
if (appInfoLoading) {
return (
)
}
- if (!userCanAccess)
- return
+ if (!userCanAccess) {
+ return
+
+ {!isInstalledApp &&
{t('common.userProfile.logout')}}
+
+ }
if (appInfoError) {
return (
diff --git a/web/app/components/base/chat/embedded-chatbot/index.tsx b/web/app/components/base/chat/embedded-chatbot/index.tsx
index 201f38a7f1..431a7a7ee2 100644
--- a/web/app/components/base/chat/embedded-chatbot/index.tsx
+++ b/web/app/components/base/chat/embedded-chatbot/index.tsx
@@ -1,10 +1,14 @@
+'use client'
import {
+ useCallback,
useEffect,
useState,
} from 'react'
import { useAsyncEffect } from 'ahooks'
import { useTranslation } from 'react-i18next'
import { RiLoopLeftLine } from '@remixicon/react'
+import { usePathname, useRouter, useSearchParams } from 'next/navigation'
+import Tooltip from '../../tooltip'
import {
EmbeddedChatbotContext,
useEmbeddedChatbotContext,
@@ -12,8 +16,7 @@ import {
import { useEmbeddedChatbot } from './hooks'
import { isDify } from './utils'
import { useThemeContext } from './theme/theme-context'
-import cn from '@/utils/classnames'
-import { checkOrSetAccessToken } from '@/app/components/share/utils'
+import { checkOrSetAccessToken, removeAccessToken } from '@/app/components/share/utils'
import AppUnavailable from '@/app/components/base/app-unavailable'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import Loading from '@/app/components/base/loading'
@@ -21,7 +24,8 @@ import LogoHeader from '@/app/components/base/logo/logo-embedded-chat-header'
import Header from '@/app/components/base/chat/embedded-chatbot/header'
import ConfigPanel from '@/app/components/base/chat/embedded-chatbot/config-panel'
import ChatWrapper from '@/app/components/base/chat/embedded-chatbot/chat-wrapper'
-import Tooltip from '@/app/components/base/tooltip'
+import cn from '@/utils/classnames'
+import useDocumentTitle from '@/hooks/use-document-title'
const Chatbot = () => {
const { t } = useTranslation()
@@ -36,6 +40,7 @@ const Chatbot = () => {
appChatListDataLoading,
handleNewConversation,
themeBuilder,
+ isInstalledApp,
} = useEmbeddedChatbotContext()
const chatReady = (!showConfigPanelBeforeChat || !!appPrevChatList.length)
@@ -54,14 +59,36 @@ const Chatbot = () => {
}
}, [site, customConfig, themeBuilder])
+ useDocumentTitle(site?.title || 'Chat')
+
+ const searchParams = useSearchParams()
+ const router = useRouter()
+ const pathname = usePathname()
+ const getSigninUrl = useCallback(() => {
+ const params = new URLSearchParams(searchParams)
+ params.delete('message')
+ params.set('redirect_url', pathname)
+ return `/webapp-signin?${params.toString()}`
+ }, [searchParams, pathname])
+
+ const backToHome = useCallback(() => {
+ removeAccessToken()
+ const url = getSigninUrl()
+ router.replace(url)
+ }, [getSigninUrl, router])
+
if (appInfoLoading) {
return (
)
}
- if (!userCanAccess)
- return
+ if (!userCanAccess) {
+ return
+
+ {!isInstalledApp &&
{t('common.userProfile.logout')}}
+
+ }
if (appInfoError) {
return (
@@ -118,7 +145,6 @@ const EmbeddedChatbotWrapper = () => {
appInfoError,
appInfoLoading,
appData,
- accessMode,
userCanAccess,
appParams,
appMeta,
@@ -146,7 +172,6 @@ const EmbeddedChatbotWrapper = () => {
return = ({
const { isPending: isGettingAccessMode, data: appAccessMode } = useGetAppAccessMode({ appId, isInstalledApp })
const { isPending: isCheckingPermission, data: userCanAccessResult } = useGetUserCanAccessApp({ appId, isInstalledApp })
+ const systemFeatures = useGlobalPublicStore(s => s.systemFeatures)
// save message
const [savedMessages, setSavedMessages] = useState([])
const fetchSavedMessage = async () => {
@@ -544,14 +546,31 @@ const TextGeneration: FC = ({
)
- if (!appId || !siteInfo || !promptConfig || isGettingAccessMode || isCheckingPermission) {
+ const getSigninUrl = useCallback(() => {
+ const params = new URLSearchParams(searchParams)
+ params.delete('message')
+ params.set('redirect_url', pathname)
+ return `/webapp-signin?${params.toString()}`
+ }, [searchParams, pathname])
+
+ const backToHome = useCallback(() => {
+ removeAccessToken()
+ const url = getSigninUrl()
+ router.replace(url)
+ }, [getSigninUrl, router])
+
+ if (!appId || !siteInfo || !promptConfig || (systemFeatures.webapp_auth.enabled && (isGettingAccessMode || isCheckingPermission))) {
return (
)
}
- if (!userCanAccessResult?.result)
- return
+ if (systemFeatures.webapp_auth.enabled && !userCanAccessResult?.result) {
+ return
+
+ {!isInstalledApp &&
{t('common.userProfile.logout')}}
+
+ }
return (
<>
diff --git a/web/service/base.ts b/web/service/base.ts
index cf025b22db..79c7439b21 100644
--- a/web/service/base.ts
+++ b/web/service/base.ts
@@ -122,12 +122,13 @@ function unicodeToChar(text: string) {
})
}
-function requiredWebSSOLogin(message?: string) {
- removeAccessToken()
+function requiredWebSSOLogin(message?: string, code?: number) {
const params = new URLSearchParams()
params.append('redirect_url', globalThis.location.pathname)
if (message)
params.append('message', message)
+ if (code)
+ params.append('code', String(code))
globalThis.location.href = `/webapp-signin?${params.toString()}`
}
@@ -518,10 +519,12 @@ export const ssePost = (
res.json().then((data: any) => {
if (isPublicAPI) {
if (data.code === 'web_app_access_denied')
- requiredWebSSOLogin(data.message)
+ requiredWebSSOLogin(data.message, 403)
- if (data.code === 'web_sso_auth_required')
+ if (data.code === 'web_sso_auth_required') {
+ removeAccessToken()
requiredWebSSOLogin()
+ }
if (data.code === 'unauthorized') {
removeAccessToken()
@@ -575,10 +578,11 @@ export const request = async
(url: string, options = {}, otherOptions?: IOther
const { code, message } = errRespData
// webapp sso
if (code === 'web_app_access_denied') {
- requiredWebSSOLogin(message)
+ requiredWebSSOLogin(message, 403)
return Promise.reject(err)
}
if (code === 'web_sso_auth_required') {
+ removeAccessToken()
requiredWebSSOLogin()
return Promise.reject(err)
}