From c1fa47f2804df6e1f6dc99f47418b96a7bc0dd2a Mon Sep 17 00:00:00 2001 From: Gao Sun Date: Wed, 28 Jun 2023 15:51:45 +0800 Subject: [PATCH] refactor(console): redirect to current tenant when needed --- .../console/src/containers/ErrorBoundary/index.tsx | 4 ++-- packages/console/src/pages/Callback/index.tsx | 12 +++++++++++- packages/console/src/utils/url.ts | 8 ++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/packages/console/src/containers/ErrorBoundary/index.tsx b/packages/console/src/containers/ErrorBoundary/index.tsx index 81fc8bc72..45f671887 100644 --- a/packages/console/src/containers/ErrorBoundary/index.tsx +++ b/packages/console/src/containers/ErrorBoundary/index.tsx @@ -9,6 +9,7 @@ import { withTranslation } from 'react-i18next'; import AppError from '@/components/AppError'; import SessionExpired from '@/components/SessionExpired'; +import { isInCallback } from '@/utils/url'; type Props = { children: ReactNode; @@ -59,8 +60,7 @@ class ErrorBoundary extends Component { if (error) { // Different strategies for handling errors in callback pages since the callback errors // are likely unexpected and unrecoverable. - const { pathname } = window.location; - if (['/callback', '-callback'].some((path) => pathname.endsWith(path))) { + if (isInCallback()) { if (error instanceof LogtoError && error.data instanceof OidcError) { return ( { - navigate('/', { replace: true }); + /** + * The first level callback check is due to the usage of `basename` + * for tenant-specific routes, e.g., `/:tenantId/applications`. + * Once we merge all the routes into one router, we can remove this check. + */ + navigate(isInFirstLevelCallback() ? `/${getUserTenantId()}` : '/', { + replace: true, + }); }); return ; diff --git a/packages/console/src/utils/url.ts b/packages/console/src/utils/url.ts index 3f789691d..131362ea7 100644 --- a/packages/console/src/utils/url.ts +++ b/packages/console/src/utils/url.ts @@ -2,3 +2,11 @@ export const buildUrl = (path: string, searchParameters: Record) `${path}?${new URLSearchParams(searchParameters).toString()}`; export const formatSearchKeyword = (keyword: string) => `%${keyword}%`; + +/** If the current pathname is `/callback` or ends with `-callback`, we consider it as a callback page. */ +export const isInCallback = () => + ['/callback', '-callback'].some((path) => window.location.pathname.endsWith(path)); + +/** If the current pathname is a callback page and the pathname only has one level. */ +export const isInFirstLevelCallback = () => + window.location.pathname.split('/').length === 1 && isInCallback();