@genesislcap/blank-app-seed 3.30.0-prerelease.81 → 3.30.0-prerelease.83
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.genx/package.json +1 -1
- package/.genx/versions.json +1 -1
- package/CHANGELOG.md +14 -0
- package/client-tmp/angular/angular.json +0 -3
- package/client-tmp/angular/src/app/app.component.ts +6 -12
- package/client-tmp/angular/src/app/guards/auth.guard.ts +1 -1
- package/client-tmp/angular/src/app/layouts/default/default.layout.html +0 -1
- package/client-tmp/angular/src/app/layouts/default/default.layout.ts +2 -6
- package/client-tmp/angular/src/app/services/route.service.ts +2 -2
- package/client-tmp/angular/src/app/share/foundation-auth.ts +15 -29
- package/client-tmp/angular/src/app/share/foundation-login.ts +47 -0
- package/client-tmp/react/package.json +2 -2
- package/client-tmp/react/src/App.tsx +9 -4
- package/client-tmp/react/src/config.ts +2 -2
- package/client-tmp/react/src/guards/ProtectedGuard.tsx +4 -7
- package/client-tmp/react/src/layouts/default/DefaultLayout.tsx +17 -12
- package/client-tmp/react/src/pages/AuthPage/AuthPage.tsx +7 -15
- package/client-tmp/react/src/pbc/container.tsx +2 -2
- package/client-tmp/react/src/share/foundation-login.ts +19 -28
- package/client-tmp/react/src/store/RoutesContext.tsx +2 -2
- package/client-tmp/react/src/utils/history.ts +5 -0
- package/client-tmp/react/src/utils/index.ts +2 -1
- package/client-tmp/react/webpack.config.js +2 -16
- package/client-tmp/web-components/package.json +1 -4
- package/client-tmp/web-components/src/routes/config.ts +81 -35
- package/package.json +1 -1
- package/client-tmp/angular/src/proxy.conf.json +0 -12
- package/server/{{appName}}-app/src/main/genesis/scripts/genesis-router.kts +0 -13
package/.genx/package.json
CHANGED
package/.genx/versions.json
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [3.30.0-prerelease.83](https://github.com/genesiscommunitysuccess/blank-app-seed/compare/v3.30.0-prerelease.82...v3.30.0-prerelease.83) (2025-02-06)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* revert changes from 8.9 (#430) 4133d7e, closes FUI-2196 PSD-9
|
|
9
|
+
|
|
10
|
+
## [3.30.0-prerelease.82](https://github.com/genesiscommunitysuccess/blank-app-seed/compare/v3.30.0-prerelease.81...v3.30.0-prerelease.82) (2025-02-06)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* automated dependency version update [skip-ci] [PSD-9](https://github.com/genesiscommunitysuccess/blank-app-seed/issues/9) (#429) 7f512d2
|
|
16
|
+
|
|
3
17
|
## [3.30.0-prerelease.81](https://github.com/genesiscommunitysuccess/blank-app-seed/compare/v3.30.0-prerelease.80...v3.30.0-prerelease.81) (2025-02-05)
|
|
4
18
|
|
|
5
19
|
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { AfterViewInit, Component, ElementRef, OnDestroy, OnInit } from '@angular/core';
|
|
2
2
|
import { Router, NavigationEnd } from '@angular/router';
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import getLayoutNameByRoute from './utils/getLayoutNameByRoute';
|
|
4
|
+
import type { LayoutComponentName } from './types/layout';
|
|
5
|
+
import { configureFoundationLogin } from './share/foundation-login';
|
|
6
6
|
import { registerComponents } from './share/genesis-components';
|
|
7
7
|
import { getStore } from './store';
|
|
8
|
-
import
|
|
9
|
-
import getLayoutNameByRoute from './utils/getLayoutNameByRoute';
|
|
8
|
+
import { customEventFactory, registerStylesTarget } from '../pbc/utils';
|
|
10
9
|
{{#if FDC3.channels.length}}
|
|
11
10
|
import { listenToChannel, onFDC3Ready } from './utils';
|
|
12
11
|
{{/if}}
|
|
@@ -21,17 +20,12 @@ export class AppComponent implements OnInit, OnDestroy, AfterViewInit {
|
|
|
21
20
|
title = '{{capitalCase appName}}';
|
|
22
21
|
store = getStore();
|
|
23
22
|
|
|
24
|
-
// @ts-ignore
|
|
25
|
-
@Connect connect: Connect;
|
|
26
|
-
|
|
27
23
|
constructor(
|
|
28
24
|
private el: ElementRef,
|
|
29
25
|
router: Router,
|
|
30
26
|
) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
configureFoundationLogin({ router });
|
|
28
|
+
|
|
35
29
|
// Set layout componet based on route
|
|
36
30
|
router.events.subscribe((event: any) => {
|
|
37
31
|
if (event instanceof NavigationEnd) {
|
|
@@ -9,7 +9,7 @@ export class AuthGuard extends PermissionsGuard {
|
|
|
9
9
|
override async canActivate(): Promise<boolean> {
|
|
10
10
|
if (!this.user.isAuthenticated) {
|
|
11
11
|
this.user.trackPath();
|
|
12
|
-
|
|
12
|
+
this.router.navigate([`/${AUTH_PATH}`]);
|
|
13
13
|
return false;
|
|
14
14
|
}
|
|
15
15
|
return true;
|
|
@@ -29,15 +29,11 @@ export class DefaultLayoutComponent extends BaseLayout implements AfterViewInit
|
|
|
29
29
|
configureDesignSystem(this.designSystemProviderElement.nativeElement, designTokens);
|
|
30
30
|
registerStylesTarget(this.el.nativeElement, 'layout');
|
|
31
31
|
}
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
navigateAngular = (path: string) => {
|
|
34
34
|
this.router.navigate([path]);
|
|
35
35
|
};
|
|
36
|
-
|
|
37
|
-
onLogout = () => {
|
|
38
|
-
this.router.navigate(['/login']);
|
|
39
|
-
};
|
|
40
|
-
|
|
36
|
+
|
|
41
37
|
onLuminanceToogle = (): void => {
|
|
42
38
|
baseLayerLuminance.setValueFor(
|
|
43
39
|
this.designSystemProviderElement.nativeElement,
|
|
@@ -39,7 +39,7 @@ export class RouteService {
|
|
|
39
39
|
navItems: [
|
|
40
40
|
{
|
|
41
41
|
navId: 'header',
|
|
42
|
-
title: '{{#if this.title}}{{
|
|
42
|
+
title: '{{#if this.title}}{{this.title}}{{else}}{{this.name}}{{/if}}',
|
|
43
43
|
icon: {
|
|
44
44
|
name: '{{this.icon}}',
|
|
45
45
|
variant: 'solid',
|
|
@@ -53,7 +53,7 @@ export class RouteService {
|
|
|
53
53
|
|
|
54
54
|
/**
|
|
55
55
|
* @privateRemarks
|
|
56
|
-
* The shell has access to context, so it's possible for it to return a pre-mapped framework variant of routes.
|
|
56
|
+
* The shell has access to context, so it's possible for it to return a pre-mapped framework variant of routes.
|
|
57
57
|
* In this iteration we're doing it inline, given the angular version may move and here we know the shape we need.
|
|
58
58
|
*/
|
|
59
59
|
pbcRoutes(): Routes {
|
|
@@ -1,34 +1,20 @@
|
|
|
1
|
+
// import { configure } from '@genesislcap/foundation-auth/config';
|
|
1
2
|
import type { Router } from '@angular/router';
|
|
2
|
-
import { configure, defaultAuthConfig } from '@genesislcap/foundation-auth/config';
|
|
3
|
-
import type { Connect } from '@genesislcap/foundation-comms';
|
|
4
|
-
import { getUser } from '@genesislcap/foundation-user';
|
|
5
|
-
import { GENESIS_SOCKET_URL } from '@genesislcap/foundation-utils';
|
|
6
|
-
import { AUTH_PATH } from '../app.config';
|
|
7
3
|
|
|
8
4
|
/**
|
|
9
5
|
* Configure the micro frontend
|
|
10
6
|
*/
|
|
11
|
-
export const configureFoundationAuth = ({
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
postLoginRedirect: async () => {
|
|
26
|
-
const url = GENESIS_SOCKET_URL;
|
|
27
|
-
await connectService.connect(url);
|
|
28
|
-
|
|
29
|
-
const lastPath = getUser().lastPath()?.replace(basePath, '');
|
|
30
|
-
|
|
31
|
-
router.navigate([lastPath ?? '{{kebabCase routes.[0].name}}']);
|
|
32
|
-
},
|
|
33
|
-
});
|
|
34
|
-
};
|
|
7
|
+
export const configureFoundationAuth = ({
|
|
8
|
+
router,
|
|
9
|
+
connectService,
|
|
10
|
+
}: {
|
|
11
|
+
router: Router;
|
|
12
|
+
connectService: any;
|
|
13
|
+
}) => null
|
|
14
|
+
// configure({
|
|
15
|
+
// omitRoutes: ['request-account'],
|
|
16
|
+
// postLoginRedirect: async () => {
|
|
17
|
+
// await connectService.init();
|
|
18
|
+
// router.navigate([`/${INTERNAL_URLS.homepage}`]);
|
|
19
|
+
// },
|
|
20
|
+
// });
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import {configure, define} from '@genesislcap/foundation-login';
|
|
2
|
+
import type { Router } from '@angular/router';
|
|
3
|
+
import { getUser } from '@genesislcap/foundation-user';
|
|
4
|
+
import { css, DI } from '@genesislcap/web-core';
|
|
5
|
+
import { AUTH_PATH } from '../app.config';
|
|
6
|
+
import logo from '../../assets/logo.svg';
|
|
7
|
+
|
|
8
|
+
// eslint-disable-next-line
|
|
9
|
+
declare var ENABLE_SSO: boolean;
|
|
10
|
+
|
|
11
|
+
const ssoSettings =
|
|
12
|
+
typeof ENABLE_SSO !== 'undefined' && ENABLE_SSO === true
|
|
13
|
+
? {
|
|
14
|
+
autoAuth: true,
|
|
15
|
+
sso: {
|
|
16
|
+
toggled: true,
|
|
17
|
+
identityProvidersPath: 'sso/list',
|
|
18
|
+
},
|
|
19
|
+
}
|
|
20
|
+
: {};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Configure the micro frontend
|
|
24
|
+
*/
|
|
25
|
+
export const configureFoundationLogin = ({
|
|
26
|
+
router,
|
|
27
|
+
}: {
|
|
28
|
+
router: Router;
|
|
29
|
+
}) => {
|
|
30
|
+
configure(DI.getOrCreateDOMContainer(), {
|
|
31
|
+
// autoConnect: true, // < Guard in place to ensure connection. Keeping the connect form in place for now.
|
|
32
|
+
autoAuth: true, // < Allow users to skip login
|
|
33
|
+
showConnectionIndicator: true,
|
|
34
|
+
hostPath: AUTH_PATH,
|
|
35
|
+
redirectHandler: () => {
|
|
36
|
+
router.navigate([getUser().lastPath() ?? '{{kebabCase routes.[0].name}}'])
|
|
37
|
+
},
|
|
38
|
+
...ssoSettings,
|
|
39
|
+
logo: css `
|
|
40
|
+
content: url("${logo}");
|
|
41
|
+
`,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
return define({
|
|
45
|
+
name: `client-app-login`,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"history": "^5.3.0",
|
|
59
59
|
"react": "^19.0.0",
|
|
60
60
|
"react-dom": "^19.0.0",
|
|
61
|
-
"react-router": "
|
|
61
|
+
"react-router-dom": "7.0.2",
|
|
62
62
|
"web-vitals": "^2.1.4"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"@types/css-modules": "^1.0.5",
|
|
78
78
|
"@types/jest": "^29.5.12",
|
|
79
79
|
"@types/node": "^20.14.10",
|
|
80
|
-
"@types/react": "^19.0.1",
|
|
80
|
+
"@types/react": "^19.0.1",
|
|
81
81
|
"@types/react-dom": "^19.0.2",
|
|
82
82
|
"@typescript-eslint/eslint-plugin": "^7.13.1",
|
|
83
83
|
"@typescript-eslint/parser": "^7.13.1",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useEffect, useState } from 'react';
|
|
2
|
-
import {Routes, Route, useLocation
|
|
2
|
+
import { unstable_HistoryRouter as HistoryRouter, Routes, Route, useLocation } from 'react-router-dom';
|
|
3
3
|
import {
|
|
4
|
+
history,
|
|
4
5
|
setApiHost,
|
|
5
6
|
getLayoutNameByRoute,
|
|
6
7
|
{{#if FDC3.channels.length~}}
|
|
@@ -16,6 +17,7 @@ import { AuthProvider } from './store/AuthContext';
|
|
|
16
17
|
import { RoutesProvider, useRoutesContext } from './store/RoutesContext';
|
|
17
18
|
import AuthPage from './pages/AuthPage/AuthPage';
|
|
18
19
|
import { registerComponents as genesisRegisterComponents } from './share/genesis-components';
|
|
20
|
+
import { configureFoundationLogin } from './share/foundation-login';
|
|
19
21
|
import ProtectedGuard from './guards/ProtectedGuard';
|
|
20
22
|
import { storeService } from '@/services/store.service';
|
|
21
23
|
|
|
@@ -31,8 +33,10 @@ const DynamicLayout = () => {
|
|
|
31
33
|
|
|
32
34
|
useEffect(() => {
|
|
33
35
|
handleRouteChange(location);
|
|
36
|
+
const unlisten = history.listen(handleRouteChange);
|
|
34
37
|
|
|
35
38
|
return () => {
|
|
39
|
+
unlisten();
|
|
36
40
|
}
|
|
37
41
|
}, [location]);
|
|
38
42
|
|
|
@@ -78,6 +82,7 @@ const App: React.FC<AppProps> = ({ rootElement }) => {
|
|
|
78
82
|
|
|
79
83
|
setApiHost();
|
|
80
84
|
genesisRegisterComponents();
|
|
85
|
+
configureFoundationLogin({ router: history });
|
|
81
86
|
|
|
82
87
|
useEffect(() => {
|
|
83
88
|
registerStylesTarget(document.body, 'main');
|
|
@@ -102,14 +107,14 @@ const App: React.FC<AppProps> = ({ rootElement }) => {
|
|
|
102
107
|
return (
|
|
103
108
|
<AuthProvider>
|
|
104
109
|
<RoutesProvider>
|
|
105
|
-
<
|
|
110
|
+
<HistoryRouter history={history as any}>
|
|
106
111
|
<Routes>
|
|
107
112
|
<Route path="*" element={<DynamicLayout />} />
|
|
108
113
|
</Routes>
|
|
109
|
-
</
|
|
114
|
+
</HistoryRouter>
|
|
110
115
|
</RoutesProvider>
|
|
111
116
|
</AuthProvider>
|
|
112
117
|
);
|
|
113
118
|
};
|
|
114
119
|
|
|
115
|
-
export default App;
|
|
120
|
+
export default App;
|
|
@@ -2,11 +2,11 @@ import { RouteLayouts } from './types/RouteLayouts';
|
|
|
2
2
|
import { environment } from '@environment';
|
|
3
3
|
|
|
4
4
|
export const routeLayouts: RouteLayouts = {
|
|
5
|
-
'/
|
|
5
|
+
'/auth': 'blank',
|
|
6
6
|
'/': 'blank',
|
|
7
7
|
};
|
|
8
8
|
|
|
9
|
-
export const AUTH_PATH = '
|
|
9
|
+
export const AUTH_PATH = 'auth';
|
|
10
10
|
export const NOT_PERMITTED_PATH = 'not-permitted';
|
|
11
11
|
|
|
12
12
|
export const API_DATA = {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useState, useEffect, ReactNode } from 'react';
|
|
2
|
-
import {RouteObject
|
|
2
|
+
import { RouteObject } from 'react-router';
|
|
3
|
+
import { useNavigate } from 'react-router-dom';
|
|
3
4
|
import isConnectedHelper from '@/helpers/isConnectedHelper';
|
|
4
5
|
import isAuthenticatedHelper from '@/helpers/isAuthenticatedHelper';
|
|
5
6
|
import hasPermissionHelper from '@/helpers/hasPermissionHelper';
|
|
@@ -55,15 +56,11 @@ const ProtectedGuard: React.FC<{ children: ReactNode }> = ({ children }: { child
|
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
if (permissionState) {
|
|
58
|
-
|
|
59
|
-
const basePath = baseElement?.getAttribute('href') || '';
|
|
60
|
-
|
|
61
|
-
const redirect = `${basePath}${redirectUrlByPermissionState[permissionState]}`;
|
|
62
|
-
navigate(`/${redirect}`);
|
|
59
|
+
navigate(`/${redirectUrlByPermissionState[permissionState]}`);
|
|
63
60
|
}
|
|
64
61
|
}, [routes, isConnected, isAuthenticated, hasPermission]);
|
|
65
62
|
|
|
66
63
|
return children;
|
|
67
64
|
};
|
|
68
65
|
|
|
69
|
-
export default ProtectedGuard;
|
|
66
|
+
export default ProtectedGuard;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { ReactNode, useEffect, useRef } from 'react';
|
|
2
|
-
import { RouteObject
|
|
2
|
+
import { RouteObject } from 'react-router';
|
|
3
3
|
import { configureDesignSystem, getNavItems } from '@genesislcap/foundation-ui';
|
|
4
|
+
import { useNavigate } from 'react-router-dom';
|
|
4
5
|
import {
|
|
5
6
|
baseLayerLuminance,
|
|
6
7
|
StandardLuminance,
|
|
@@ -9,9 +10,6 @@ import styles from './DefaultLayout.module.css';
|
|
|
9
10
|
import PBCElementsRenderer from '@/pbc/elementsRenderer';
|
|
10
11
|
import * as designTokens from '@/styles/design-tokens.json';
|
|
11
12
|
import { useRoutesContext } from '@/store/RoutesContext';
|
|
12
|
-
import { connectService } from '@/services/connect.service.ts';
|
|
13
|
-
import { getUser } from '@genesislcap/foundation-user';
|
|
14
|
-
import { AUTH_PATH } from '@/config';
|
|
15
13
|
|
|
16
14
|
interface DefaultLayoutProps {
|
|
17
15
|
children: ReactNode;
|
|
@@ -27,6 +25,7 @@ type ExtendedRouteObject = RouteObject & {
|
|
|
27
25
|
const DefaultLayout: React.FC<DefaultLayoutProps> = ({ children }) => {
|
|
28
26
|
const navigate = useNavigate();
|
|
29
27
|
const designSystemProviderRef = useRef<HTMLElement>(null);
|
|
28
|
+
const foundationHeaderRef = useRef<HTMLElement>(null);
|
|
30
29
|
const routes = useRoutesContext() as ExtendedRouteObject[];
|
|
31
30
|
const navItems = getNavItems(routes.flatMap((route) => ({
|
|
32
31
|
path: route.path || '',
|
|
@@ -44,18 +43,25 @@ const DefaultLayout: React.FC<DefaultLayoutProps> = ({ children }) => {
|
|
|
44
43
|
);
|
|
45
44
|
}
|
|
46
45
|
};
|
|
47
|
-
|
|
48
|
-
if (!connectService.isConnected()) {
|
|
49
|
-
getUser().trackPath();
|
|
50
|
-
navigate(`/${AUTH_PATH}`)
|
|
51
|
-
}
|
|
52
|
-
|
|
46
|
+
|
|
53
47
|
useEffect(() => {
|
|
54
48
|
if (designSystemProviderRef.current) {
|
|
55
49
|
configureDesignSystem(designSystemProviderRef.current, designTokens);
|
|
56
50
|
}
|
|
57
51
|
|
|
52
|
+
const handleLuminanceIconClicked = () => {
|
|
53
|
+
onLuminanceToggle();
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const foundationHeader = foundationHeaderRef.current;
|
|
57
|
+
if (foundationHeader) {
|
|
58
|
+
foundationHeader.addEventListener('luminance-icon-clicked', handleLuminanceIconClicked);
|
|
59
|
+
}
|
|
60
|
+
|
|
58
61
|
return () => {
|
|
62
|
+
if (foundationHeader) {
|
|
63
|
+
foundationHeader.removeEventListener('luminance-icon-clicked', handleLuminanceIconClicked);
|
|
64
|
+
}
|
|
59
65
|
};
|
|
60
66
|
}, []);
|
|
61
67
|
|
|
@@ -65,8 +71,7 @@ const DefaultLayout: React.FC<DefaultLayoutProps> = ({ children }) => {
|
|
|
65
71
|
<rapid-design-system-provider ref={designSystemProviderRef} class={className}>
|
|
66
72
|
<PBCElementsRenderer target={['layout-start']} />
|
|
67
73
|
<foundation-header
|
|
68
|
-
|
|
69
|
-
onlogout-clicked={() => navigate(`/${AUTH_PATH}`)}
|
|
74
|
+
ref={foundationHeaderRef}
|
|
70
75
|
show-luminance-toggle-button
|
|
71
76
|
show-misc-toggle-button
|
|
72
77
|
routeNavItems={navItems}
|
|
@@ -1,20 +1,12 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import './AuthPage.css';
|
|
3
|
-
import { configureFoundationLogin } from "@/share/foundation-login.ts";
|
|
4
|
-
import { useNavigate } from "react-router";
|
|
5
3
|
|
|
6
4
|
const AuthPage: React.FC = () => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
return (
|
|
14
|
-
<section className="auth-page">
|
|
15
|
-
<client-app-login></client-app-login>
|
|
16
|
-
</section>
|
|
17
|
-
);
|
|
5
|
+
return (
|
|
6
|
+
<section className="auth-page">
|
|
7
|
+
<client-app-login></client-app-login>
|
|
8
|
+
</section>
|
|
9
|
+
);
|
|
18
10
|
};
|
|
19
11
|
|
|
20
|
-
export default AuthPage;
|
|
12
|
+
export default AuthPage;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useEffect, useRef, RouteObject } from 'react';
|
|
2
2
|
import { deriveElementTag } from './utils';
|
|
3
3
|
import { useRoutesContext } from '@/store/RoutesContext';
|
|
4
|
-
import { useLocation } from 'react-router';
|
|
4
|
+
import { useLocation } from 'react-router-dom';
|
|
5
5
|
|
|
6
6
|
type ExtendedRouteObject = RouteObject & {
|
|
7
7
|
data?: {
|
|
@@ -41,4 +41,4 @@ const PBCContainer: React.FC = () => {
|
|
|
41
41
|
return <div ref={containerRef} className="container" style=\{{ width: '100%', height: '100%' }}></div>;
|
|
42
42
|
};
|
|
43
43
|
|
|
44
|
-
export default PBCContainer;
|
|
44
|
+
export default PBCContainer;
|
|
@@ -1,37 +1,28 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {configure, define} from '@genesislcap/foundation-login';
|
|
2
2
|
import { getUser } from '@genesislcap/foundation-user';
|
|
3
|
-
import { AUTH_PATH } from '@/config';
|
|
4
|
-
import { GENESIS_SOCKET_URL } from '@genesislcap/foundation-utils';
|
|
5
|
-
import { Connect } from '@genesislcap/foundation-comms';
|
|
6
3
|
import { DI } from '@genesislcap/web-core';
|
|
7
|
-
import
|
|
4
|
+
import { AUTH_PATH } from '@/config';
|
|
5
|
+
import type { Router } from '@/utils/history';
|
|
8
6
|
|
|
9
7
|
/**
|
|
10
8
|
* Configure the micro frontend
|
|
11
9
|
*/
|
|
12
|
-
export const configureFoundationLogin = ({
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
...defaultAuthConfig.fields.username,
|
|
25
|
-
},
|
|
10
|
+
export const configureFoundationLogin = ({ router }:{ router: Router }) => {
|
|
11
|
+
configure(DI.getOrCreateDOMContainer(), {
|
|
12
|
+
autoConnect: true,
|
|
13
|
+
autoAuth: true, // < Allow users to skip login
|
|
14
|
+
showConnectionIndicator: true,
|
|
15
|
+
hostPath: AUTH_PATH,
|
|
16
|
+
redirectHandler: () => {
|
|
17
|
+
// workaround for redirect from foundation-login
|
|
18
|
+
setTimeout(() => {
|
|
19
|
+
const lastPath = getUser().lastPath() ?? '/{{kebabCase routes.[0].name}}';
|
|
20
|
+
router.push(lastPath);
|
|
21
|
+
}, 0);
|
|
26
22
|
},
|
|
27
|
-
|
|
28
|
-
postLoginRedirect: async () => {
|
|
29
|
-
const url = GENESIS_SOCKET_URL;
|
|
30
|
-
await connect.connect(url);
|
|
23
|
+
});
|
|
31
24
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
})
|
|
25
|
+
return define({
|
|
26
|
+
name: `client-app-login`,
|
|
27
|
+
});
|
|
36
28
|
}
|
|
37
|
-
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { createContext, useContext, ReactNode } from 'react';
|
|
2
|
-
import { RouteObject, Navigate } from 'react-router';
|
|
2
|
+
import { RouteObject, Navigate } from 'react-router-dom';
|
|
3
3
|
import { getApp } from '@genesislcap/foundation-shell/app';
|
|
4
4
|
import AuthPage from '@/pages/AuthPage/AuthPage';
|
|
5
5
|
import NotFoundPage from '@/pages/NotFoundPage/NotFoundPage';
|
|
@@ -71,4 +71,4 @@ export const RoutesProvider: React.FC<{ children: ReactNode }> = ({ children })
|
|
|
71
71
|
|
|
72
72
|
export const useRoutesContext = () => {
|
|
73
73
|
return useContext(RoutesContext);
|
|
74
|
-
};
|
|
74
|
+
};
|
|
@@ -7,7 +7,7 @@ module.exports = (env, argv) => {
|
|
|
7
7
|
const https = process.env.HTTPS === 'true';
|
|
8
8
|
const open = !(process.env.NO_OPEN === 'true');
|
|
9
9
|
const environmentFile = mode === 'production'
|
|
10
|
-
? 'environment.prod.ts'
|
|
10
|
+
? 'environment.prod.ts'
|
|
11
11
|
: 'environment.ts';
|
|
12
12
|
const environmentPath = resolve(__dirname, 'src/environments', environmentFile);
|
|
13
13
|
|
|
@@ -76,20 +76,6 @@ module.exports = (env, argv) => {
|
|
|
76
76
|
],
|
|
77
77
|
devServer: {
|
|
78
78
|
server: https ? 'https' : 'http',
|
|
79
|
-
proxy: [
|
|
80
|
-
{
|
|
81
|
-
context: "/sm",
|
|
82
|
-
"target": "{{apiHost}}",
|
|
83
|
-
"secure": false,
|
|
84
|
-
"pathRewrite": {"^/sm": ""},
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
context: "/gwf",
|
|
88
|
-
"target": "{{apiHost}}",
|
|
89
|
-
"secure": false,
|
|
90
|
-
"ws": true
|
|
91
|
-
}
|
|
92
|
-
],
|
|
93
79
|
open,
|
|
94
80
|
static: {
|
|
95
81
|
directory: join(__dirname, 'public'),
|
|
@@ -114,4 +100,4 @@ module.exports = (env, argv) => {
|
|
|
114
100
|
modules: false,
|
|
115
101
|
},
|
|
116
102
|
};
|
|
117
|
-
};
|
|
103
|
+
};
|
|
@@ -89,7 +89,6 @@
|
|
|
89
89
|
"lint-staged": "^12.4.1"
|
|
90
90
|
},
|
|
91
91
|
"dependencies": {
|
|
92
|
-
"@genesislcap/foundation-auth": "{{versions.UI}}",
|
|
93
92
|
"@genesislcap/foundation-comms": "{{versions.UI}}",
|
|
94
93
|
"@genesislcap/foundation-entity-management": "{{versions.UI}}",
|
|
95
94
|
"@genesislcap/foundation-events": "{{versions.UI}}",
|
|
@@ -118,7 +117,6 @@
|
|
|
118
117
|
"tslib": "^2.3.1"
|
|
119
118
|
},
|
|
120
119
|
"overrides": {
|
|
121
|
-
"@genesislcap/foundation-auth": "{{versions.UI}}",
|
|
122
120
|
"@genesislcap/foundation-comms": "{{versions.UI}}",
|
|
123
121
|
"@genesislcap/foundation-entity-management": "{{versions.UI}}",
|
|
124
122
|
"@genesislcap/foundation-events": "{{versions.UI}}",
|
|
@@ -141,7 +139,6 @@
|
|
|
141
139
|
"@genesislcap/g2plot-chart": "{{versions.UI}}",
|
|
142
140
|
"@genesislcap/rapid-design-system": "{{versions.UI}}",
|
|
143
141
|
"@genesislcap/rapid-grid-pro": "{{versions.UI}}",
|
|
144
|
-
"@genesislcap/web-core": "{{versions.UI}}"
|
|
145
|
-
"typescript": "5.6.3"
|
|
142
|
+
"@genesislcap/web-core": "{{versions.UI}}"
|
|
146
143
|
}
|
|
147
144
|
}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Auth, Session } from '@genesislcap/foundation-comms';
|
|
2
|
+
import { defaultLoginConfig, LoginConfig } from '@genesislcap/foundation-login';
|
|
3
3
|
import { FoundationRouterConfiguration } from '@genesislcap/foundation-ui';
|
|
4
|
-
import {
|
|
4
|
+
import { PUBLIC_PATH } from '@genesislcap/foundation-utils';
|
|
5
|
+
import { NavigationPhase, optional, Route } from '@genesislcap/web-core';
|
|
5
6
|
import { defaultLayout, loginLayout } from '../layouts';
|
|
6
|
-
import {
|
|
7
|
-
import { defaultNotPermittedRoute, NotPermitted } from './not-permitted/not-permitted';
|
|
8
|
-
import { LoginSettings } from './types';
|
|
7
|
+
import { logger } from '../utils';
|
|
9
8
|
{{#each routes}}
|
|
10
9
|
import { {{pascalCase this.name}} } from './{{kebabCase this.name}}/{{kebabCase this.name}}';
|
|
11
10
|
{{/each}}
|
|
11
|
+
import { NotFound } from './not-found/not-found';
|
|
12
|
+
import { defaultNotPermittedRoute, NotPermitted } from './not-permitted/not-permitted';
|
|
13
|
+
import { LoginSettings } from './types';
|
|
12
14
|
|
|
13
15
|
// eslint-disable-next-line
|
|
14
16
|
declare var ENABLE_SSO: string;
|
|
@@ -27,12 +29,17 @@ const ssoSettings =
|
|
|
27
29
|
const publicPath = typeof PUBLIC_PATH !== 'undefined' ? PUBLIC_PATH : '';
|
|
28
30
|
|
|
29
31
|
export class MainRouterConfig extends FoundationRouterConfiguration<LoginSettings> {
|
|
30
|
-
|
|
32
|
+
constructor(
|
|
33
|
+
@Auth private auth: Auth,
|
|
34
|
+
@Session private session: Session,
|
|
35
|
+
@optional(LoginConfig)
|
|
36
|
+
private loginConfig: LoginConfig = { ...defaultLoginConfig, autoAuth: true, autoConnect: true },
|
|
37
|
+
) {
|
|
38
|
+
super();
|
|
39
|
+
}
|
|
31
40
|
|
|
32
41
|
async configure() {
|
|
33
42
|
this.configureAnalytics();
|
|
34
|
-
this.configureRoutePermittedChecks();
|
|
35
|
-
this.configureFallbackRouteDefinition();
|
|
36
43
|
this.title = '{{capitalCase appName}}';
|
|
37
44
|
this.defaultLayout = defaultLayout;
|
|
38
45
|
|
|
@@ -45,31 +52,22 @@ export class MainRouterConfig extends FoundationRouterConfiguration<LoginSetting
|
|
|
45
52
|
name: 'login',
|
|
46
53
|
title: 'Login',
|
|
47
54
|
element: async () => {
|
|
48
|
-
const { configure,
|
|
49
|
-
|
|
55
|
+
const { configure, define } = await import(
|
|
56
|
+
/* webpackChunkName: "foundation-login" */
|
|
57
|
+
'@genesislcap/foundation-login'
|
|
50
58
|
);
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
username: {
|
|
56
|
-
...defaultAuthConfig.fields.username,
|
|
57
|
-
pattern: '^[a-zA-Z0-9.@_:-]*$',
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
|
-
hostPath: this.loginPath,
|
|
61
|
-
postLoginRedirect: async () => {
|
|
62
|
-
await this.connect.connect(GENESIS_SOCKET_URL);
|
|
63
|
-
navigateTo(getUser().lastPath() ?? publicPath + '{{kebabCase routes.[0].name}}');
|
|
64
|
-
},
|
|
65
|
-
postLogoutRedirect: () => {
|
|
66
|
-
if (this.connect.isConnected) {
|
|
67
|
-
this.connect.disconnect();
|
|
68
|
-
}
|
|
69
|
-
defaultAuthConfig.postLogoutRedirect();
|
|
70
|
-
},
|
|
59
|
+
configure(this.container, {
|
|
60
|
+
hostPath: 'login',
|
|
61
|
+
autoConnect: true,
|
|
62
|
+
defaultRedirectUrl: publicPath + '{{kebabCase routes.[0].name}}',
|
|
71
63
|
...ssoSettings,
|
|
72
64
|
});
|
|
65
|
+
return define({
|
|
66
|
+
name: `{{rootElement}}-login`,
|
|
67
|
+
/**
|
|
68
|
+
* You can augment the template and styles here when needed.
|
|
69
|
+
*/
|
|
70
|
+
});
|
|
73
71
|
},
|
|
74
72
|
layout: loginLayout,
|
|
75
73
|
settings: { public: true },
|
|
@@ -105,22 +103,70 @@ export class MainRouterConfig extends FoundationRouterConfiguration<LoginSetting
|
|
|
105
103
|
{{/each}}
|
|
106
104
|
);
|
|
107
105
|
|
|
106
|
+
/**
|
|
107
|
+
* Example of a FallbackRouteDefinition
|
|
108
|
+
*/
|
|
109
|
+
this.routes.fallback(() =>
|
|
110
|
+
this.auth.isLoggedIn ? { redirect: 'not-found' } : { redirect: authPath },
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Example of a NavigationContributor
|
|
115
|
+
*/
|
|
108
116
|
this.contributors.push({
|
|
109
117
|
navigate: async (phase) => {
|
|
110
118
|
const settings = phase.route.settings;
|
|
111
119
|
|
|
112
120
|
/**
|
|
113
|
-
* If
|
|
121
|
+
* If public route don't block
|
|
114
122
|
*/
|
|
115
|
-
if (settings
|
|
123
|
+
if (settings && settings.public) {
|
|
116
124
|
return;
|
|
117
125
|
}
|
|
118
126
|
|
|
119
127
|
/**
|
|
120
|
-
*
|
|
128
|
+
* If logged in don't block
|
|
121
129
|
*/
|
|
122
|
-
this.
|
|
130
|
+
if (this.auth.isLoggedIn) {
|
|
131
|
+
this.redirectIfNotPermitted(settings, phase);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* If allowAutoAuth and session is valid try to connect+auto-login
|
|
137
|
+
*/
|
|
138
|
+
if (this.loginConfig.autoAuth && (await this.reAuthFromSession(settings, phase))) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Otherwise route them somewhere, like to a login
|
|
144
|
+
*/
|
|
145
|
+
phase.cancel(() => {
|
|
146
|
+
this.session.captureReturnUrl();
|
|
147
|
+
Route.name.replace(phase.router, authPath);
|
|
148
|
+
});
|
|
123
149
|
},
|
|
124
150
|
});
|
|
125
151
|
}
|
|
152
|
+
|
|
153
|
+
private async reAuthFromSession(settings: LoginSettings, phase: NavigationPhase) {
|
|
154
|
+
return this.auth.reAuthFromSession().then((authenticated) => {
|
|
155
|
+
logger.info(`reAuthFromSession. authenticated: ${authenticated}`);
|
|
156
|
+
if (authenticated) {
|
|
157
|
+
this.redirectIfNotPermitted(settings, phase);
|
|
158
|
+
}
|
|
159
|
+
return authenticated;
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private redirectIfNotPermitted(settings: LoginSettings, phase: NavigationPhase) {
|
|
164
|
+
const { path } = phase.route.endpoint;
|
|
165
|
+
if (settings?.isPermitted && !settings.isPermitted()) {
|
|
166
|
+
logger.warn(`Not permitted - Redirecting URL from ${path} to ${defaultNotPermittedRoute}.`);
|
|
167
|
+
phase.cancel(() => {
|
|
168
|
+
Route.name.replace(phase.router, defaultNotPermittedRoute);
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
126
172
|
}
|
package/package.json
CHANGED