2022-09-17 00:35:10 -05:00
|
|
|
import { UserScope } from '@logto/core-kit';
|
2024-03-26 03:15:56 -05:00
|
|
|
import { LogtoProvider, Prompt, useLogto } from '@logto/react';
|
2023-12-18 00:07:30 -05:00
|
|
|
import {
|
|
|
|
adminConsoleApplicationId,
|
|
|
|
defaultTenantId,
|
|
|
|
PredefinedScope,
|
|
|
|
TenantScope,
|
|
|
|
} from '@logto/schemas';
|
|
|
|
import { conditionalArray } from '@silverhand/essentials';
|
2023-04-27 05:34:38 -05:00
|
|
|
import { useContext, useMemo } from 'react';
|
2023-03-28 12:51:14 -05:00
|
|
|
import { Helmet } from 'react-helmet';
|
2023-07-21 01:12:01 -05:00
|
|
|
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
|
2022-06-07 08:33:53 -05:00
|
|
|
|
2023-06-10 03:21:12 -05:00
|
|
|
import 'overlayscrollbars/overlayscrollbars.css';
|
2022-02-27 21:35:14 -05:00
|
|
|
import './scss/normalized.scss';
|
2023-01-30 22:47:30 -05:00
|
|
|
import './scss/overlayscrollbars.scss';
|
2022-05-14 07:51:55 -05:00
|
|
|
// eslint-disable-next-line import/no-unassigned-import
|
|
|
|
import '@fontsource/roboto-mono';
|
2023-03-01 10:46:30 -05:00
|
|
|
|
2023-07-21 01:12:01 -05:00
|
|
|
import CloudAppRoutes from '@/cloud/AppRoutes';
|
|
|
|
import AppLoading from '@/components/AppLoading';
|
|
|
|
import { isCloud } from '@/consts/env';
|
2023-02-28 03:04:12 -05:00
|
|
|
import { cloudApi, getManagementApi, meApi } from '@/consts/resources';
|
2024-03-05 01:39:37 -05:00
|
|
|
import { ConsoleRoutes } from '@/containers/ConsoleRoutes';
|
2022-03-03 02:44:42 -05:00
|
|
|
|
2024-03-04 22:41:39 -05:00
|
|
|
import { GlobalScripts } from './components/Conversion';
|
2023-03-28 12:51:14 -05:00
|
|
|
import { adminTenantEndpoint, mainTitle } from './consts';
|
2023-03-01 23:11:08 -05:00
|
|
|
import ErrorBoundary from './containers/ErrorBoundary';
|
2023-06-26 22:31:03 -05:00
|
|
|
import LogtoErrorBoundary from './containers/LogtoErrorBoundary';
|
2023-03-01 05:24:39 -05:00
|
|
|
import AppConfirmModalProvider from './contexts/AppConfirmModalProvider';
|
2023-07-21 01:12:01 -05:00
|
|
|
import AppDataProvider, { AppDataContext } from './contexts/AppDataProvider';
|
2023-03-19 11:15:00 -05:00
|
|
|
import { AppThemeProvider } from './contexts/AppThemeProvider';
|
2023-02-28 03:04:12 -05:00
|
|
|
import TenantsProvider, { TenantsContext } from './contexts/TenantsProvider';
|
2024-06-02 23:54:42 -05:00
|
|
|
import Toast from './ds-components/Toast';
|
2024-01-03 22:16:11 -05:00
|
|
|
import useCurrentUser from './hooks/use-current-user';
|
2023-06-24 04:23:41 -05:00
|
|
|
import initI18n from './i18n/init';
|
2022-09-17 00:35:10 -05:00
|
|
|
|
2022-02-28 09:18:01 -05:00
|
|
|
void initI18n();
|
2022-02-16 02:04:34 -05:00
|
|
|
|
2023-07-21 01:12:01 -05:00
|
|
|
/**
|
|
|
|
* The main entry of the project. It provides two fundamental context providers:
|
|
|
|
*
|
|
|
|
* - `RouterProvider`: the sole router provider of the project.
|
|
|
|
* - `TenantsProvider`: manages the tenants data, requires the `RouterProvider` to
|
|
|
|
* get the current tenant ID from the URL.
|
|
|
|
*/
|
|
|
|
function App() {
|
|
|
|
const router = createBrowserRouter([
|
|
|
|
{
|
|
|
|
path: '*',
|
|
|
|
element: (
|
|
|
|
<TenantsProvider>
|
|
|
|
<Providers />
|
|
|
|
</TenantsProvider>
|
|
|
|
),
|
|
|
|
},
|
|
|
|
]);
|
|
|
|
|
|
|
|
return <RouterProvider router={router} />;
|
|
|
|
}
|
|
|
|
|
|
|
|
export default App;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This component serves as a container for all the providers and boundary components.
|
|
|
|
*
|
|
|
|
* Since `TenantsContext` requires the `TenantsProvider` to be mounted, and the initialization
|
|
|
|
* of `LogtoProvider` requires the `TenantsContext` to be available, we have to put them into
|
|
|
|
* different components.
|
|
|
|
*/
|
|
|
|
function Providers() {
|
2023-12-18 00:07:30 -05:00
|
|
|
const { currentTenantId } = useContext(TenantsContext);
|
2023-02-10 00:06:52 -05:00
|
|
|
|
2023-12-18 00:07:30 -05:00
|
|
|
// For Cloud, we use Management API proxy for accessing tenant data.
|
|
|
|
// For OSS, we directly call the tenant API with the default tenant API resource.
|
2023-04-24 08:00:53 -05:00
|
|
|
const resources = useMemo(
|
|
|
|
() =>
|
2023-12-18 00:07:30 -05:00
|
|
|
isCloud
|
|
|
|
? [cloudApi.indicator, meApi.indicator]
|
|
|
|
: [getManagementApi(defaultTenantId).indicator, meApi.indicator],
|
|
|
|
[]
|
2023-03-04 01:52:02 -05:00
|
|
|
);
|
2023-03-09 20:57:30 -05:00
|
|
|
|
2023-04-24 08:00:53 -05:00
|
|
|
const scopes = useMemo(
|
|
|
|
() => [
|
|
|
|
UserScope.Email,
|
|
|
|
UserScope.Identities,
|
|
|
|
UserScope.CustomData,
|
2023-11-06 23:33:53 -05:00
|
|
|
UserScope.Organizations,
|
2024-06-02 23:54:42 -05:00
|
|
|
UserScope.OrganizationRoles,
|
2023-04-24 08:00:53 -05:00
|
|
|
PredefinedScope.All,
|
|
|
|
...conditionalArray(
|
2023-12-18 00:07:30 -05:00
|
|
|
isCloud && [
|
|
|
|
...Object.values(TenantScope),
|
|
|
|
cloudApi.scopes.CreateTenant,
|
|
|
|
cloudApi.scopes.ManageTenantSelf,
|
|
|
|
]
|
2023-04-24 08:00:53 -05:00
|
|
|
),
|
|
|
|
],
|
|
|
|
[]
|
|
|
|
);
|
2022-05-05 05:42:10 -05:00
|
|
|
|
2022-02-27 21:35:14 -05:00
|
|
|
return (
|
2023-02-28 03:04:12 -05:00
|
|
|
<LogtoProvider
|
2023-06-20 19:35:45 -05:00
|
|
|
unstable_enableCache
|
2023-02-28 03:04:12 -05:00
|
|
|
config={{
|
2023-03-06 23:38:26 -05:00
|
|
|
endpoint: adminTenantEndpoint.href,
|
2023-02-28 03:04:12 -05:00
|
|
|
appId: adminConsoleApplicationId,
|
|
|
|
resources,
|
|
|
|
scopes,
|
2024-03-26 03:15:56 -05:00
|
|
|
prompt: [Prompt.Login, Prompt.Consent],
|
2023-02-28 03:04:12 -05:00
|
|
|
}}
|
|
|
|
>
|
2023-03-19 11:15:00 -05:00
|
|
|
<AppThemeProvider>
|
2024-04-17 08:38:30 -05:00
|
|
|
<Helmet titleTemplate={`%s - ${mainTitle}`} defaultTitle={mainTitle} />
|
2024-06-02 23:54:42 -05:00
|
|
|
<Toast />
|
2024-04-17 08:38:30 -05:00
|
|
|
<ErrorBoundary>
|
|
|
|
<LogtoErrorBoundary>
|
|
|
|
{/**
|
|
|
|
* If it's not Cloud (OSS), render the tenant app container directly since only default tenant is available;
|
|
|
|
* if it's Cloud, render the tenant app container only when a tenant ID is available (in a tenant context).
|
|
|
|
*/}
|
|
|
|
{!isCloud || currentTenantId ? (
|
|
|
|
<AppDataProvider>
|
|
|
|
<AppConfirmModalProvider>
|
|
|
|
<AppRoutes />
|
|
|
|
</AppConfirmModalProvider>
|
|
|
|
</AppDataProvider>
|
|
|
|
) : (
|
|
|
|
<CloudAppRoutes />
|
|
|
|
)}
|
|
|
|
</LogtoErrorBoundary>
|
|
|
|
</ErrorBoundary>
|
2023-03-19 11:15:00 -05:00
|
|
|
</AppThemeProvider>
|
2023-02-28 03:04:12 -05:00
|
|
|
</LogtoProvider>
|
2022-02-27 21:35:14 -05:00
|
|
|
);
|
2023-03-22 03:45:10 -05:00
|
|
|
}
|
2022-03-03 02:02:30 -05:00
|
|
|
|
2023-07-21 01:12:01 -05:00
|
|
|
/** Renders different routes based on the user's onboarding status. */
|
|
|
|
function AppRoutes() {
|
2023-07-25 06:06:34 -05:00
|
|
|
const { tenantEndpoint } = useContext(AppDataContext);
|
2024-01-03 22:16:11 -05:00
|
|
|
const { isLoaded } = useCurrentUser();
|
2023-07-21 01:12:01 -05:00
|
|
|
const { isAuthenticated } = useLogto();
|
2023-03-09 20:57:30 -05:00
|
|
|
|
2023-07-21 01:12:01 -05:00
|
|
|
// Authenticated user should load onboarding data before rendering the app.
|
|
|
|
// This looks weird and it will be refactored soon by merging the onboarding
|
|
|
|
// routes with the console routes.
|
2023-07-25 06:06:34 -05:00
|
|
|
if (!tenantEndpoint || (isCloud && isAuthenticated && !isLoaded)) {
|
2023-07-21 01:12:01 -05:00
|
|
|
return <AppLoading />;
|
|
|
|
}
|
|
|
|
|
2024-03-04 22:41:39 -05:00
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<GlobalScripts />
|
2024-05-28 03:09:08 -05:00
|
|
|
<ConsoleRoutes />
|
2024-03-04 22:41:39 -05:00
|
|
|
</>
|
|
|
|
);
|
2023-07-21 01:12:01 -05:00
|
|
|
}
|