@gridsuite/commons-ui 0.43.1 → 0.45.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.
|
@@ -11,9 +11,14 @@ import React from 'react';
|
|
|
11
11
|
import { Button } from '@mui/material';
|
|
12
12
|
import { FormattedMessage } from 'react-intl';
|
|
13
13
|
import PropTypes from 'prop-types';
|
|
14
|
+
import { useThemeProps } from '@mui/material/styles';
|
|
14
15
|
var CancelButton = function CancelButton(_ref) {
|
|
15
|
-
var
|
|
16
|
-
|
|
16
|
+
var inProps = _extends({}, (_objectDestructuringEmpty(_ref), _ref));
|
|
17
|
+
var props = useThemeProps({
|
|
18
|
+
props: inProps,
|
|
19
|
+
name: 'CancelButton'
|
|
20
|
+
});
|
|
21
|
+
return /*#__PURE__*/React.createElement(Button, props, /*#__PURE__*/React.createElement(FormattedMessage, {
|
|
17
22
|
id: "cancel"
|
|
18
23
|
}));
|
|
19
24
|
};
|
package/es/utils/AuthService.js
CHANGED
|
@@ -12,34 +12,62 @@ import jwtDecode from 'jwt-decode';
|
|
|
12
12
|
|
|
13
13
|
// set as a global variable to allow log level configuration at runtime
|
|
14
14
|
window.OIDCLog = Log;
|
|
15
|
-
var
|
|
15
|
+
var hackAuthorityKey = 'oidc.hack.authority';
|
|
16
|
+
var oidcHackReloadedKey = 'gridsuite-oidc-hack-reloaded';
|
|
16
17
|
var pathKey = 'powsybl-gridsuite-current-path';
|
|
18
|
+
function isIssuerErrorForCodeFlow(error) {
|
|
19
|
+
return error.message.includes('Invalid issuer in token');
|
|
20
|
+
}
|
|
21
|
+
function extractIssuerToSessionStorage(error) {
|
|
22
|
+
var issuer = error.message.split(' ').pop();
|
|
23
|
+
sessionStorage.setItem(hackAuthorityKey, issuer);
|
|
24
|
+
}
|
|
25
|
+
function reload() {
|
|
26
|
+
if (!sessionStorage.getItem(oidcHackReloadedKey)) {
|
|
27
|
+
sessionStorage.setItem(oidcHackReloadedKey, true);
|
|
28
|
+
console.log('Hack oidc, reload page to make login work');
|
|
29
|
+
window.location.reload();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function reloadTimerOnExpiresIn(user, userManager, expiresIn) {
|
|
33
|
+
// TODO: Can we stop doing it in the hash for implicit flow ? To make it common for both flows
|
|
34
|
+
user.expires_in = expiresIn;
|
|
35
|
+
userManager.storeUser(user).then(function () {
|
|
36
|
+
userManager.getUser();
|
|
37
|
+
});
|
|
38
|
+
}
|
|
17
39
|
function handleSigninSilent(dispatch, userManager) {
|
|
18
40
|
userManager.getUser().then(function (user) {
|
|
19
41
|
if (user == null || getIdTokenExpiresIn(user) < 0) {
|
|
20
42
|
return userManager.signinSilent()["catch"](function (error) {
|
|
21
43
|
dispatch(setShowAuthenticationRouterLogin(true));
|
|
22
|
-
var
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
44
|
+
var errorIssuerCodeFlow = isIssuerErrorForCodeFlow(error);
|
|
45
|
+
var errorIssuerImplicitFlow = error.message === 'authority mismatch on settings vs. signin state';
|
|
46
|
+
if (errorIssuerCodeFlow) {
|
|
47
|
+
// Replacing authority for code flow only because it's done in the hash for implicit flow
|
|
48
|
+
// TODO: Can we stop doing it in the hash for implicit flow ? To make it common here for both flows
|
|
49
|
+
extractIssuerToSessionStorage(error);
|
|
50
|
+
}
|
|
51
|
+
if (errorIssuerCodeFlow || errorIssuerImplicitFlow) {
|
|
52
|
+
reload();
|
|
27
53
|
}
|
|
28
54
|
});
|
|
29
55
|
}
|
|
30
56
|
});
|
|
31
57
|
}
|
|
32
|
-
function initializeAuthenticationDev(dispatch, isSilentRenew, validateUser) {
|
|
58
|
+
function initializeAuthenticationDev(dispatch, isSilentRenew, validateUser, isSigninCallback) {
|
|
33
59
|
var userManager = new UserManagerMock({});
|
|
34
60
|
if (!isSilentRenew) {
|
|
35
61
|
handleUser(dispatch, userManager, validateUser);
|
|
36
|
-
|
|
62
|
+
if (!isSigninCallback) {
|
|
63
|
+
handleSigninSilent(dispatch, userManager);
|
|
64
|
+
}
|
|
37
65
|
}
|
|
38
66
|
return Promise.resolve(userManager);
|
|
39
67
|
}
|
|
40
68
|
var accessTokenExpiringNotificationTime = 60; // seconds
|
|
41
69
|
|
|
42
|
-
function initializeAuthenticationProd(dispatch, isSilentRenew, idpSettings, validateUser, authorizationCodeFlowEnabled) {
|
|
70
|
+
function initializeAuthenticationProd(dispatch, isSilentRenew, idpSettings, validateUser, authorizationCodeFlowEnabled, isSigninCallback) {
|
|
43
71
|
return idpSettings.then(function (r) {
|
|
44
72
|
return r.json();
|
|
45
73
|
}).then(function (idpSettings) {
|
|
@@ -62,33 +90,16 @@ function initializeAuthenticationProd(dispatch, isSilentRenew, idpSettings, vali
|
|
|
62
90
|
console.debug('Replacing authority in storedState. Before: ', storedState.authority, 'after: ', authority);
|
|
63
91
|
storedState.authority = authority;
|
|
64
92
|
localStorage.setItem('oidc.' + state, JSON.stringify(storedState));
|
|
65
|
-
sessionStorage.setItem(
|
|
93
|
+
sessionStorage.setItem(hackAuthorityKey, authority);
|
|
66
94
|
var matched_expires = window.location.hash.match(regexexpires);
|
|
67
95
|
if (matched_expires != null) {
|
|
68
96
|
var expires_in = parseInt(matched_expires[0].split('=')[1]);
|
|
69
|
-
|
|
70
|
-
var exp = decoded.exp;
|
|
71
|
-
var idTokenExpiresIn = exp - now;
|
|
72
|
-
var minAccesstokenOrIdtokenOrIdpSettingsExpiresIn = expires_in;
|
|
73
|
-
var newExpireReplaceReason;
|
|
74
|
-
if (idTokenExpiresIn < minAccesstokenOrIdtokenOrIdpSettingsExpiresIn) {
|
|
75
|
-
minAccesstokenOrIdtokenOrIdpSettingsExpiresIn = idTokenExpiresIn;
|
|
76
|
-
newExpireReplaceReason = 'idtoken.exp is earlier';
|
|
77
|
-
}
|
|
78
|
-
if (idpSettings.maxExpiresIn && idpSettings.maxExpiresIn < minAccesstokenOrIdtokenOrIdpSettingsExpiresIn) {
|
|
79
|
-
minAccesstokenOrIdtokenOrIdpSettingsExpiresIn = idpSettings.maxExpiresIn;
|
|
80
|
-
newExpireReplaceReason = 'idpSettings.maxExpiresIn is smaller';
|
|
81
|
-
}
|
|
82
|
-
if (newExpireReplaceReason) {
|
|
83
|
-
var newhash = window.location.hash.replace(matched_expires[0], 'expires_in=' + minAccesstokenOrIdtokenOrIdpSettingsExpiresIn);
|
|
84
|
-
console.debug('Replacing expires_in in window.location.hash to ' + minAccesstokenOrIdtokenOrIdpSettingsExpiresIn + ' because ' + newExpireReplaceReason + '. ', 'debug:', 'original expires_in: ' + expires_in + ', ', 'idTokenExpiresIn: ' + idTokenExpiresIn + '(idtoken exp: ' + exp + '), ', 'idpSettings maxExpiresIn: ' + idpSettings.maxExpiresIn);
|
|
85
|
-
window.location.hash = newhash;
|
|
86
|
-
}
|
|
97
|
+
window.location.hash = window.location.hash.replace(matched_expires[0], 'expires_in=' + computeMinExpiresIn(expires_in, id_token, idpSettings.maxExpiresIn));
|
|
87
98
|
}
|
|
88
99
|
}
|
|
89
100
|
}
|
|
90
101
|
}
|
|
91
|
-
authority = authority || sessionStorage.getItem(
|
|
102
|
+
authority = authority || sessionStorage.getItem(hackAuthorityKey) || idpSettings.authority;
|
|
92
103
|
var responseSettings = authorizationCodeFlowEnabled ? {
|
|
93
104
|
response_type: 'code'
|
|
94
105
|
} : {
|
|
@@ -107,9 +118,12 @@ function initializeAuthenticationProd(dispatch, isSilentRenew, idpSettings, vali
|
|
|
107
118
|
}, responseSettings);
|
|
108
119
|
var userManager = new UserManager(settings);
|
|
109
120
|
userManager.idpSettings = idpSettings; //store our settings in there as well to use it later
|
|
121
|
+
userManager.authorizationCodeFlowEnabled = authorizationCodeFlowEnabled;
|
|
110
122
|
if (!isSilentRenew) {
|
|
111
123
|
handleUser(dispatch, userManager, validateUser);
|
|
112
|
-
|
|
124
|
+
if (!isSigninCallback) {
|
|
125
|
+
handleSigninSilent(dispatch, userManager);
|
|
126
|
+
}
|
|
113
127
|
}
|
|
114
128
|
return userManager;
|
|
115
129
|
})["catch"](function (error) {
|
|
@@ -118,6 +132,25 @@ function initializeAuthenticationProd(dispatch, isSilentRenew, idpSettings, vali
|
|
|
118
132
|
throw error;
|
|
119
133
|
});
|
|
120
134
|
}
|
|
135
|
+
function computeMinExpiresIn(expiresIn, idToken, maxExpiresIn) {
|
|
136
|
+
var now = parseInt(Date.now() / 1000);
|
|
137
|
+
var exp = jwtDecode(idToken).exp;
|
|
138
|
+
var idTokenExpiresIn = exp - now;
|
|
139
|
+
var newExpiresIn = expiresIn;
|
|
140
|
+
var newExpiresInReplaceReason;
|
|
141
|
+
if (expiresIn === undefined || idTokenExpiresIn < newExpiresIn) {
|
|
142
|
+
newExpiresIn = idTokenExpiresIn;
|
|
143
|
+
newExpiresInReplaceReason = 'idtoken.exp is earlier';
|
|
144
|
+
}
|
|
145
|
+
if (maxExpiresIn && maxExpiresIn < newExpiresIn) {
|
|
146
|
+
newExpiresIn = maxExpiresIn;
|
|
147
|
+
newExpiresInReplaceReason = 'idpSettings.maxExpiresIn is smaller';
|
|
148
|
+
}
|
|
149
|
+
if (newExpiresInReplaceReason) {
|
|
150
|
+
console.debug('Replacing expiresIn in user to ' + newExpiresIn + ' because ' + newExpiresInReplaceReason + '. ', 'debug:', 'original expires_in: ' + expiresIn + ', ', 'idTokenExpiresIn: ' + idTokenExpiresIn + ', idpSettings maxExpiresIn: ' + maxExpiresIn);
|
|
151
|
+
}
|
|
152
|
+
return newExpiresIn;
|
|
153
|
+
}
|
|
121
154
|
function login(location, userManagerInstance) {
|
|
122
155
|
sessionStorage.setItem(pathKey, location.pathname + location.search);
|
|
123
156
|
return userManagerInstance.signinRedirect().then(function () {
|
|
@@ -125,7 +158,7 @@ function login(location, userManagerInstance) {
|
|
|
125
158
|
});
|
|
126
159
|
}
|
|
127
160
|
function logout(dispatch, userManagerInstance) {
|
|
128
|
-
sessionStorage.removeItem(
|
|
161
|
+
sessionStorage.removeItem(hackAuthorityKey); //To remove when hack is removed
|
|
129
162
|
return userManagerInstance.getUser().then(function (user) {
|
|
130
163
|
if (user) {
|
|
131
164
|
// We don't need to check if token is valid at this point
|
|
@@ -173,6 +206,12 @@ function dispatchUser(dispatch, userManagerInstance, validateUser) {
|
|
|
173
206
|
return dispatch(setUnauthorizedUserInfo(user === null || user === void 0 ? void 0 : (_user$profile2 = user.profile) === null || _user$profile2 === void 0 ? void 0 : _user$profile2.name, {}));
|
|
174
207
|
}
|
|
175
208
|
console.debug('User has been successfully loaded from store.');
|
|
209
|
+
|
|
210
|
+
// In authorization code flow we have to make the oidc-client lib re-evaluate the date of the token renewal timers
|
|
211
|
+
// because it is not hacked at page loading on the fragment before oidc-client lib initialization
|
|
212
|
+
if (userManagerInstance.authorizationCodeFlowEnabled) {
|
|
213
|
+
reloadTimerOnExpiresIn(user, userManagerInstance, computeMinExpiresIn(user.expires_in, user.id_token, userManagerInstance.idpSettings.maxExpiresIn));
|
|
214
|
+
}
|
|
176
215
|
return dispatch(setLoggedUser(user));
|
|
177
216
|
})["catch"](function (e) {
|
|
178
217
|
var _user$profile3;
|
|
@@ -189,11 +228,31 @@ function dispatchUser(dispatch, userManagerInstance, validateUser) {
|
|
|
189
228
|
function getPreLoginPath() {
|
|
190
229
|
return sessionStorage.getItem(pathKey);
|
|
191
230
|
}
|
|
231
|
+
function navigateToPreLoginPath(navigate) {
|
|
232
|
+
var previousPath = getPreLoginPath();
|
|
233
|
+
navigate(previousPath);
|
|
234
|
+
}
|
|
192
235
|
function handleSigninCallback(dispatch, navigate, userManagerInstance) {
|
|
193
|
-
|
|
236
|
+
var reloadAfterNavigate = false;
|
|
237
|
+
userManagerInstance.signinRedirectCallback()["catch"](function (e) {
|
|
238
|
+
if (isIssuerErrorForCodeFlow(e)) {
|
|
239
|
+
// Replacing authority for code flow only because it's done in the hash for implicit flow
|
|
240
|
+
// TODO: Can we also do it here for the implicit flow ? To make it common here for both flows
|
|
241
|
+
extractIssuerToSessionStorage(e);
|
|
242
|
+
// After navigate, location will be out of a redirection route (sign-in-silent or sign-in-callback) so reloading the page will attempt a silent signin
|
|
243
|
+
// It will reload the user manager based on hacked authority at initialization with the new authority
|
|
244
|
+
// We do this because on Azure we only get to know the issuer of the user in the idtoken and so signingredirectcallback will always fail
|
|
245
|
+
// We could restart the whole login process from signin redirect with the correct issuer, but instead we just rely on the silent login after the reload which will work
|
|
246
|
+
reloadAfterNavigate = true;
|
|
247
|
+
} else {
|
|
248
|
+
throw e;
|
|
249
|
+
}
|
|
250
|
+
}).then(function () {
|
|
194
251
|
dispatch(setSignInCallbackError(null));
|
|
195
|
-
|
|
196
|
-
|
|
252
|
+
navigateToPreLoginPath(navigate);
|
|
253
|
+
if (reloadAfterNavigate) {
|
|
254
|
+
reload();
|
|
255
|
+
}
|
|
197
256
|
})["catch"](function (e) {
|
|
198
257
|
dispatch(setSignInCallbackError(e));
|
|
199
258
|
console.error(e);
|
|
@@ -209,8 +268,9 @@ function handleUser(dispatch, userManager, validateUser) {
|
|
|
209
268
|
});
|
|
210
269
|
userManager.events.addSilentRenewError(function (error) {
|
|
211
270
|
console.debug(error);
|
|
212
|
-
//
|
|
213
|
-
// otherwise the library
|
|
271
|
+
// Wait for accessTokenExpiringNotificationTime so that the user is expired and not between expiring and expired
|
|
272
|
+
// otherwise the library will fire AccessTokenExpiring everytime we do getUser()
|
|
273
|
+
// Indeed, getUSer() => loadUser() => load() on events => if it's already expiring it will be init and triggerred again
|
|
214
274
|
window.setTimeout(function () {
|
|
215
275
|
userManager.getUser().then(function (user) {
|
|
216
276
|
if (!user) {
|
|
@@ -229,16 +289,10 @@ function handleUser(dispatch, userManager, validateUser) {
|
|
|
229
289
|
// TODO here attempt last chance login ? snackbar to notify the user ? Popup ?
|
|
230
290
|
// for now we do the same thing as in the else block
|
|
231
291
|
console.log('Error in silent renew, but idtoken ALMOST expiring (expiring in' + idTokenExpiresIn + ') => last chance, next error will logout', 'maxExpiresIn = ' + userManager.idpSettings.maxExpiresIn, 'last renew attempt in ' + idTokenExpiresIn - accessTokenExpiringNotificationTime + 'seconds', error);
|
|
232
|
-
user
|
|
233
|
-
userManager.storeUser(user).then(function () {
|
|
234
|
-
userManager.getUser();
|
|
235
|
-
});
|
|
292
|
+
reloadTimerOnExpiresIn(user, userManager, idTokenExpiresIn);
|
|
236
293
|
} else {
|
|
237
294
|
console.log('Error in silent renew, but idtoken NOT expiring (expiring in' + idTokenExpiresIn + ') => postponing expiration to' + userManager.idpSettings.maxExpiresIn, error);
|
|
238
|
-
user
|
|
239
|
-
userManager.storeUser(user).then(function () {
|
|
240
|
-
userManager.getUser();
|
|
241
|
-
});
|
|
295
|
+
reloadTimerOnExpiresIn(user, userManager, userManager.idpSettings.maxExpiresIn);
|
|
242
296
|
}
|
|
243
297
|
} else {
|
|
244
298
|
console.log('Error in silent renew, unsupported configuration: token still valid for ' + idTokenExpiresIn + ' but maxExpiresIn is not configured:' + userManager.idpSettings.maxExpiresIn, error);
|
package/es/utils/ElementType.js
CHANGED
|
@@ -7,12 +7,14 @@
|
|
|
7
7
|
import React from 'react';
|
|
8
8
|
import LibraryBooksOutlinedIcon from '@mui/icons-material/LibraryBooksOutlined';
|
|
9
9
|
import OfflineBoltIcon from '@mui/icons-material/OfflineBolt';
|
|
10
|
+
import NoteAltIcon from '@mui/icons-material/NoteAlt';
|
|
10
11
|
import ArticleIcon from '@mui/icons-material/Article';
|
|
11
12
|
import SettingsIcon from '@mui/icons-material/Settings';
|
|
12
13
|
export var elementType = {
|
|
13
14
|
DIRECTORY: 'DIRECTORY',
|
|
14
15
|
STUDY: 'STUDY',
|
|
15
16
|
FILTER: 'FILTER',
|
|
17
|
+
MODIFICATION: 'MODIFICATION',
|
|
16
18
|
CONTINGENCY_LIST: 'CONTINGENCY_LIST',
|
|
17
19
|
VOLTAGE_INIT_PARAMETERS: 'VOLTAGE_INIT_PARAMETERS'
|
|
18
20
|
};
|
|
@@ -26,6 +28,10 @@ export function getFileIcon(type, style) {
|
|
|
26
28
|
return /*#__PURE__*/React.createElement(OfflineBoltIcon, {
|
|
27
29
|
sx: style
|
|
28
30
|
});
|
|
31
|
+
case elementType.MODIFICATION:
|
|
32
|
+
return /*#__PURE__*/React.createElement(NoteAltIcon, {
|
|
33
|
+
sx: style
|
|
34
|
+
});
|
|
29
35
|
case elementType.FILTER:
|
|
30
36
|
return /*#__PURE__*/React.createElement(ArticleIcon, {
|
|
31
37
|
sx: style
|