mirror of
https://github.com/logto-io/logto.git
synced 2025-01-06 20:40:08 -05:00
fix(console): adapt callback and current tenant id logic (#4206)
* fix(console): adapt callback and current tenant id logic * fix(console): fix cache and onboarding route * fix(console): fix cache and onboarding route
This commit is contained in:
parent
437be82a27
commit
f8e11b1b34
6 changed files with 45 additions and 15 deletions
|
@ -1,6 +1,7 @@
|
||||||
import { Route, Routes } from 'react-router-dom';
|
import { Route, Routes } from 'react-router-dom';
|
||||||
|
|
||||||
import ProtectedRoutes from '@/containers/ProtectedRoutes';
|
import ProtectedRoutes from '@/containers/ProtectedRoutes';
|
||||||
|
import { GlobalAnonymousRoute } from '@/contexts/TenantsProvider';
|
||||||
import Callback from '@/pages/Callback';
|
import Callback from '@/pages/Callback';
|
||||||
|
|
||||||
import * as styles from './AppRoutes.module.scss';
|
import * as styles from './AppRoutes.module.scss';
|
||||||
|
@ -12,11 +13,10 @@ function AppRoutes() {
|
||||||
return (
|
return (
|
||||||
<div className={styles.app}>
|
<div className={styles.app}>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/callback" element={<Callback />} />
|
<Route path={GlobalAnonymousRoute.Callback} element={<Callback />} />
|
||||||
<Route path="/social-demo-callback" element={<SocialDemoCallback />} />
|
<Route path={GlobalAnonymousRoute.SocialDemoCallback} element={<SocialDemoCallback />} />
|
||||||
<Route path="/:tenantId/callback" element={<Callback />} />
|
|
||||||
<Route element={<ProtectedRoutes />}>
|
<Route element={<ProtectedRoutes />}>
|
||||||
<Route path="*" element={<Main />} />
|
<Route index element={<Main />} />
|
||||||
</Route>
|
</Route>
|
||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -59,7 +59,7 @@ export default function TenantAccess() {
|
||||||
* We need to exclude the `me` key because it's not tenant-aware. If don't, we
|
* We need to exclude the `me` key because it's not tenant-aware. If don't, we
|
||||||
* need to manually revalidate the `me` key to make console work again.
|
* need to manually revalidate the `me` key to make console work again.
|
||||||
*/
|
*/
|
||||||
void mutate((key) => key !== 'me', undefined, false);
|
void mutate((key) => key !== 'me', undefined, { rollbackOnError: false, throwOnError: false });
|
||||||
}, [mutate, currentTenantId]);
|
}, [mutate, currentTenantId]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -7,6 +7,23 @@ import { useMatch, useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
import { isCloud } from '@/consts/env';
|
import { isCloud } from '@/consts/env';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The routes don't start with a tenant ID.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* It's important to keep this single source of truth for all anonymous routes
|
||||||
|
* because we need to check if the current route is anonymous or not to decide
|
||||||
|
* if the current tenant ID is available.
|
||||||
|
*
|
||||||
|
* This should be more clear once we refactor the file structure and the routes.
|
||||||
|
*/
|
||||||
|
export enum GlobalAnonymousRoute {
|
||||||
|
Callback = '/callback',
|
||||||
|
SocialDemoCallback = '/social-demo-callback',
|
||||||
|
}
|
||||||
|
|
||||||
|
const anonymousRoutes: Readonly<string[]> = Object.freeze(Object.values(GlobalAnonymousRoute));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current tenant status of access validation. When it's `validated`, it indicates that a
|
* The current tenant status of access validation. When it's `validated`, it indicates that a
|
||||||
* valid Access Token for the current tenant is available.
|
* valid Access Token for the current tenant is available.
|
||||||
|
@ -83,12 +100,19 @@ function TenantsProvider({ children }: Props) {
|
||||||
const [tenants, setTenants] = useState(initialTenants);
|
const [tenants, setTenants] = useState(initialTenants);
|
||||||
/** @see {@link initialTenants} */
|
/** @see {@link initialTenants} */
|
||||||
const [isInitComplete, setIsInitComplete] = useState(!isCloud);
|
const [isInitComplete, setIsInitComplete] = useState(!isCloud);
|
||||||
const matched = useMatch('/:tenantId/*');
|
const match = useMatch('/:tenantId/*');
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const currentTenantId = useMemo(
|
const currentTenantId = useMemo(() => {
|
||||||
() => (isCloud ? matched?.params.tenantId ?? '' : defaultTenantId),
|
if (!isCloud) {
|
||||||
[matched]
|
return defaultTenantId;
|
||||||
);
|
}
|
||||||
|
|
||||||
|
if (!match || anonymousRoutes.includes(match.pathname)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return match.params.tenantId ?? '';
|
||||||
|
}, [match]);
|
||||||
const [currentTenantStatus, setCurrentTenantStatus] = useState<CurrentTenantStatus>('pending');
|
const [currentTenantStatus, setCurrentTenantStatus] = useState<CurrentTenantStatus>('pending');
|
||||||
|
|
||||||
const navigateTenant = useCallback(
|
const navigateTenant = useCallback(
|
||||||
|
|
|
@ -23,9 +23,8 @@ function Congrats() {
|
||||||
const { update } = useUserOnboardingData();
|
const { update } = useUserOnboardingData();
|
||||||
const { navigateTenant, currentTenantId } = useContext(TenantsContext);
|
const { navigateTenant, currentTenantId } = useContext(TenantsContext);
|
||||||
|
|
||||||
const enterAdminConsole = () => {
|
const enterAdminConsole = async () => {
|
||||||
void update({ isOnboardingDone: true });
|
await update({ isOnboardingDone: true });
|
||||||
// Note: navigate to the admin console page directly instead of using the router
|
|
||||||
navigateTenant(currentTenantId);
|
navigateTenant(currentTenantId);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ function Callback() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
navigate(getTo('/'), { replace: true });
|
navigate('/', { replace: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
return <AppLoading />;
|
return <AppLoading />;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { Component, GeneralEvent } from '@logto/app-insights/custom-event';
|
import { Component, GeneralEvent } from '@logto/app-insights/custom-event';
|
||||||
import { TrackOnce } from '@logto/app-insights/react';
|
import { TrackOnce } from '@logto/app-insights/react';
|
||||||
import { Outlet, Route, Routes } from 'react-router-dom';
|
import { ossConsolePath } from '@logto/schemas';
|
||||||
|
import { Navigate, Outlet, Route, Routes } from 'react-router-dom';
|
||||||
import { SWRConfig } from 'swr';
|
import { SWRConfig } from 'swr';
|
||||||
|
|
||||||
import { isCloud, isProduction } from '@/consts/env';
|
import { isCloud, isProduction } from '@/consts/env';
|
||||||
|
@ -35,6 +36,12 @@ function Layout() {
|
||||||
export function ConsoleRoutes() {
|
export function ConsoleRoutes() {
|
||||||
return (
|
return (
|
||||||
<Routes>
|
<Routes>
|
||||||
|
{/**
|
||||||
|
* OSS doesn't have a tenant concept nor root path handling component, but it may
|
||||||
|
* navigate to the root path in frontend. In this case, we redirect it to the OSS
|
||||||
|
* console path to trigger the console routes.
|
||||||
|
*/}
|
||||||
|
{!isCloud && <Route path="/" element={<Navigate to={ossConsolePath} />} />}
|
||||||
<Route path="/:tenantId" element={<Layout />}>
|
<Route path="/:tenantId" element={<Layout />}>
|
||||||
<Route path="callback" element={<Callback />} />
|
<Route path="callback" element={<Callback />} />
|
||||||
<Route path="welcome" element={<Welcome />} />
|
<Route path="welcome" element={<Welcome />} />
|
||||||
|
|
Loading…
Reference in a new issue