diff --git a/.gitignore b/.gitignore index e71b381610..66249653d7 100644 --- a/.gitignore +++ b/.gitignore @@ -139,6 +139,7 @@ web/.vscode/settings.json !.idea/icon.png .ideaDataSources/ *.iml +api/.idea api/.env api/storage/* diff --git a/web/app/(shareLayout)/chatbot/[token]/page.tsx b/web/app/(shareLayout)/chatbot/[token]/page.tsx index 1db5c7e458..6196afecc4 100644 --- a/web/app/(shareLayout)/chatbot/[token]/page.tsx +++ b/web/app/(shareLayout)/chatbot/[token]/page.tsx @@ -1,85 +1,10 @@ 'use client' -import React, { useEffect } from 'react' -import cn from 'classnames' +import React from 'react' import EmbeddedChatbot from '@/app/components/base/chat/embedded-chatbot' -import Loading from '@/app/components/base/loading' -import { fetchSystemFeatures } from '@/service/share' -import LogoSite from '@/app/components/base/logo/logo-site' const Chatbot = () => { - const [isSSOEnforced, setIsSSOEnforced] = React.useState(true) - const [loading, setLoading] = React.useState(true) - - useEffect(() => { - fetchSystemFeatures().then((res) => { - setIsSSOEnforced(res.sso_enforced_for_web) - setLoading(false) - }) - }, []) - return ( - <> - { - loading - ? ( -
-
- -
-
- ) - : ( - <> - {isSSOEnforced - ? ( -
-
-
- -
- -
-
-
-

- Warning: Chatbot is not available -

-

- Because SSO is enforced. Please contact your administrator. -

-
-
-
-
-
- ) - : - } - - )} - + ) } diff --git a/web/app/(shareLayout)/webapp-signin/page.tsx b/web/app/(shareLayout)/webapp-signin/page.tsx index ebb83884d6..4394cef822 100644 --- a/web/app/(shareLayout)/webapp-signin/page.tsx +++ b/web/app/(shareLayout)/webapp-signin/page.tsx @@ -2,150 +2,99 @@ import cn from 'classnames' import { useRouter, useSearchParams } from 'next/navigation' import type { FC } from 'react' -import React, { useEffect, useState } from 'react' -import { useTranslation } from 'react-i18next' +import React, { useEffect } from 'react' import Toast from '@/app/components/base/toast' -import Button from '@/app/components/base/button' import { fetchSystemFeatures, fetchWebOAuth2SSOUrl, fetchWebOIDCSSOUrl, fetchWebSAMLSSOUrl } from '@/service/share' -import LogoSite from '@/app/components/base/logo/logo-site' import { setAccessToken } from '@/app/components/share/utils' +import Loading from '@/app/components/base/loading' const WebSSOForm: FC = () => { const searchParams = useSearchParams() + const router = useRouter() const redirectUrl = searchParams.get('redirect_url') const tokenFromUrl = searchParams.get('web_sso_token') const message = searchParams.get('message') - const router = useRouter() - const { t } = useTranslation() + const showErrorToast = (message: string) => { + Toast.notify({ + type: 'error', + message, + }) + } - const [isLoading, setIsLoading] = useState(false) - const [protocol, setProtocol] = useState('') + const getAppCodeFromRedirectUrl = () => { + const appCode = redirectUrl?.split('/').pop() + if (!appCode) + return null - useEffect(() => { - const fetchFeaturesAndSetToken = async () => { - await fetchSystemFeatures().then((res) => { - setProtocol(res.sso_enforced_for_web_protocol) - }) + return appCode + } - // Callback from SSO, process token and redirect - if (tokenFromUrl && redirectUrl) { - const appCode = redirectUrl.split('/').pop() - if (!appCode) { - Toast.notify({ - type: 'error', - message: 'redirect url is invalid. App code is not found.', - }) - return - } + const processTokenAndRedirect = async () => { + const appCode = getAppCodeFromRedirectUrl() + if (!appCode || !tokenFromUrl || !redirectUrl) { + showErrorToast('redirect url or app code or token is invalid.') + return + } - await setAccessToken(appCode, tokenFromUrl) - router.push(redirectUrl) + await setAccessToken(appCode, tokenFromUrl) + router.push(redirectUrl) + } + + const handleSSOLogin = async (protocol: string) => { + const appCode = getAppCodeFromRedirectUrl() + if (!appCode || !redirectUrl) { + showErrorToast('redirect url or app code is invalid.') + return + } + + switch (protocol) { + case 'saml': { + const samlRes = await fetchWebSAMLSSOUrl(appCode, redirectUrl) + router.push(samlRes.url) + break } - } - - fetchFeaturesAndSetToken() - - if (message) { - Toast.notify({ - type: 'error', - message, - }) - } - }, []) - - const handleSSOLogin = () => { - setIsLoading(true) - - if (!redirectUrl) { - Toast.notify({ - type: 'error', - message: 'redirect url is not found.', - }) - setIsLoading(false) - return - } - - const appCode = redirectUrl.split('/').pop() - if (!appCode) { - Toast.notify({ - type: 'error', - message: 'redirect url is invalid. App code is not found.', - }) - return - } - - if (protocol === 'saml') { - fetchWebSAMLSSOUrl(appCode, redirectUrl).then((res) => { - router.push(res.url) - }).finally(() => { - setIsLoading(false) - }) - } - else if (protocol === 'oidc') { - fetchWebOIDCSSOUrl(appCode, redirectUrl).then((res) => { - router.push(res.url) - }).finally(() => { - setIsLoading(false) - }) - } - else if (protocol === 'oauth2') { - fetchWebOAuth2SSOUrl(appCode, redirectUrl).then((res) => { - router.push(res.url) - }).finally(() => { - setIsLoading(false) - }) - } - else { - Toast.notify({ - type: 'error', - message: 'sso protocol is not supported.', - }) - setIsLoading(false) + case 'oidc': { + const oidcRes = await fetchWebOIDCSSOUrl(appCode, redirectUrl) + router.push(oidcRes.url) + break + } + case 'oauth2': { + const oauth2Res = await fetchWebOAuth2SSOUrl(appCode, redirectUrl) + router.push(oauth2Res.url) + break + } + default: + showErrorToast('SSO protocol is not supported.') } } - return ( -
-
-
- -
+ useEffect(() => { + const init = async () => { + const res = await fetchSystemFeatures() + const protocol = res.sso_enforced_for_web_protocol -
-
-
-

{t('login.pageTitle')}

-
-
- -
-
-
+ if (message) { + showErrorToast(message) + return + } + + if (!tokenFromUrl) { + await handleSSOLogin(protocol) + return + } + + await processTokenAndRedirect() + } + + init() + }, [message, tokenFromUrl]) // Added dependencies to useEffect + + return ( +
+
+
)