diff --git a/web/app/components/base/app-unavailable.tsx b/web/app/components/base/app-unavailable.tsx index b8b42108a9..ea20464b1b 100644 --- a/web/app/components/base/app-unavailable.tsx +++ b/web/app/components/base/app-unavailable.tsx @@ -17,7 +17,7 @@ const AppUnavailable: FC = ({ const { t } = useTranslation() return ( -
+

({ + isFromExplore: false, + accessMode: AccessMode.SPECIFIC_GROUPS_MEMBERS, + userCanAccess: false, currentConversationId: '', appPrevChatTree: [], pinnedConversationList: [], @@ -59,21 +66,21 @@ export const ChatWithHistoryContext = createContext showConfigPanelBeforeChat: false, newConversationInputs: {}, newConversationInputsRef: { current: {} }, - handleNewConversationInputsChange: () => {}, + handleNewConversationInputsChange: () => { }, inputsForms: [], - handleNewConversation: () => {}, - handleStartChat: () => {}, - handleChangeConversation: () => {}, - handlePinConversation: () => {}, - handleUnpinConversation: () => {}, - handleDeleteConversation: () => {}, + handleNewConversation: () => { }, + handleStartChat: () => { }, + handleChangeConversation: () => { }, + handlePinConversation: () => { }, + handleUnpinConversation: () => { }, + handleDeleteConversation: () => { }, conversationRenaming: false, - handleRenameConversation: () => {}, - handleNewConversationCompleted: () => {}, + handleRenameConversation: () => { }, + handleNewConversationCompleted: () => { }, chatShouldReloadKey: '', isMobile: false, isInstalledApp: false, - handleFeedback: () => {}, - currentChatInstanceRef: { current: { handleStop: () => {} } }, + handleFeedback: () => { }, + currentChatInstanceRef: { current: { handleStop: () => { } } }, }) export const useChatWithHistoryContext = () => useContext(ChatWithHistoryContext) diff --git a/web/app/components/base/chat/chat-with-history/hooks.tsx b/web/app/components/base/chat/chat-with-history/hooks.tsx index 64dbb13acf..cc3ad7ece8 100644 --- a/web/app/components/base/chat/chat-with-history/hooks.tsx +++ b/web/app/components/base/chat/chat-with-history/hooks.tsx @@ -42,6 +42,7 @@ import { changeLanguage } from '@/i18n/i18next-config' import { useAppFavicon } from '@/hooks/use-app-favicon' import { InputVarType } from '@/app/components/workflow/types' import { TransferMethod } from '@/types/app' +import { useGetAppAccessMode, useGetUserCanAccessApp } from '@/service/access-control' function getFormattedChatList(messages: any[]) { const newChatList: ChatItem[] = [] @@ -72,6 +73,8 @@ function getFormattedChatList(messages: any[]) { export const useChatWithHistory = (installedAppInfo?: InstalledApp) => { const isInstalledApp = useMemo(() => !!installedAppInfo, [installedAppInfo]) const { data: appInfo, isLoading: appInfoLoading, error: appInfoError } = useSWR(installedAppInfo ? null : 'appInfo', fetchAppInfo) + const { isPending: isGettingAccessMode, data: appAccessMode } = useGetAppAccessMode(installedAppInfo?.app.id || appInfo?.app_id) + const { isPending: isCheckingPermission, data: userCanAccessResult } = useGetUserCanAccessApp(installedAppInfo?.app.id || appInfo?.app_id) useAppFavicon({ enable: !installedAppInfo, @@ -418,7 +421,9 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => { return { appInfoError, - appInfoLoading, + appInfoLoading: appInfoLoading || isGettingAccessMode || isCheckingPermission, + accessMode: appAccessMode?.accessMode, + userCanAccess: userCanAccessResult?.result, isInstalledApp, appId, currentConversationId, 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 7282dd4216..b794cd5e5d 100644 --- a/web/app/components/base/chat/chat-with-history/index.tsx +++ b/web/app/components/base/chat/chat-with-history/index.tsx @@ -27,6 +27,7 @@ const ChatWithHistory: FC = ({ className, }) => { const { + userCanAccess, appInfoError, appData, appInfoLoading, @@ -57,6 +58,8 @@ const ChatWithHistory: FC = ({ ) } + if (!userCanAccess) + return if (appInfoError) { return ( @@ -102,10 +105,12 @@ const ChatWithHistory: FC = ({ export type ChatWithHistoryWrapProps = { installedAppInfo?: InstalledApp className?: string + isFromExplore?: boolean } const ChatWithHistoryWrap: FC = ({ installedAppInfo, className, + isFromExplore, }) => { const media = useBreakpoints() const isMobile = media === MediaType.mobile @@ -114,6 +119,8 @@ const ChatWithHistoryWrap: FC = ({ const { appInfoError, appInfoLoading, + accessMode, + userCanAccess, appData, appParams, appMeta, @@ -146,9 +153,12 @@ const ChatWithHistoryWrap: FC = ({ return ( = ({ const ChatWithHistoryWrapWithCheckToken: FC = ({ installedAppInfo, className, + isFromExplore = false, }) => { const [initialized, setInitialized] = useState(false) const [appUnavailable, setAppUnavailable] = useState(false) @@ -222,6 +233,7 @@ const ChatWithHistoryWrapWithCheckToken: FC = ({ ) } diff --git a/web/app/components/base/chat/chat-with-history/sidebar/index.tsx b/web/app/components/base/chat/chat-with-history/sidebar/index.tsx index a4d0af3388..18d30fde9b 100644 --- a/web/app/components/base/chat/chat-with-history/sidebar/index.tsx +++ b/web/app/components/base/chat/chat-with-history/sidebar/index.tsx @@ -12,10 +12,13 @@ import type { ConversationItem } from '@/models/share' import Confirm from '@/app/components/base/confirm' import RenameModal from '@/app/components/base/chat/chat-with-history/sidebar/rename-modal' import MenuDropdown from '@/app/components/share/text-generation/menu-dropdown' +import { AccessMode } from '@/models/access-control' const Sidebar = () => { const { t } = useTranslation() const { + isFromExplore, + accessMode, appData, pinnedConversationList, conversationList, @@ -117,7 +120,7 @@ const Sidebar = () => { }

- + {appData?.site.copyright && (
© {(new Date()).getFullYear()} {appData?.site.copyright} diff --git a/web/app/components/base/chat/embedded-chatbot/context.tsx b/web/app/components/base/chat/embedded-chatbot/context.tsx index f48247a691..b24344260f 100644 --- a/web/app/components/base/chat/embedded-chatbot/context.tsx +++ b/web/app/components/base/chat/embedded-chatbot/context.tsx @@ -14,8 +14,12 @@ import type { AppMeta, ConversationItem, } from '@/models/share' +import { AccessMode } from '@/models/access-control' export type EmbeddedChatbotContextValue = { + isFromExplore: boolean + accessMode?: AccessMode + userCanAccess?: boolean appInfoError?: any appInfoLoading?: boolean appMeta?: AppMeta @@ -46,6 +50,9 @@ export type EmbeddedChatbotContextValue = { } export const EmbeddedChatbotContext = createContext({ + isFromExplore: false, + userCanAccess: false, + accessMode: AccessMode.SPECIFIC_GROUPS_MEMBERS, currentConversationId: '', appPrevChatList: [], pinnedConversationList: [], @@ -53,16 +60,16 @@ export const EmbeddedChatbotContext = createContext showConfigPanelBeforeChat: false, newConversationInputs: {}, newConversationInputsRef: { current: {} }, - handleNewConversationInputsChange: () => {}, + handleNewConversationInputsChange: () => { }, inputsForms: [], - handleNewConversation: () => {}, - handleStartChat: () => {}, - handleChangeConversation: () => {}, - handleNewConversationCompleted: () => {}, + handleNewConversation: () => { }, + handleStartChat: () => { }, + handleChangeConversation: () => { }, + handleNewConversationCompleted: () => { }, chatShouldReloadKey: '', isMobile: false, isInstalledApp: false, - handleFeedback: () => {}, - currentChatInstanceRef: { current: { handleStop: () => {} } }, + handleFeedback: () => { }, + currentChatInstanceRef: { current: { handleStop: () => { } } }, }) export const useEmbeddedChatbotContext = () => useContext(EmbeddedChatbotContext) diff --git a/web/app/components/base/chat/embedded-chatbot/hooks.tsx b/web/app/components/base/chat/embedded-chatbot/hooks.tsx index 077eefc325..90070d0cc0 100644 --- a/web/app/components/base/chat/embedded-chatbot/hooks.tsx +++ b/web/app/components/base/chat/embedded-chatbot/hooks.tsx @@ -35,6 +35,7 @@ import { changeLanguage } from '@/i18n/i18next-config' import { InputVarType } from '@/app/components/workflow/types' import { TransferMethod } from '@/types/app' import { addFileInfos, sortAgentSorts } from '@/app/components/tools/utils' +import { useGetAppAccessMode, useGetUserCanAccessApp } from '@/service/access-control' function getFormattedChatList(messages: any[]) { const newChatList: ChatItem[] = [] @@ -65,6 +66,8 @@ function getFormattedChatList(messages: any[]) { export const useEmbeddedChatbot = () => { const isInstalledApp = false const { data: appInfo, isLoading: appInfoLoading, error: appInfoError } = useSWR('appInfo', fetchAppInfo) + const { isPending: isGettingAccessMode, data: appAccessMode } = useGetAppAccessMode(appInfo?.app_id) + const { isPending: isCheckingPermission, data: userCanAccessResult } = useGetUserCanAccessApp(appInfo?.app_id) const appData = useMemo(() => { return appInfo @@ -319,7 +322,9 @@ export const useEmbeddedChatbot = () => { return { appInfoError, - appInfoLoading, + appInfoLoading: appInfoLoading || isGettingAccessMode || isCheckingPermission, + accessMode: appAccessMode?.accessMode, + userCanAccess: userCanAccessResult?.result, isInstalledApp, appId, currentConversationId, diff --git a/web/app/components/base/chat/embedded-chatbot/index.tsx b/web/app/components/base/chat/embedded-chatbot/index.tsx index 703dde1076..384ec1dfb6 100644 --- a/web/app/components/base/chat/embedded-chatbot/index.tsx +++ b/web/app/components/base/chat/embedded-chatbot/index.tsx @@ -26,6 +26,8 @@ import Tooltip from '@/app/components/base/tooltip' const Chatbot = () => { const { t } = useTranslation() const { + isFromExplore, + userCanAccess, isMobile, appInfoError, appInfoLoading, @@ -59,6 +61,9 @@ const Chatbot = () => { ) } + if (!userCanAccess) + return + if (appInfoError) { return ( @@ -91,7 +96,7 @@ const Chatbot = () => { popupContent={t('share.chat.resetChat')} >
- +
@@ -105,7 +110,11 @@ const Chatbot = () => { ) } -const EmbeddedChatbotWrapper = () => { +type EmbeddedChatbotProps = { + isFromExplore?: boolean +} + +const EmbeddedChatbotWrapper = ({ isFromExplore }: EmbeddedChatbotProps) => { const media = useBreakpoints() const isMobile = media === MediaType.mobile const themeBuilder = useThemeContext() @@ -114,6 +123,8 @@ const EmbeddedChatbotWrapper = () => { appInfoError, appInfoLoading, appData, + accessMode, + userCanAccess, appParams, appMeta, appChatListDataLoading, @@ -139,6 +150,9 @@ const EmbeddedChatbotWrapper = () => { } = useEmbeddedChatbot() return { } -const EmbeddedChatbot = () => { +const EmbeddedChatbot = ({ isFromExplore = false }: EmbeddedChatbotProps) => { const [initialized, setInitialized] = useState(false) const [appUnavailable, setAppUnavailable] = useState(false) const [isUnknownReason, setIsUnknownReason] = useState(false) @@ -200,7 +214,7 @@ const EmbeddedChatbot = () => { if (appUnavailable) return - return + return } export default EmbeddedChatbot diff --git a/web/app/components/explore/installed-app/index.tsx b/web/app/components/explore/installed-app/index.tsx index 2785fcc4bc..221ca12daa 100644 --- a/web/app/components/explore/installed-app/index.tsx +++ b/web/app/components/explore/installed-app/index.tsx @@ -26,15 +26,15 @@ const InstalledApp: FC = ({ } return ( -
+
{installedApp.app.mode !== 'completion' && installedApp.app.mode !== 'workflow' && ( - + )} {installedApp.app.mode === 'completion' && ( - + )} {installedApp.app.mode === 'workflow' && ( - + )}
) diff --git a/web/app/components/share/text-generation/index.tsx b/web/app/components/share/text-generation/index.tsx index 34c6ce41a6..0f0accd2f8 100644 --- a/web/app/components/share/text-generation/index.tsx +++ b/web/app/components/share/text-generation/index.tsx @@ -11,6 +11,7 @@ import { usePathname, useRouter, useSearchParams } from 'next/navigation' import TabHeader from '../../base/tab-header' import Button from '../../base/button' import { checkOrSetAccessToken } from '../utils' +import AppUnavailable from '../../base/app-unavailable' import s from './style.module.css' import RunBatch from './run-batch' import ResDownload from './run-batch/res-download' @@ -38,6 +39,8 @@ import Toast from '@/app/components/base/toast' import type { VisionFile, VisionSettings } from '@/types/app' import { Resolution, TransferMethod } from '@/types/app' import { useAppFavicon } from '@/hooks/use-app-favicon' +import { useGetAppAccessMode, useGetUserCanAccessApp } from '@/service/access-control' +import { AccessMode } from '@/models/access-control' const GROUP_SIZE = 5 // to avoid RPM(Request per minute) limit. The group task finished then the next group. enum TaskStatus { @@ -61,12 +64,14 @@ export type IMainProps = { isInstalledApp?: boolean installedAppInfo?: InstalledApp isWorkflow?: boolean + isFromExplore?: boolean } const TextGeneration: FC = ({ isInstalledApp = false, installedAppInfo, isWorkflow = false, + isFromExplore = false, }) => { const { notify } = Toast @@ -107,6 +112,9 @@ const TextGeneration: FC = ({ const [moreLikeThisConfig, setMoreLikeThisConfig] = useState(null) const [textToSpeechConfig, setTextToSpeechConfig] = useState(null) + const { isPending: isGettingAccessMode, data: appAccessMode } = useGetAppAccessMode(appId) + const { isPending: isCheckingPermission, data: userCanAccessResult } = useGetUserCanAccessApp(appId) + // save message const [savedMessages, setSavedMessages] = useState([]) const fetchSavedMessage = async () => { @@ -538,12 +546,14 @@ const TextGeneration: FC = ({
) - if (!appId || !siteInfo || !promptConfig) { + if (!appId || !siteInfo || !promptConfig || isGettingAccessMode || isCheckingPermission) { return (
) } + if (!userCanAccessResult?.result) + return return ( <> @@ -571,7 +581,7 @@ const TextGeneration: FC = ({ />
{siteInfo.title}
- +
{!isPC && (