@gridsuite/commons-ui 0.61.1 → 0.62.0

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/README.md CHANGED
@@ -33,13 +33,12 @@ you need to follow the steps below:
33
33
  - Update to the new version in [package.json](https://github.com/gridsuite/commons-ui/blob/main/package.json) (example `0.6.0`)
34
34
  - Build it: `npm install`
35
35
  - Commit the package.json and package-lock.json files, push to a branch, make a PR, have it reviewed and merged to main.
36
- - Pull and checkout main on your last commit.
37
- - [Tag your last commit](https://semver.org/) : `git tag <tag>` (example: `v0.6.0`)
38
- - Push tag : `git push origin <tag>`
39
- - Checkout the tag in a fresh repo copy : `cd $(mktemp -d) && git clone https://github.com/gridsuite/commons-ui.git` then `cd commons-ui && git checkout <tag>`
40
- - [Test your package](https://docs.npmjs.com/creating-and-publishing-scoped-public-packages#testing-your-package): `npm install`
41
- - [Login on the command line to the npm registry](https://docs.npmjs.com/logging-in-to-an-npm-enterprise-registry-from-the-command-line): `npm login`
42
- - [Publish the package](https://docs.npmjs.com/creating-and-publishing-scoped-public-packages#publishing-scoped-public-packages): `npm publish`
36
+ - [Make a release](https://github.com/gridsuite/commons-ui/releases/new) on GitHub by creating a new tag on the last commit. On the release creation page:
37
+ - In "Choose a tag": type the tag you want to create (ex.: v0.6.0) and select "create new tag"
38
+ - In "Target": click on "recent commit" tab and select your release commit
39
+ - Click on "Generate release note"
40
+ - Click on "Publish release"
41
+ - It will trigger a job that will publish the release on NPM
43
42
 
44
43
  #### License Headers and dependencies checking
45
44
 
@@ -1,5 +1,5 @@
1
1
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
- import { useState, useEffect, useMemo, useCallback } from "react";
2
+ import { useState, useEffect, useCallback } from "react";
3
3
  import { useTheme, Dialog, useMediaQuery, DialogTitle, Collapse, Alert, Box, Fade, CircularProgress, Typography, DialogContent, Accordion, AccordionSummary, AccordionDetails, Grid, DialogActions, Button, Tooltip, Zoom, Stack, tooltipClasses } from "@mui/material";
4
4
  import { LoadingButton } from "@mui/lab";
5
5
  import { Refresh, ExpandMore, Gavel, Apps, WidgetsOutlined, DnsOutlined, QuestionMark } from "@mui/icons-material";
@@ -115,18 +115,15 @@ const AboutDialog = ({
115
115
  }, [open, globalVersionPromise]);
116
116
  const [loadingAdditionalModules, setLoadingAdditionalModules] = useState(false);
117
117
  const [modules, setModules] = useState(null);
118
- const currentApp = useMemo(
119
- () => ({
120
- name: !!logo && appName || `Grid${appName}`,
121
- type: "app",
122
- version: appVersion,
123
- gitTag: appGitTag,
124
- license: appLicense
125
- }),
126
- [logo, appName, appVersion, appGitTag, appLicense]
127
- );
128
118
  useEffect(() => {
129
119
  if (open) {
120
+ const currentApp = {
121
+ name: `Grid${appName}`,
122
+ type: "app",
123
+ version: appVersion,
124
+ gitTag: appGitTag,
125
+ license: appLicense
126
+ };
130
127
  (additionalModulesPromise ? Promise.resolve(setLoadingAdditionalModules(true)).then(
131
128
  () => additionalModulesPromise()
132
129
  ) : Promise.reject(new Error("no getter"))).then(
@@ -136,7 +133,14 @@ const AboutDialog = ({
136
133
  setModules([currentApp, ...values]);
137
134
  }).finally(() => setLoadingAdditionalModules(false));
138
135
  }
139
- }, [open, additionalModulesPromise, currentApp]);
136
+ }, [
137
+ open,
138
+ additionalModulesPromise,
139
+ appName,
140
+ appVersion,
141
+ appGitTag,
142
+ appLicense
143
+ ]);
140
144
  const handleClose = useCallback(() => {
141
145
  if (onClose) {
142
146
  onClose();
package/dist/index.d.ts CHANGED
@@ -35,6 +35,7 @@ export { ElementType } from './utils/ElementType';
35
35
  export type { ElementAttributes, Option, Equipment } from './utils/types';
36
36
  export { EQUIPMENT_TYPE, EquipmentType, getEquipmentsInfosForSearchBar, equipmentStyles, } from './utils/EquipmentType';
37
37
  export { initializeAuthenticationDev, initializeAuthenticationProd, logout, dispatchUser, getPreLoginPath, } from './utils/AuthService';
38
+ export type * from './utils/AuthService';
38
39
  export { getFileIcon } from './utils/ElementIcon';
39
40
  export { DEFAULT_CELL_PADDING, DEFAULT_HEADER_HEIGHT, DEFAULT_ROW_HEIGHT, } from './components/MuiVirtualizedTable/MuiVirtualizedTable';
40
41
  export { DARK_THEME, LIGHT_THEME, LANG_SYSTEM, LANG_ENGLISH, LANG_FRENCH, } from './components/TopBar/TopBar';
@@ -3,18 +3,27 @@ import { Dispatch } from 'react';
3
3
  import { User, UserManager } from 'oidc-client';
4
4
 
5
5
  type UserValidationFunc = (user: User) => Promise<boolean>;
6
+ type IdpSettingsGetter = () => Promise<IdpSettings>;
7
+ export type IdpSettings = {
8
+ authority: string;
9
+ client_id: string;
10
+ redirect_uri: string;
11
+ post_logout_redirect_uri: string;
12
+ silent_redirect_uri: string;
13
+ scope: string;
14
+ maxExpiresIn?: number;
15
+ };
6
16
  type CustomUserManager = UserManager & {
7
- authorizationCodeFlowEnabled?: boolean;
8
17
  idpSettings?: {
9
18
  maxExpiresIn?: number;
10
19
  };
11
20
  };
12
- declare function initializeAuthenticationDev(dispatch: Dispatch<unknown>, isSilentRenew: boolean, validateUser: UserValidationFunc, isSigninCallback: boolean): Promise<UserManager>;
13
- declare function initializeAuthenticationProd(dispatch: Dispatch<unknown>, isSilentRenew: boolean, idpSettings: Promise<Response>, validateUser: UserValidationFunc, authorizationCodeFlowEnabled: boolean, isSigninCallback: boolean): Promise<CustomUserManager>;
14
- declare function login(location: Location, userManagerInstance: UserManager): Promise<void>;
15
- declare function logout(dispatch: Dispatch<unknown>, userManagerInstance: UserManager): Promise<void | undefined>;
16
- declare function dispatchUser(dispatch: Dispatch<unknown>, userManagerInstance: CustomUserManager, validateUser: UserValidationFunc): Promise<void | undefined>;
17
- declare function getPreLoginPath(): string | null;
18
- declare function handleSigninCallback(dispatch: Dispatch<unknown>, navigate: NavigateFunction, userManagerInstance: UserManager): void;
19
- declare function handleSilentRenewCallback(userManagerInstance: UserManager): void;
20
- export { initializeAuthenticationDev, initializeAuthenticationProd, handleSilentRenewCallback, login, logout, dispatchUser, handleSigninCallback, getPreLoginPath, };
21
+ export declare function initializeAuthenticationDev(dispatch: Dispatch<unknown>, isSilentRenew: boolean, validateUser: UserValidationFunc, isSigninCallback: boolean): Promise<UserManager>;
22
+ export declare function initializeAuthenticationProd(dispatch: Dispatch<unknown>, isSilentRenew: boolean, idpSettingsGetter: IdpSettingsGetter, validateUser: UserValidationFunc, isSigninCallback: boolean): Promise<CustomUserManager>;
23
+ export declare function login(location: Location, userManagerInstance: UserManager): Promise<void>;
24
+ export declare function logout(dispatch: Dispatch<unknown>, userManagerInstance: UserManager): Promise<void | undefined>;
25
+ export declare function dispatchUser(dispatch: Dispatch<unknown>, userManagerInstance: CustomUserManager, validateUser: UserValidationFunc): Promise<void | undefined>;
26
+ export declare function getPreLoginPath(): string | null;
27
+ export declare function handleSigninCallback(dispatch: Dispatch<unknown>, navigate: NavigateFunction, userManagerInstance: UserManager): void;
28
+ export declare function handleSilentRenewCallback(userManagerInstance: UserManager): void;
29
+ export {};
@@ -6,7 +6,7 @@ window.OIDCLog = Log;
6
6
  const hackAuthorityKey = "oidc.hack.authority";
7
7
  const oidcHackReloadedKey = "gridsuite-oidc-hack-reloaded";
8
8
  const pathKey = "powsybl-gridsuite-current-path";
9
- function isIssuerErrorForCodeFlow(error) {
9
+ function isIssuerError(error) {
10
10
  return error.message.includes("Invalid issuer in token");
11
11
  }
12
12
  function extractIssuerToSessionStorage(error) {
@@ -33,19 +33,15 @@ function handleSigninSilent(dispatch, userManager) {
33
33
  if (user == null || getIdTokenExpiresIn(user) < 0) {
34
34
  return userManager.signinSilent().catch((error) => {
35
35
  dispatch(setShowAuthenticationRouterLogin(true));
36
- const errorIssuerCodeFlow = isIssuerErrorForCodeFlow(error);
37
- const errorIssuerImplicitFlow = error.message === "authority mismatch on settings vs. signin state";
38
- if (errorIssuerCodeFlow) {
36
+ if (isIssuerError(error)) {
39
37
  extractIssuerToSessionStorage(error);
40
- }
41
- if (errorIssuerCodeFlow || errorIssuerImplicitFlow) {
42
38
  reload();
43
39
  }
44
40
  });
45
41
  }
46
42
  });
47
43
  }
48
- function initializeAuthenticationDev(dispatch, isSilentRenew, validateUser, isSigninCallback) {
44
+ async function initializeAuthenticationDev(dispatch, isSilentRenew, validateUser, isSigninCallback) {
49
45
  let userManager = new UserManagerMock(
50
46
  {}
51
47
  );
@@ -55,76 +51,25 @@ function initializeAuthenticationDev(dispatch, isSilentRenew, validateUser, isSi
55
51
  handleSigninSilent(dispatch, userManager);
56
52
  }
57
53
  }
58
- return Promise.resolve(userManager);
54
+ return userManager;
59
55
  }
60
56
  const accessTokenExpiringNotificationTime = 60;
61
- function initializeAuthenticationProd(dispatch, isSilentRenew, idpSettings, validateUser, authorizationCodeFlowEnabled, isSigninCallback) {
62
- return idpSettings.then((r) => r.json()).then((idpSettings2) => {
63
- const regextoken = /id_token=[^&]*/;
64
- const regexstate = /state=[^&]*/;
65
- const regexexpires = /expires_in=[^&]*/;
66
- let authority;
67
- if (window.location.hash) {
68
- const matched_id_token = window.location.hash.match(regextoken);
69
- const matched_state = window.location.hash.match(regexstate);
70
- if (matched_id_token != null && matched_state != null) {
71
- const id_token = matched_id_token[0].split("=")[1];
72
- const state = matched_state[0].split("=")[1];
73
- const strState = localStorage.getItem("oidc." + state);
74
- if (strState != null) {
75
- const decoded = jwtDecode(id_token);
76
- authority = decoded.iss;
77
- const storedState = JSON.parse(strState);
78
- console.debug(
79
- "Replacing authority in storedState. Before: ",
80
- storedState.authority,
81
- "after: ",
82
- authority
83
- );
84
- storedState.authority = authority;
85
- localStorage.setItem(
86
- "oidc." + state,
87
- JSON.stringify(storedState)
88
- );
89
- if (authority !== void 0) {
90
- sessionStorage.setItem(hackAuthorityKey, authority);
91
- }
92
- const matched_expires = window.location.hash.match(regexexpires);
93
- if (matched_expires != null) {
94
- const expires_in = parseInt(
95
- matched_expires[0].split("=")[1]
96
- );
97
- window.location.hash = window.location.hash.replace(
98
- matched_expires[0],
99
- "expires_in=" + computeMinExpiresIn(
100
- expires_in,
101
- id_token,
102
- idpSettings2.maxExpiresIn
103
- )
104
- );
105
- }
106
- }
107
- }
108
- }
109
- authority = authority || sessionStorage.getItem(hackAuthorityKey) || idpSettings2.authority;
110
- const responseSettings = authorizationCodeFlowEnabled ? { response_type: "code" } : {
111
- response_type: "id_token token",
112
- response_mode: "fragment"
113
- };
57
+ async function initializeAuthenticationProd(dispatch, isSilentRenew, idpSettingsGetter, validateUser, isSigninCallback) {
58
+ const idpSettings = await idpSettingsGetter();
59
+ try {
114
60
  const settings = {
115
- authority,
116
- client_id: idpSettings2.client_id,
117
- redirect_uri: idpSettings2.redirect_uri,
118
- post_logout_redirect_uri: idpSettings2.post_logout_redirect_uri,
119
- silent_redirect_uri: idpSettings2.silent_redirect_uri,
120
- scope: idpSettings2.scope,
61
+ authority: sessionStorage.getItem(hackAuthorityKey) || idpSettings.authority,
62
+ client_id: idpSettings.client_id,
63
+ redirect_uri: idpSettings.redirect_uri,
64
+ post_logout_redirect_uri: idpSettings.post_logout_redirect_uri,
65
+ silent_redirect_uri: idpSettings.silent_redirect_uri,
66
+ scope: idpSettings.scope,
121
67
  automaticSilentRenew: !isSilentRenew,
122
68
  accessTokenExpiringNotificationTime,
123
- ...responseSettings
69
+ response_type: "code"
124
70
  };
125
71
  let userManager = new UserManager(settings);
126
- userManager.idpSettings = idpSettings2;
127
- userManager.authorizationCodeFlowEnabled = authorizationCodeFlowEnabled;
72
+ userManager.idpSettings = idpSettings;
128
73
  if (!isSilentRenew) {
129
74
  handleUser(dispatch, userManager, validateUser);
130
75
  if (!isSigninCallback) {
@@ -132,11 +77,11 @@ function initializeAuthenticationProd(dispatch, isSilentRenew, idpSettings, vali
132
77
  }
133
78
  }
134
79
  return userManager;
135
- }).catch((error) => {
80
+ } catch (error) {
136
81
  console.debug("error when importing the idp settings", error);
137
82
  dispatch(setShowAuthenticationRouterLogin(true));
138
83
  throw error;
139
- });
84
+ }
140
85
  }
141
86
  function computeMinExpiresIn(expiresIn, idToken, maxExpiresIn) {
142
87
  const now = Date.now() / 1e3;
@@ -171,6 +116,7 @@ function login(location, userManagerInstance) {
171
116
  }
172
117
  function logout(dispatch, userManagerInstance) {
173
118
  sessionStorage.removeItem(hackAuthorityKey);
119
+ sessionStorage.removeItem(oidcHackReloadedKey);
174
120
  return userManagerInstance.getUser().then((user) => {
175
121
  if (user) {
176
122
  return userManagerInstance.signoutRedirect({
@@ -221,17 +167,15 @@ function dispatchUser(dispatch, userManagerInstance, validateUser) {
221
167
  console.debug(
222
168
  "User has been successfully loaded from store."
223
169
  );
224
- if (userManagerInstance.authorizationCodeFlowEnabled) {
225
- reloadTimerOnExpiresIn(
226
- user,
227
- userManagerInstance,
228
- computeMinExpiresIn(
229
- user.expires_in,
230
- user.id_token,
231
- (_b = userManagerInstance.idpSettings) == null ? void 0 : _b.maxExpiresIn
232
- )
233
- );
234
- }
170
+ reloadTimerOnExpiresIn(
171
+ user,
172
+ userManagerInstance,
173
+ computeMinExpiresIn(
174
+ user.expires_in,
175
+ user.id_token,
176
+ (_b = userManagerInstance.idpSettings) == null ? void 0 : _b.maxExpiresIn
177
+ )
178
+ );
235
179
  return dispatch(setLoggedUser(user));
236
180
  }).catch((e) => {
237
181
  var _a;
@@ -259,7 +203,7 @@ function navigateToPreLoginPath(navigate) {
259
203
  function handleSigninCallback(dispatch, navigate, userManagerInstance) {
260
204
  let reloadAfterNavigate = false;
261
205
  userManagerInstance.signinRedirectCallback().catch(function(e) {
262
- if (isIssuerErrorForCodeFlow(e)) {
206
+ if (isIssuerError(e)) {
263
207
  extractIssuerToSessionStorage(e);
264
208
  reloadAfterNavigate = true;
265
209
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gridsuite/commons-ui",
3
- "version": "0.61.1",
3
+ "version": "0.62.0",
4
4
  "description": "common react components for gridsuite applications",
5
5
  "engines": {
6
6
  "npm": ">=9",