asab_webui_shell 25.1.1

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.
Files changed (90) hide show
  1. package/CHANGELOG.md +218 -0
  2. package/LICENSE +28 -0
  3. package/README.md +3 -0
  4. package/dist/actions.js +22 -0
  5. package/dist/components/branding/BrandImage.js +72 -0
  6. package/dist/components/locationReplace.js +51 -0
  7. package/dist/config/ConfigReducer.js +22 -0
  8. package/dist/config/ConfigService.js +169 -0
  9. package/dist/containers/AdvancedMode/reducer.js +28 -0
  10. package/dist/containers/Alerts/alerts.scss +9 -0
  11. package/dist/containers/Alerts/index.js +81 -0
  12. package/dist/containers/Alerts/reducer.js +68 -0
  13. package/dist/containers/Application.js +773 -0
  14. package/dist/containers/Application.scss +104 -0
  15. package/dist/containers/AttentionRequired/reducer.js +30 -0
  16. package/dist/containers/FullscreenMode/reducer.js +28 -0
  17. package/dist/containers/Header/ApplicationScreenTitle/ApplicationScreenTitle.js +47 -0
  18. package/dist/containers/Header/ApplicationScreenTitle/ApplicationScreenTitle.scss +8 -0
  19. package/dist/containers/Header/ApplicationScreenTitle/index.js +31 -0
  20. package/dist/containers/Header/Help/HelpButton.js +58 -0
  21. package/dist/containers/Header/Help/HelpButton.scss +15 -0
  22. package/dist/containers/Header/Help/HelpService.js +34 -0
  23. package/dist/containers/Header/Preview/PreviewFlag.js +34 -0
  24. package/dist/containers/Header/Preview/PreviewService.js +34 -0
  25. package/dist/containers/Header/header.scss +24 -0
  26. package/dist/containers/Header/index.js +39 -0
  27. package/dist/containers/Header/reducer.js +53 -0
  28. package/dist/containers/Navigation/index.js +66 -0
  29. package/dist/containers/Navigation/reducer.js +56 -0
  30. package/dist/containers/RouteErrorHandler/ErrorContainer.js +46 -0
  31. package/dist/containers/RouteErrorHandler/index.js +80 -0
  32. package/dist/containers/Router/ApplicationRouter.js +78 -0
  33. package/dist/containers/Router/index.js +50 -0
  34. package/dist/containers/Router/reducer.js +28 -0
  35. package/dist/containers/Sidebar/NavbarBrand.js +59 -0
  36. package/dist/containers/Sidebar/SidebarBottomItem.js +55 -0
  37. package/dist/containers/Sidebar/SidebarIcon.js +21 -0
  38. package/dist/containers/Sidebar/SidebarItem.js +209 -0
  39. package/dist/containers/Sidebar/SidebarItemRenderer.js +30 -0
  40. package/dist/containers/Sidebar/index.js +86 -0
  41. package/dist/containers/Sidebar/reducer.js +35 -0
  42. package/dist/containers/Sidebar/sidebar.scss +176 -0
  43. package/dist/containers/Sidepanel/Sidepanel.js +60 -0
  44. package/dist/containers/Sidepanel/Sidepanel.scss +20 -0
  45. package/dist/containers/Toast/ToastComponent.js +31 -0
  46. package/dist/containers/Toast/ToastComponent.jsx +28 -0
  47. package/dist/containers/Toast/ToastContainer.js +80 -0
  48. package/dist/containers/Toast/ToastContainer.jsx +59 -0
  49. package/dist/containers/Toast/reducer.js +55 -0
  50. package/dist/containers/Toast/reducer.jsx +45 -0
  51. package/dist/index.js +48 -0
  52. package/dist/modules/about/AboutScreen.js +84 -0
  53. package/dist/modules/about/index.js +41 -0
  54. package/dist/modules/auth/actions.js +11 -0
  55. package/dist/modules/auth/api.js +214 -0
  56. package/dist/modules/auth/components/SessionExpirationAlert.js +35 -0
  57. package/dist/modules/auth/header.js +109 -0
  58. package/dist/modules/auth/header.scss +9 -0
  59. package/dist/modules/auth/index.js +761 -0
  60. package/dist/modules/auth/reducer.js +36 -0
  61. package/dist/modules/auth/screens/AccessControlScreen.js +78 -0
  62. package/dist/modules/auth/screens/InvitationScreen.js +161 -0
  63. package/dist/modules/i18n/actions.js +7 -0
  64. package/dist/modules/i18n/dropdown.js +77 -0
  65. package/dist/modules/i18n/index.js +44 -0
  66. package/dist/modules/i18n/reducer.js +26 -0
  67. package/dist/modules/i18n/service.js +158 -0
  68. package/dist/modules/tenant/TenantDropdown.js +53 -0
  69. package/dist/modules/tenant/access/AccessDeniedCard.js +107 -0
  70. package/dist/modules/tenant/access/AccessDeniedCard.scss +6 -0
  71. package/dist/modules/tenant/actions.js +10 -0
  72. package/dist/modules/tenant/index.js +41 -0
  73. package/dist/modules/tenant/reducer.js +26 -0
  74. package/dist/modules/tenant/service.js +228 -0
  75. package/dist/screens/InvalidRouteScreen.js +30 -0
  76. package/dist/screens/InvalidRouteScreen.scss +19 -0
  77. package/dist/screens/SuspenseScreen.js +43 -0
  78. package/dist/screens/SuspenseScreen.scss +9 -0
  79. package/dist/screens/UnauthorizedAccessScreen.js +79 -0
  80. package/dist/screens/UnauthorizedAccessScreen.scss +19 -0
  81. package/dist/services/AttentionRequiredService.js +169 -0
  82. package/dist/services/BrandingService.js +104 -0
  83. package/dist/services/HeaderService.js +84 -0
  84. package/dist/services/ReduxService.js +25 -0
  85. package/dist/services/TitleService.js +45 -0
  86. package/dist/theme/ThemeButton.js +39 -0
  87. package/dist/theme/ThemeReducer.js +20 -0
  88. package/dist/theme/ThemeService.js +52 -0
  89. package/dist/theme/actions.js +7 -0
  90. package/package.json +41 -0
@@ -0,0 +1,761 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports["default"] = void 0;
8
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
9
+ var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
10
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
11
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
12
+ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
13
+ var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
14
+ var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
15
+ var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
16
+ var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
17
+ var _react = _interopRequireWildcard(require("react"));
18
+ var _asab_webui_components = require("asab_webui_components");
19
+ var _header = require("./header");
20
+ var _reducer = _interopRequireDefault(require("./reducer"));
21
+ var _actions = require("./actions");
22
+ var _actions2 = require("../../actions");
23
+ var _api = require("./api");
24
+ var _locationReplace = require("../../components/locationReplace");
25
+ var _SessionExpirationAlert = require("./components/SessionExpirationAlert");
26
+ function _callSuper(t, o, e) { return o = (0, _getPrototypeOf2["default"])(o), (0, _possibleConstructorReturn2["default"])(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], (0, _getPrototypeOf2["default"])(t).constructor) : o.apply(t, e)); }
27
+ function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
28
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
29
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != (0, _typeof2["default"])(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; } // TODO: Use SessionExpirationAlert only after proper fix of the component
30
+ var AccessControlScreen = /*#__PURE__*/(0, _react.lazy)(function () {
31
+ return Promise.resolve().then(function () {
32
+ return _interopRequireWildcard(require("./screens/AccessControlScreen"));
33
+ });
34
+ });
35
+ var InvitationScreen = /*#__PURE__*/(0, _react.lazy)(function () {
36
+ return Promise.resolve().then(function () {
37
+ return _interopRequireWildcard(require("./screens/InvitationScreen"));
38
+ });
39
+ });
40
+ var AuthModule = exports["default"] = /*#__PURE__*/function (_Module) {
41
+ function AuthModule(app, name) {
42
+ var _this;
43
+ (0, _classCallCheck2["default"])(this, AuthModule);
44
+ _this = _callSuper(this, AuthModule, [app, "AuthModule"]);
45
+ _this.OAuthToken = JSON.parse(sessionStorage.getItem('SeaCatOAuth2Token'));
46
+ _this.UserInfo = null;
47
+ _this.Api = new _api.SeaCatAuthApi(app);
48
+ _this.RedirectURL = window.location.href;
49
+ _this.MustAuthenticate = true; // Setting this to false means, that we can operate without authenticated user
50
+ app.ReduxService.addReducer("auth", _reducer["default"]);
51
+ _this.App.addSplashScreenRequestor(_this);
52
+ _this.Authorization = _this.App.Config.get("authorization"); // Get authorization settings from configuration
53
+
54
+ _this.SessionExpiration = null; // Session expiration as defined in user info
55
+ _this.sessionValidationInterval = null; // Initialize session validation interval
56
+
57
+ // Access control screen
58
+ app.Router.addRoute({
59
+ path: '/auth/access-control',
60
+ end: true,
61
+ name: 'Access control',
62
+ component: AccessControlScreen,
63
+ resource: "*"
64
+ });
65
+
66
+ // Invitation screen
67
+ app.Router.addRoute({
68
+ path: '/auth/invite',
69
+ end: true,
70
+ name: 'Invite',
71
+ component: InvitationScreen,
72
+ resource: "seacat:tenant:assign"
73
+ });
74
+ return _this;
75
+ }
76
+ (0, _inherits2["default"])(AuthModule, _Module);
77
+ return (0, _createClass2["default"])(AuthModule, [{
78
+ key: "initialize",
79
+ value: function () {
80
+ var _initialize = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee() {
81
+ var headerService, qs, authorization_code, errorType, stateIndex, state, reloadUrl, result, force_login_prompt, tenantAuthorized, _force_login_prompt, currentTenant, resources, _force_login_prompt2, _force_login_prompt3;
82
+ return _regenerator["default"].wrap(function _callee$(_context) {
83
+ while (1) switch (_context.prev = _context.next) {
84
+ case 0:
85
+ headerService = this.App.locateService("HeaderService");
86
+ headerService.addComponent({
87
+ component: _header.AuthHeaderInvitation,
88
+ componentProps: {
89
+ AuthModule: this
90
+ },
91
+ order: 200
92
+ });
93
+ headerService.addComponent({
94
+ component: _header.AuthHeaderDropdown,
95
+ componentProps: {
96
+ AuthModule: this
97
+ },
98
+ order: 700
99
+ });
100
+ if (!(typeof MOCK_USERINFO !== 'undefined')) {
101
+ _context.next = 8;
102
+ break;
103
+ }
104
+ _context.next = 6;
105
+ return this.simulateUserinfo(MOCK_USERINFO);
106
+ case 6:
107
+ _context.next = 63;
108
+ break;
109
+ case 8:
110
+ // Check the query string for 'code'
111
+ qs = new URLSearchParams(window.location.search);
112
+ authorization_code = qs.get('code'); // Checking error type in params
113
+ errorType = qs.get('error');
114
+ if (!(errorType != undefined && errorType != 'tenant_access_denied')) {
115
+ _context.next = 13;
116
+ break;
117
+ }
118
+ return _context.abrupt("return");
119
+ case 13:
120
+ if (!(authorization_code !== null)) {
121
+ _context.next = 25;
122
+ break;
123
+ }
124
+ _context.next = 16;
125
+ return this._updateToken(authorization_code);
126
+ case 16:
127
+ // Remove 'code' from a query string
128
+ qs["delete"]('code');
129
+ stateIndex = qs.get("state");
130
+ state = ""; // Check if stateIndex is present, eventually return empty state string
131
+ if (stateIndex != undefined) {
132
+ // Check if oauth2_state_ is present, eventually return empty string
133
+ if (localStorage.getItem("oauth2_state_".concat(stateIndex)) != undefined) {
134
+ state = localStorage.getItem("oauth2_state_".concat(stateIndex));
135
+ }
136
+ }
137
+ localStorage.removeItem("oauth2_state_".concat(stateIndex));
138
+
139
+ // Remove 'state' from a query string
140
+ qs["delete"]("state");
141
+
142
+ // Construct the new URL without `code` in the query string
143
+ // For this case, condition on empty qs string is sufficient and tested
144
+
145
+ if (qs.toString() == '') {
146
+ // Remove `?` part from URL completely, if empty
147
+ reloadUrl = window.location.pathname + state; // part form localstorage instead of hash
148
+ } else {
149
+ reloadUrl = window.location.pathname + '?' + qs.toString() + state; // part form localstorage instead of hash
150
+ }
151
+
152
+ // Reload the app with `code` removed
153
+ _context.next = 25;
154
+ return (0, _locationReplace.locationReplace)(reloadUrl);
155
+ case 25:
156
+ if (!(this.OAuthToken != null)) {
157
+ _context.next = 58;
158
+ break;
159
+ }
160
+ _context.next = 28;
161
+ return this.updateUserInfo();
162
+ case 28:
163
+ result = _context.sent;
164
+ if (result) {
165
+ _context.next = 35;
166
+ break;
167
+ }
168
+ // User info not found - go to login
169
+ sessionStorage.removeItem('SeaCatOAuth2Token');
170
+ force_login_prompt = true;
171
+ _context.next = 34;
172
+ return this.Api.login(this.RedirectURL, force_login_prompt);
173
+ case 34:
174
+ return _context.abrupt("return");
175
+ case 35:
176
+ // Add interceptor with Bearer token in the Header into axios calls
177
+ this.App.addAxiosInterceptor(this.authInterceptor());
178
+ // Add webSocket interceptor with Bearer token into websocket calls
179
+ this.App.addWebSocketInterceptor(this.webSocketAuthInterceptor());
180
+
181
+ // Authorization of the user based on tenant access
182
+ if (!(this.App.Config.get("authorization") !== "disabled" && this.App.Services.TenantService)) {
183
+ _context.next = 44;
184
+ break;
185
+ }
186
+ // Tenant access validation
187
+ tenantAuthorized = this.validateTenant();
188
+ if (tenantAuthorized) {
189
+ _context.next = 44;
190
+ break;
191
+ }
192
+ // If tenant not authorized, redirect to Access denied card
193
+ _force_login_prompt = false;
194
+ _context.next = 43;
195
+ return this.Api.login(this.RedirectURL, _force_login_prompt);
196
+ case 43:
197
+ return _context.abrupt("return");
198
+ case 44:
199
+ if (!(this.App.Store && this.App.Services.TenantService && this.UserInfo !== null)) {
200
+ _context.next = 55;
201
+ break;
202
+ }
203
+ currentTenant = this.App.Services.TenantService.getCurrentTenant();
204
+ resources = this.UserInfo.resources ? this.UserInfo.resources[currentTenant] : [];
205
+ /*
206
+ When switching between tenants,
207
+ we need to force authorization to obtain
208
+ correct data (resources) for particular
209
+ tenant (this is unavailable until auth token is updated)
210
+ */
211
+ if (!(resources == undefined)) {
212
+ _context.next = 52;
213
+ break;
214
+ }
215
+ _force_login_prompt2 = false;
216
+ _context.next = 51;
217
+ return this.Api.login(this.RedirectURL, _force_login_prompt2);
218
+ case 51:
219
+ return _context.abrupt("return");
220
+ case 52:
221
+ if (this.App.Store != null) {
222
+ this.App.Store.dispatch({
223
+ type: _actions.types.AUTH_RESOURCES,
224
+ resources: resources
225
+ });
226
+ }
227
+ _context.next = 55;
228
+ return this.validateNavigation();
229
+ case 55:
230
+ if (!(this.UserInfo != null)) {
231
+ _context.next = 58;
232
+ break;
233
+ }
234
+ _context.next = 58;
235
+ return this._startSessionExpirationValidation();
236
+ case 58:
237
+ if (!(this.UserInfo == null && this.MustAuthenticate)) {
238
+ _context.next = 63;
239
+ break;
240
+ }
241
+ // TODO: force_login_prompt = true to break authentication failure loop
242
+ _force_login_prompt3 = false;
243
+ _context.next = 62;
244
+ return this.Api.login(this.RedirectURL, _force_login_prompt3);
245
+ case 62:
246
+ return _context.abrupt("return");
247
+ case 63:
248
+ this.App.removeSplashScreenRequestor(this);
249
+ case 64:
250
+ case "end":
251
+ return _context.stop();
252
+ }
253
+ }, _callee, this);
254
+ }));
255
+ function initialize() {
256
+ return _initialize.apply(this, arguments);
257
+ }
258
+ return initialize;
259
+ }()
260
+ }, {
261
+ key: "authInterceptor",
262
+ value: function authInterceptor() {
263
+ var _this2 = this;
264
+ var interceptor = function interceptor(config) {
265
+ config.headers['Authorization'] = 'Bearer ' + _this2.OAuthToken['access_token'];
266
+ return config;
267
+ };
268
+ return interceptor;
269
+ }
270
+ }, {
271
+ key: "webSocketAuthInterceptor",
272
+ value: function webSocketAuthInterceptor() {
273
+ return "access_token_".concat(this.OAuthToken['access_token']);
274
+ }
275
+ }, {
276
+ key: "simulateUserinfo",
277
+ value: function () {
278
+ var _simulateUserinfo = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee2(mock_userinfo) {
279
+ var mockParams, availableTenants;
280
+ return _regenerator["default"].wrap(function _callee2$(_context2) {
281
+ while (1) switch (_context2.prev = _context2.next) {
282
+ case 0:
283
+ /*
284
+ This method takes parameters from wepack.dev.js settings
285
+ plugins: [
286
+ ...
287
+ new webpack.DefinePlugin({
288
+ 'MOCK_USERINFO': JSON.stringify({ // Inject mocked UserInfo object, this means the application will NOT require user authorization
289
+ "username": "johndev",
290
+ "email": "dev@dev.de",
291
+ "phone": "123456789",
292
+ "resources": ["authz:superuser"],
293
+ "roles": ["default/Admin"],
294
+ "sub": "devdb:dev:1abc2def3456",
295
+ "tenants": ["default"]
296
+ })
297
+ }),
298
+ ...
299
+ ],
300
+ */
301
+ this.App.addAlert("warning", "ASABAuthModule|You are using MOCK_USERINFO!", 1, true);
302
+ mockParams = mock_userinfo;
303
+ if (mockParams.resources) {
304
+ mockParams["resources"] = Object.values(mockParams.resources);
305
+ }
306
+ if (mockParams.roles) {
307
+ mockParams["roles"] = Object.values(mockParams.roles);
308
+ }
309
+ if (mockParams.tenants) {
310
+ mockParams["tenants"] = Object.values(mockParams.tenants);
311
+ }
312
+ if (this.App.Store != null) {
313
+ this.App.Store.dispatch({
314
+ type: _actions.types.AUTH_USERINFO,
315
+ payload: mockParams
316
+ });
317
+ this.App.Store.dispatch({
318
+ type: _actions.types.AUTH_RESOURCES,
319
+ resources: mockParams["resources"]
320
+ });
321
+ }
322
+
323
+ /** Check for TenantService and pass tenants list obtained from userinfo */
324
+ availableTenants = mockParams.tenants;
325
+ if (!this.App.Services.TenantService) {
326
+ _context2.next = 10;
327
+ break;
328
+ }
329
+ _context2.next = 10;
330
+ return this.App.Services.TenantService.setTenants(availableTenants, this._getAuthorizedTenant(mockParams));
331
+ case 10:
332
+ case "end":
333
+ return _context2.stop();
334
+ }
335
+ }, _callee2, this);
336
+ }));
337
+ function simulateUserinfo(_x) {
338
+ return _simulateUserinfo.apply(this, arguments);
339
+ }
340
+ return simulateUserinfo;
341
+ }()
342
+ }, {
343
+ key: "logout",
344
+ value: function logout() {
345
+ this.App.addSplashScreenRequestor(this);
346
+ this._stopSessionExpirationValidation(); // Stop session validation and clear the timeout
347
+
348
+ sessionStorage.removeItem('SeaCatOAuth2Token');
349
+ var promise = this.Api.logout(this.OAuthToken['access_token']);
350
+ if (promise == null) {
351
+ window.location.reload();
352
+ }
353
+ promise.then(function (response) {
354
+ window.location.reload();
355
+ })["catch"](function (error) {
356
+ window.location.reload();
357
+ });
358
+ }
359
+
360
+ // TODO: reconsider removing async/await with promise
361
+ }, {
362
+ key: "validateNavigation",
363
+ value: function () {
364
+ var _validateNavigation = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee4() {
365
+ var _state$navigation,
366
+ _state$auth,
367
+ _this3 = this;
368
+ var state, navItems, resources, authorizedNavItems;
369
+ return _regenerator["default"].wrap(function _callee4$(_context4) {
370
+ while (1) switch (_context4.prev = _context4.next) {
371
+ case 0:
372
+ state = this.App.Store.getState();
373
+ navItems = (_state$navigation = state.navigation) === null || _state$navigation === void 0 ? void 0 : _state$navigation.navItems;
374
+ resources = (_state$auth = state.auth) === null || _state$auth === void 0 ? void 0 : _state$auth.resources;
375
+ authorizedNavItems = [];
376
+ _context4.t0 = navItems;
377
+ if (!_context4.t0) {
378
+ _context4.next = 8;
379
+ break;
380
+ }
381
+ _context4.next = 8;
382
+ return Promise.all(navItems.map(/*#__PURE__*/function () {
383
+ var _ref = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee3(itm, idx) {
384
+ var access_auth;
385
+ return _regenerator["default"].wrap(function _callee3$(_context3) {
386
+ while (1) switch (_context3.prev = _context3.next) {
387
+ case 0:
388
+ if (!(resources.indexOf('authz:superuser') !== -1)) {
389
+ _context3.next = 4;
390
+ break;
391
+ }
392
+ // If user is superuser, validate every navigation item
393
+ authorizedNavItems.push(itm);
394
+ _context3.next = 18;
395
+ break;
396
+ case 4:
397
+ if (!itm.resource) {
398
+ _context3.next = 13;
399
+ break;
400
+ }
401
+ if (!itm.children) {
402
+ _context3.next = 9;
403
+ break;
404
+ }
405
+ _context3.next = 8;
406
+ return _this3._validateChildrenNav(itm, resources);
407
+ case 8:
408
+ itm.children = _context3.sent;
409
+ case 9:
410
+ // Item validation
411
+ access_auth = _this3._validateItemNav(itm.resource, resources);
412
+ if (access_auth == true) {
413
+ authorizedNavItems.push(itm);
414
+ }
415
+ _context3.next = 18;
416
+ break;
417
+ case 13:
418
+ if (!itm.children) {
419
+ _context3.next = 18;
420
+ break;
421
+ }
422
+ _context3.next = 16;
423
+ return _this3._validateChildrenNav(itm, resources);
424
+ case 16:
425
+ itm.children = _context3.sent;
426
+ if (itm.children.length > 0) {
427
+ authorizedNavItems.push(itm);
428
+ }
429
+ case 18:
430
+ case "end":
431
+ return _context3.stop();
432
+ }
433
+ }, _callee3);
434
+ }));
435
+ return function (_x2, _x3) {
436
+ return _ref.apply(this, arguments);
437
+ };
438
+ }()));
439
+ case 8:
440
+ this.App.Store.dispatch({
441
+ type: _actions2.SET_NAVIGATION_ITEMS,
442
+ navItems: authorizedNavItems
443
+ });
444
+ case 9:
445
+ case "end":
446
+ return _context4.stop();
447
+ }
448
+ }, _callee4, this);
449
+ }));
450
+ function validateNavigation() {
451
+ return _validateNavigation.apply(this, arguments);
452
+ }
453
+ return validateNavigation;
454
+ }() // Validate sidebar's item children
455
+ }, {
456
+ key: "_validateChildrenNav",
457
+ value: function () {
458
+ var _validateChildrenNav2 = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee6(itm, resources) {
459
+ var _this4 = this;
460
+ var authorizedNavChildren;
461
+ return _regenerator["default"].wrap(function _callee6$(_context6) {
462
+ while (1) switch (_context6.prev = _context6.next) {
463
+ case 0:
464
+ // Item's children validation
465
+ authorizedNavChildren = [];
466
+ _context6.next = 3;
467
+ return Promise.all(itm.children.map(/*#__PURE__*/function () {
468
+ var _ref2 = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee5(child, id) {
469
+ var access_auth;
470
+ return _regenerator["default"].wrap(function _callee5$(_context5) {
471
+ while (1) switch (_context5.prev = _context5.next) {
472
+ case 0:
473
+ if (child.resource) {
474
+ access_auth = _this4._validateItemNav(child.resource, resources);
475
+ if (access_auth == true) {
476
+ authorizedNavChildren.push(child);
477
+ }
478
+ }
479
+ case 1:
480
+ case "end":
481
+ return _context5.stop();
482
+ }
483
+ }, _callee5);
484
+ }));
485
+ return function (_x6, _x7) {
486
+ return _ref2.apply(this, arguments);
487
+ };
488
+ }()));
489
+ case 3:
490
+ return _context6.abrupt("return", authorizedNavChildren);
491
+ case 4:
492
+ case "end":
493
+ return _context6.stop();
494
+ }
495
+ }, _callee6);
496
+ }));
497
+ function _validateChildrenNav(_x4, _x5) {
498
+ return _validateChildrenNav2.apply(this, arguments);
499
+ }
500
+ return _validateChildrenNav;
501
+ }() // Validate sidebar items
502
+ }, {
503
+ key: "_validateItemNav",
504
+ value: function _validateItemNav(resource, resources) {
505
+ var valid = resources ? resources.indexOf(resource) !== -1 : false;
506
+ // If user is superuser, then item is enabled
507
+ if (resources.indexOf('authz:superuser') !== -1) {
508
+ valid = true;
509
+ }
510
+ return valid;
511
+ }
512
+
513
+ // Validate tenant access
514
+ }, {
515
+ key: "validateTenant",
516
+ value: function validateTenant() {
517
+ var resources = [];
518
+ var tenants = [];
519
+ var currentTenant = this.App.Services.TenantService.getCurrentTenant();
520
+ if (this.UserInfo !== null) {
521
+ resources = this.UserInfo.resources ? this.UserInfo.resources[currentTenant] : [];
522
+ tenants = this.UserInfo.tenants ? this.UserInfo.tenants : [];
523
+ }
524
+ var valid = tenants ? tenants.indexOf(currentTenant) !== -1 : false;
525
+ // If user is superuser, then tenant access is granted
526
+ if (resources && resources.indexOf('authz:superuser') !== -1) {
527
+ valid = true;
528
+ }
529
+ return valid;
530
+ }
531
+ }, {
532
+ key: "updateUserInfo",
533
+ value: function () {
534
+ var _updateUserInfo = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee7() {
535
+ var _response$data;
536
+ var response, availableTenants;
537
+ return _regenerator["default"].wrap(function _callee7$(_context7) {
538
+ while (1) switch (_context7.prev = _context7.next) {
539
+ case 0:
540
+ _context7.prev = 0;
541
+ _context7.next = 3;
542
+ return this.Api.userinfo(this.OAuthToken.access_token);
543
+ case 3:
544
+ response = _context7.sent;
545
+ _context7.next = 12;
546
+ break;
547
+ case 6:
548
+ _context7.prev = 6;
549
+ _context7.t0 = _context7["catch"](0);
550
+ console.error("Failed to update user info", _context7.t0);
551
+ this.UserInfo = null;
552
+ if (this.App.Store != null) {
553
+ this.App.Store.dispatch({
554
+ type: _actions.types.AUTH_USERINFO,
555
+ payload: this.UserInfo
556
+ });
557
+ }
558
+ return _context7.abrupt("return", false);
559
+ case 12:
560
+ this.UserInfo = response.data;
561
+ this.SessionExpiration = (_response$data = response.data) === null || _response$data === void 0 ? void 0 : _response$data.exp;
562
+ if (this.App.Store != null) {
563
+ this.App.Store.dispatch({
564
+ type: _actions.types.AUTH_USERINFO,
565
+ payload: this.UserInfo
566
+ });
567
+ }
568
+
569
+ /** Check for TenantService and pass tenants list obtained from userinfo */
570
+ availableTenants = this.UserInfo.tenants;
571
+ if (!this.App.Services.TenantService) {
572
+ _context7.next = 19;
573
+ break;
574
+ }
575
+ _context7.next = 19;
576
+ return this.App.Services.TenantService.setTenants(availableTenants, this._getAuthorizedTenant(this.UserInfo));
577
+ case 19:
578
+ return _context7.abrupt("return", true);
579
+ case 20:
580
+ case "end":
581
+ return _context7.stop();
582
+ }
583
+ }, _callee7, this, [[0, 6]]);
584
+ }));
585
+ function updateUserInfo() {
586
+ return _updateUserInfo.apply(this, arguments);
587
+ }
588
+ return updateUserInfo;
589
+ }()
590
+ }, {
591
+ key: "_updateToken",
592
+ value: function () {
593
+ var _updateToken2 = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee8(authorization_code) {
594
+ var response;
595
+ return _regenerator["default"].wrap(function _callee8$(_context8) {
596
+ while (1) switch (_context8.prev = _context8.next) {
597
+ case 0:
598
+ _context8.prev = 0;
599
+ _context8.next = 3;
600
+ return this.Api.token_authorization_code(authorization_code, this.RedirectURL);
601
+ case 3:
602
+ response = _context8.sent;
603
+ _context8.next = 10;
604
+ break;
605
+ case 6:
606
+ _context8.prev = 6;
607
+ _context8.t0 = _context8["catch"](0);
608
+ console.error("Failed to update token", _context8.t0);
609
+ return _context8.abrupt("return", false);
610
+ case 10:
611
+ this.OAuthToken = response.data;
612
+ sessionStorage.setItem('SeaCatOAuth2Token', JSON.stringify(response.data));
613
+ return _context8.abrupt("return", true);
614
+ case 13:
615
+ case "end":
616
+ return _context8.stop();
617
+ }
618
+ }, _callee8, this, [[0, 6]]);
619
+ }));
620
+ function _updateToken(_x8) {
621
+ return _updateToken2.apply(this, arguments);
622
+ }
623
+ return _updateToken;
624
+ }()
625
+ }, {
626
+ key: "_getAuthorizedTenant",
627
+ value: function _getAuthorizedTenant(userInfo) {
628
+ /*
629
+ Return the authorized tenant ID from userinfo.
630
+ Pick the first one if there are multiple tenants.
631
+ */
632
+ if (userInfo !== null && userInfo !== void 0 && userInfo.resources) {
633
+ for (var tenantId in userInfo.resources) {
634
+ if (tenantId != '*' && userInfo.resources.hasOwnProperty(tenantId)) {
635
+ return tenantId;
636
+ }
637
+ }
638
+ } else {
639
+ return undefined;
640
+ }
641
+ }
642
+
643
+ // Loop validating session expiration
644
+ }, {
645
+ key: "_startSessionExpirationValidation",
646
+ value: function () {
647
+ var _startSessionExpirationValidation2 = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee10() {
648
+ var _this5 = this;
649
+ var warningDisplayed, _validateSession;
650
+ return _regenerator["default"].wrap(function _callee10$(_context10) {
651
+ while (1) switch (_context10.prev = _context10.next) {
652
+ case 0:
653
+ if (this.SessionExpiration) {
654
+ _context10.next = 3;
655
+ break;
656
+ }
657
+ console.warn("Session expiration is not set.");
658
+ return _context10.abrupt("return");
659
+ case 3:
660
+ warningDisplayed = false; // Tracks if the "about to expire" warning has been shown
661
+ _validateSession = /*#__PURE__*/function () {
662
+ var _ref3 = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee9() {
663
+ var currentTime, timeRemaining, isUserInfoUpdated;
664
+ return _regenerator["default"].wrap(function _callee9$(_context9) {
665
+ while (1) switch (_context9.prev = _context9.next) {
666
+ case 0:
667
+ currentTime = Date.now() / 1000; // Convert milliseconds to seconds
668
+ timeRemaining = _this5.SessionExpiration - currentTime; // Time difference for triggering "about to expire" warning
669
+ // Prevent glitches on very large time remaining values
670
+ if (timeRemaining >= Math.pow(2, 31)) {
671
+ // Set timeout to maximum allowed value
672
+ timeRemaining = Math.pow(2, 31) - 1;
673
+ }
674
+
675
+ // If remaining time is between 1 and 60s, repetitivelly ask for userInfo and trigger "about to expire" warning
676
+ if (!(timeRemaining <= 60 && timeRemaining > 0)) {
677
+ _context9.next = 7;
678
+ break;
679
+ }
680
+ if (!warningDisplayed) {
681
+ _this5.App.addAlert("info", "General|Your session will expire soon", 30, true);
682
+ warningDisplayed = true; // Mark the warning as displayed
683
+ }
684
+ _context9.next = 7;
685
+ return _this5.updateUserInfo();
686
+ case 7:
687
+ if (!(_this5.SessionExpiration <= currentTime)) {
688
+ _context9.next = 17;
689
+ break;
690
+ }
691
+ _context9.next = 10;
692
+ return _this5.updateUserInfo();
693
+ case 10:
694
+ isUserInfoUpdated = _context9.sent;
695
+ if (isUserInfoUpdated) {
696
+ _context9.next = 17;
697
+ break;
698
+ }
699
+ // Stop further checks
700
+ clearTimeout(_this5.sessionValidationInterval);
701
+ _this5.sessionValidationInterval = null;
702
+ _this5.App.addAlert("info", "ASABAuthModule|Your session has expired.", 3600 * 1000, true, function (alert, store) {
703
+ return /*#__PURE__*/_react["default"].createElement(_SessionExpirationAlert.SessionExpirationAlert, {
704
+ alert: alert,
705
+ store: store
706
+ });
707
+ });
708
+ // Disable UI elements
709
+ if (_this5.App.Store) {
710
+ _this5.App.Store.dispatch({
711
+ type: _actions.types.AUTH_SESSION_EXPIRATION,
712
+ sessionExpired: true
713
+ });
714
+
715
+ // Disable UI elements
716
+ (0, _toConsumableArray2["default"])(document.querySelectorAll('#app-sidebar .nav-link, [class^="btn"]:not(.alert-button), [class*=" btn"]:not(.alert-button), .btn-group a, .page-item, input, select')).forEach(function (i) {
717
+ i.classList.add("disabled");
718
+ i.setAttribute("disabled", "");
719
+ });
720
+
721
+ // Reload on navigation actions
722
+ window.addEventListener("popstate", function () {
723
+ window.location.reload();
724
+ });
725
+ }
726
+ return _context9.abrupt("return");
727
+ case 17:
728
+ // Re-trigger validation after 10 seconds
729
+ _this5.sessionValidationInterval = setTimeout(_validateSession, 10000);
730
+ case 18:
731
+ case "end":
732
+ return _context9.stop();
733
+ }
734
+ }, _callee9);
735
+ }));
736
+ return function validateSession() {
737
+ return _ref3.apply(this, arguments);
738
+ };
739
+ }(); // Start the first validation cycle
740
+ _validateSession();
741
+ case 6:
742
+ case "end":
743
+ return _context10.stop();
744
+ }
745
+ }, _callee10, this);
746
+ }));
747
+ function _startSessionExpirationValidation() {
748
+ return _startSessionExpirationValidation2.apply(this, arguments);
749
+ }
750
+ return _startSessionExpirationValidation;
751
+ }() // Stop looping on session expiration validation
752
+ }, {
753
+ key: "_stopSessionExpirationValidation",
754
+ value: function _stopSessionExpirationValidation() {
755
+ if (this.sessionValidationInterval) {
756
+ clearInterval(this.sessionValidationInterval);
757
+ this.sessionValidationInterval = null;
758
+ }
759
+ }
760
+ }]);
761
+ }(_asab_webui_components.Module);