@pega/react-sdk-overrides 8.8.21 → 8.23.11-debug

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 (128) hide show
  1. package/lib/designSystemExtension/AlertBanner/AlertBanner.tsx +9 -13
  2. package/lib/designSystemExtension/Banner/Banner.tsx +1 -12
  3. package/lib/designSystemExtension/CaseSummaryFields/CaseSummaryFields.tsx +10 -15
  4. package/lib/designSystemExtension/DetailsFields/DetailsFields.tsx +11 -10
  5. package/lib/designSystemExtension/FieldGroup/FieldGroup.tsx +3 -10
  6. package/lib/designSystemExtension/FieldGroupList/FieldGroupList.tsx +3 -11
  7. package/lib/designSystemExtension/FieldValueList/FieldValueList.tsx +3 -11
  8. package/lib/designSystemExtension/Operator/Operator.tsx +12 -16
  9. package/lib/designSystemExtension/Pulse/Pulse.tsx +7 -11
  10. package/lib/designSystemExtension/WssQuickCreate/WssQuickCreate.tsx +1 -10
  11. package/lib/field/AutoComplete/AutoComplete.tsx +18 -37
  12. package/lib/field/CancelAlert/CancelAlert.tsx +4 -9
  13. package/lib/field/Checkbox/Checkbox.tsx +16 -39
  14. package/lib/field/Currency/Currency.tsx +15 -23
  15. package/lib/field/Currency/currency-utils.ts +5 -1
  16. package/lib/field/Date/Date.tsx +15 -22
  17. package/lib/field/DateTime/DateTime.tsx +14 -25
  18. package/lib/field/Decimal/Decimal.tsx +14 -25
  19. package/lib/field/Dropdown/Dropdown.tsx +26 -30
  20. package/lib/field/Email/Email.tsx +9 -17
  21. package/lib/field/Integer/Integer.tsx +7 -15
  22. package/lib/field/Percentage/Percentage.tsx +7 -15
  23. package/lib/field/Phone/Phone.tsx +11 -19
  24. package/lib/field/RadioButtons/RadioButtons.tsx +37 -25
  25. package/lib/field/SemanticLink/SemanticLink.tsx +25 -26
  26. package/lib/field/TextArea/TextArea.tsx +5 -14
  27. package/lib/field/TextContent/TextContent.tsx +1 -10
  28. package/lib/field/TextInput/TextInput.tsx +6 -15
  29. package/lib/field/Time/Time.tsx +27 -22
  30. package/lib/field/URL/URL.tsx +8 -16
  31. package/lib/field/UserReference/UserReference.tsx +60 -50
  32. package/lib/helpers/attachmentHelpers.ts +4 -4
  33. package/lib/helpers/auth.js +397 -741
  34. package/lib/helpers/authManager.js +634 -0
  35. package/lib/helpers/case-utils.tsx +9 -8
  36. package/lib/helpers/common-utils.ts +1 -1
  37. package/lib/helpers/config_access.js +73 -0
  38. package/lib/helpers/date-format-utils.ts +1 -1
  39. package/lib/helpers/event-utils.ts +1 -1
  40. package/lib/helpers/formatters/Currency.ts +11 -11
  41. package/lib/helpers/formatters/CurrencyMap.ts +5 -8
  42. package/lib/helpers/formatters/Date.ts +1 -1
  43. package/lib/helpers/formatters/common.ts +6 -2
  44. package/lib/helpers/formatters/index.ts +3 -3
  45. package/lib/helpers/simpleTableHelpers.ts +7 -7
  46. package/lib/helpers/state-utils.tsx +3 -0
  47. package/lib/helpers/template-utils.ts +6 -3
  48. package/lib/helpers/versionHelpers.ts +3 -0
  49. package/lib/infra/ActionButtons/ActionButtons.tsx +19 -9
  50. package/lib/infra/Assignment/Assignment.tsx +28 -21
  51. package/lib/infra/AssignmentCard/AssignmentCard.tsx +19 -15
  52. package/lib/infra/Containers/FlowContainer/FlowContainer.tsx +58 -57
  53. package/lib/infra/Containers/FlowContainer/helpers.ts +3 -0
  54. package/lib/infra/Containers/ModalViewContainer/ModalViewContainer.tsx +19 -14
  55. package/lib/infra/Containers/ViewContainer/ViewContainer.tsx +25 -14
  56. package/lib/infra/DashboardFilter/DashboardFilter.tsx +21 -13
  57. package/lib/infra/DashboardFilter/filterUtils.tsx +1 -1
  58. package/lib/infra/DeferLoad/DeferLoad.tsx +20 -14
  59. package/lib/infra/ErrorBoundary/ErrorBoundary.tsx +14 -10
  60. package/lib/infra/MultiStep/MultiStep.tsx +22 -22
  61. package/lib/infra/NavBar/NavBar.tsx +21 -14
  62. package/lib/infra/Reference/Reference.tsx +18 -13
  63. package/lib/infra/Region/Region.tsx +6 -8
  64. package/lib/infra/RootContainer/RootContainer.tsx +25 -16
  65. package/lib/infra/Stages/Stages.tsx +8 -10
  66. package/lib/infra/VerticalTabs/LeftAlignVerticalTabs/LeftAlignVerticalTabs.tsx +1 -8
  67. package/lib/infra/VerticalTabs/VerticalTabs/VerticalTabs.tsx +12 -12
  68. package/lib/infra/View/View.tsx +22 -21
  69. package/lib/template/AppShell/AppShell.tsx +25 -36
  70. package/lib/template/BannerPage/BannerPage.tsx +31 -26
  71. package/lib/template/CaseSummary/CaseSummary.tsx +8 -15
  72. package/lib/template/CaseView/CaseView.tsx +25 -24
  73. package/lib/template/CaseViewActionsMenu/CaseViewActionsMenu.tsx +19 -10
  74. package/lib/template/Confirmation/Confirmation.tsx +53 -27
  75. package/lib/template/DataReference/DataReference.tsx +52 -48
  76. package/lib/template/DefaultForm/DefaultForm.tsx +12 -14
  77. package/lib/template/Details/Details/Details.tsx +17 -16
  78. package/lib/template/Details/DetailsSubTabs/DetailsSubTabs.tsx +16 -13
  79. package/lib/template/Details/DetailsThreeColumn/DetailsThreeColumn.tsx +18 -19
  80. package/lib/template/Details/DetailsTwoColumn/DetailsTwoColumn.tsx +18 -20
  81. package/lib/template/FieldGroupTemplate/FieldGroupTemplate.tsx +28 -22
  82. package/lib/template/InlineDashboard/InlineDashboard.tsx +7 -11
  83. package/lib/template/InlineDashboardPage/InlineDashboardPage.tsx +17 -19
  84. package/lib/template/ListPage/ListPage.tsx +13 -14
  85. package/lib/template/ListView/ListView.tsx +186 -189
  86. package/lib/template/ListView/utils.ts +23 -170
  87. package/lib/template/MultiReferenceReadOnly/MultiReferenceReadOnly.tsx +19 -10
  88. package/lib/template/NarrowWide/NarrowWide/NarrowWide.tsx +1 -16
  89. package/lib/template/NarrowWide/NarrowWideDetails/NarrowWideDetails.tsx +18 -19
  90. package/lib/template/NarrowWide/NarrowWideForm/NarrowWideForm.tsx +1 -9
  91. package/lib/template/NarrowWide/NarrowWidePage/NarrowWidePage.tsx +17 -17
  92. package/lib/template/OneColumn/OneColumn/OneColumn.tsx +7 -8
  93. package/lib/template/OneColumn/OneColumnPage/OneColumnPage.tsx +10 -10
  94. package/lib/template/OneColumn/OneColumnTab/OneColumnTab.tsx +7 -5
  95. package/lib/template/PromotedFilters/PromotedFilters.tsx +14 -16
  96. package/lib/template/SimpleTable/SimpleTable/SimpleTable.tsx +8 -102
  97. package/lib/template/SimpleTable/SimpleTableManual/SimpleTableManual.tsx +7 -24
  98. package/lib/template/SimpleTable/SimpleTableSelect/SimpleTableSelect.tsx +33 -23
  99. package/lib/template/SingleReferenceReadOnly/SingleReferenceReadOnly.tsx +36 -34
  100. package/lib/template/SubTabs/SubTabs.tsx +11 -10
  101. package/lib/template/SubTabs/tabUtils.ts +4 -0
  102. package/lib/template/TwoColumn/TwoColumn/TwoColumn.tsx +15 -10
  103. package/lib/template/TwoColumn/TwoColumnPage/TwoColumnPage.tsx +10 -10
  104. package/lib/template/TwoColumn/TwoColumnTab/TwoColumnTab.tsx +12 -10
  105. package/lib/template/WideNarrow/WideNarrow/WideNarrow.tsx +3 -17
  106. package/lib/template/WideNarrow/WideNarrowDetails/WideNarrowDetails.tsx +25 -35
  107. package/lib/template/WideNarrow/WideNarrowForm/WideNarrowForm.tsx +1 -7
  108. package/lib/template/WideNarrow/WideNarrowPage/WideNarrowPage.tsx +17 -15
  109. package/lib/template/WssNavBar/WssNavBar.tsx +1 -18
  110. package/lib/widget/AppAnnouncement/AppAnnouncement.tsx +21 -13
  111. package/lib/widget/Attachment/Attachment.tsx +16 -28
  112. package/lib/widget/CaseHistory/CaseHistory.tsx +10 -12
  113. package/lib/widget/FileUtility/ActionButtonsForFileUtil/ActionButtonsForFileUtil.tsx +1 -13
  114. package/lib/widget/FileUtility/FileUtility/FileUtility.tsx +22 -35
  115. package/lib/widget/Followers/Followers.tsx +11 -10
  116. package/lib/widget/QuickCreate/QuickCreate.tsx +5 -11
  117. package/lib/widget/SummaryItem/SummaryItem.tsx +1 -11
  118. package/lib/widget/SummaryList/SummaryList.tsx +3 -17
  119. package/lib/widget/ToDo/ToDo.tsx +105 -62
  120. package/package.json +1 -1
  121. package/lib/designSystemExtension/RichTextEditor/RichTextEditor.tsx +0 -121
  122. package/lib/designSystemExtension/RichTextEditor/index.tsx +0 -1
  123. package/lib/field/RichText/RichText.tsx +0 -93
  124. package/lib/field/RichText/index.tsx +0 -1
  125. package/lib/field/ScalarList/ScalarList.tsx +0 -64
  126. package/lib/field/ScalarList/config-ext.json +0 -8
  127. package/lib/field/ScalarList/index.tsx +0 -1
  128. package/lib/helpers/authManager.ts +0 -933
@@ -0,0 +1,634 @@
1
+ // This file wraps various calls related to logging in, logging out, etc.
2
+ // that use the auth.html/auth.js to do the work of logging in via OAuth 2.0.
3
+
4
+ import { getSdkConfig, SdkConfigAccess } from './config_access';
5
+ import PegaAuth from './auth';
6
+
7
+ // eslint-disable-next-line import/no-mutable-exports
8
+ export let gbLoggedIn = sessionStorage.getItem('rsdk_AH') !== null;
9
+ // eslint-disable-next-line import/no-mutable-exports
10
+ export let gbLoginInProgress = sessionStorage.getItem("rsdk_loggingIn") !== null;
11
+ // other sessionStorage items: rsdk_appName
12
+
13
+ // will store the PegaAuth instance
14
+ let authMgr = null;
15
+ // Since this variable is loaded in a separate instance in the popup scenario, use storage to coordinate across the two
16
+ let usePopupForRestOfSession = sessionStorage.getItem("rsdk_popup") === "1";
17
+ let gbC11NBootstrapInProgress = false;
18
+ // Some non Pega OAuth 2.0 Authentication in use (Basic or Custom for service package)
19
+ let gbCustomAuth = false;
20
+
21
+ /*
22
+ * Set to use popup experience for rest of session
23
+ */
24
+ const forcePopupForReauths = ( bForce ) => {
25
+ if( bForce ) {
26
+ sessionStorage.setItem("rsdk_popup", "1");
27
+ usePopupForRestOfSession = true;
28
+ } else {
29
+ sessionStorage.removeItem("rsdk_popup");
30
+ usePopupForRestOfSession = false;
31
+ }
32
+ };
33
+
34
+ const setNoInitialRedirect = (bNoInitialRedirect ) => {
35
+ if( bNoInitialRedirect ) {
36
+ forcePopupForReauths(true);
37
+ sessionStorage.setItem("rsdk_noRedirect", "1");
38
+ } else {
39
+ sessionStorage.removeItem("rsdk_noRedirect");
40
+ }
41
+ };
42
+
43
+ const isLoginExpired = () => {
44
+ let bExpired = true;
45
+ const sLoginStart = sessionStorage.getItem("rsdk_loggingIn");
46
+ if( sLoginStart !== null ) {
47
+ const currTime = Date.now();
48
+ bExpired = currTime - parseInt(sLoginStart, 10) > 60000;
49
+ }
50
+ return bExpired;
51
+ };
52
+
53
+ /**
54
+ * Clean up any web storage allocated for the user session.
55
+ */
56
+ const clearAuthMgr = (bFullReauth=false) => {
57
+ // Remove any local storage for the user
58
+ if( !gbCustomAuth ) {
59
+ sessionStorage.removeItem('rsdk_AH');
60
+ }
61
+ if( !bFullReauth ) {
62
+ sessionStorage.removeItem("rsdk_CI");
63
+ }
64
+ sessionStorage.removeItem("rsdk_TI");
65
+ sessionStorage.removeItem("rsdk_UI");
66
+ sessionStorage.removeItem("rsdk_loggingIn");
67
+ gbLoggedIn = false;
68
+ gbLoginInProgress = false;
69
+ forcePopupForReauths(bFullReauth);
70
+ // Not removing the authMgr structure itself...as it can be leveraged on next login
71
+ };
72
+
73
+ export const authNoRedirect = () => {
74
+ return sessionStorage.getItem("rsdk_noRedirect") === "1";
75
+ };
76
+
77
+ /**
78
+ * Initialize OAuth config structure members and create authMgr instance
79
+ * bInit - governs whether to create new sessionStorage or load existing one
80
+ */
81
+ const initOAuth = (bInit) => {
82
+ return getSdkConfig().then( sdkConfig => {
83
+ const sdkConfigAuth = sdkConfig.authConfig;
84
+ const sdkConfigServer = sdkConfig.serverConfig;
85
+ let pegaUrl = sdkConfigServer.infinityRestServerUrl;
86
+ const bNoInitialRedirect = authNoRedirect();
87
+
88
+ // Construct default OAuth endpoints (if not explicitly specified)
89
+ if (pegaUrl) {
90
+ // Cope with trailing slash being present
91
+ if (!pegaUrl.endsWith('/')) {
92
+ pegaUrl += '/';
93
+ }
94
+ if (!sdkConfigAuth.authorize) {
95
+ sdkConfigAuth.authorize = `${pegaUrl}PRRestService/oauth2/v1/authorize`;
96
+ }
97
+ if (!sdkConfigAuth.token) {
98
+ sdkConfigAuth.token = `${pegaUrl}PRRestService/oauth2/v1/token`;
99
+ }
100
+ if (!sdkConfigAuth.revoke) {
101
+ sdkConfigAuth.revoke = `${pegaUrl}PRRestService/oauth2/v1/revoke`;
102
+ }
103
+ if( !sdkConfigAuth.redirectUri ) {
104
+ sdkConfigAuth.redirectUri = `${window.location.origin}${window.location.pathname}`;
105
+ }
106
+ if (!sdkConfigAuth.userinfo) {
107
+ const appAliasSeg = sdkConfigServer.appAlias ? `app/${sdkConfigServer.appAlias}/` : '';
108
+ sdkConfigAuth.userinfo = `${pegaUrl}${appAliasSeg}api/oauthclients/v1/userinfo/JSON`;
109
+ }
110
+ }
111
+ // Auth service alias
112
+ if( !sdkConfigAuth.authService) {
113
+ sdkConfigAuth.authService = "pega";
114
+ }
115
+
116
+ // Construct path to auth.html (used for case when not doing a main window redirect)
117
+ let sNoMainRedirectUri=sdkConfigAuth.redirectUri;
118
+ const nLastPathSep = sNoMainRedirectUri.lastIndexOf("/");
119
+ sNoMainRedirectUri = nLastPathSep !== -1 ? `${sNoMainRedirectUri.substring(0,nLastPathSep+1)}auth.html` : `${sNoMainRedirectUri}/auth.html`;
120
+
121
+ const authConfig = {
122
+ clientId: bNoInitialRedirect ? sdkConfigAuth.mashupClientId : sdkConfigAuth.portalClientId,
123
+ authorizeUri: sdkConfigAuth.authorize,
124
+ tokenUri: sdkConfigAuth.token,
125
+ revokeUri: sdkConfigAuth.revoke,
126
+ userinfoUri: sdkConfigAuth.userinfo,
127
+ redirectUri: bNoInitialRedirect || usePopupForRestOfSession
128
+ ? sNoMainRedirectUri
129
+ : sdkConfigAuth.redirectUri,
130
+ authService: sdkConfigAuth.authService,
131
+ appAlias: sdkConfigServer.appAlias || '',
132
+ useLocking: true
133
+ };
134
+ // If no clientId is specified assume not OAuth but custom auth
135
+ if( !authConfig.clientId ) {
136
+ gbCustomAuth = true;
137
+ return;
138
+ }
139
+ if( 'silentTimeout' in sdkConfigAuth ) {
140
+ authConfig.silentTimeout = sdkConfigAuth.silentTimeout;
141
+ }
142
+ if( bNoInitialRedirect && sdkConfigAuth.mashupUserIdentifier && sdkConfigAuth.mashupPassword ) {
143
+ authConfig.userIdentifier = sdkConfigAuth.mashupUserIdentifier;
144
+ authConfig.password = sdkConfigAuth.mashupPassword;
145
+ }
146
+ if( 'iframeLoginUI' in sdkConfigAuth ){
147
+ authConfig.iframeLoginUI = sdkConfigAuth.iframeLoginUI.toString().toLowerCase() === 'true';
148
+ }
149
+
150
+ // Check if sessionStorage exists (and if so if for same authorize endpoint). Otherwise, assume
151
+ // sessionStorage is out of date (user just edited endpoints). Else, logout required to clear
152
+ // sessionStorage and get other endpoints updates.
153
+ // Doing this as sessionIndex might have been added to this storage structure
154
+ let sSI = sessionStorage.getItem("rsdk_CI");
155
+ if( sSI ) {
156
+ try {
157
+ const oSI = JSON.parse(sSI);
158
+ const aProps = ['authorizeUri', 'appAlias', 'clientId', 'authService', 'userIdentifier'];
159
+ for( let i = 0; i < aProps.length; i += 1 ) {
160
+ const prop = aProps[i];
161
+ const currValue = oSI[prop];
162
+ const newValue = authConfig[prop];
163
+ if( currValue !== newValue ) {
164
+ // eslint-disable-next-line no-console
165
+ console.warn(`Clearing credentials due to mismatch for property: ${prop};` +
166
+ `currValue (${currValue}) does not match new desired value (${newValue})`);
167
+ clearAuthMgr();
168
+ sSI = null;
169
+ break;
170
+ }
171
+ }
172
+ } catch(e) {
173
+ // do nothing
174
+ }
175
+ }
176
+
177
+ if( !sSI || bInit ) {
178
+ sessionStorage.setItem('rsdk_CI', JSON.stringify(authConfig));
179
+ }
180
+ authMgr = new PegaAuth('rsdk_CI');
181
+ });
182
+ };
183
+
184
+ const getAuthMgr = ( bInit ) => {
185
+ return new Promise( (resolve) => {
186
+ let idNextCheck = null;
187
+ const fnCheckForAuthMgr = () => {
188
+ if( PegaAuth && !authMgr ) {
189
+ initOAuth( bInit );
190
+ }
191
+ if(authMgr) {
192
+ if( idNextCheck ) {
193
+ clearInterval(idNextCheck);
194
+ }
195
+ return resolve(authMgr);
196
+ }
197
+ }
198
+ fnCheckForAuthMgr();
199
+ idNextCheck = setInterval(fnCheckForAuthMgr, 10);
200
+ });
201
+ };
202
+
203
+ export const sdkGetAuthHeader = () => {
204
+ return sessionStorage.getItem("rsdk_AH");
205
+ };
206
+
207
+ /**
208
+ * Initiate the process to get the Constellation bootstrap shell loaded and initialized
209
+ * @param {Object} authConfig
210
+ * @param {Object} tokenInfo
211
+ * @param {Function} authTokenUpdated - callback invoked when Constellation JS Engine silently updates
212
+ * an expired access_token
213
+ * @param {Function} fnReauth - callback invoked when a full or custom reauth is needed
214
+ */
215
+ const constellationInit = (authConfig, tokenInfo, authTokenUpdated, fnReauth) => {
216
+ const constellationBootConfig = {};
217
+ const sdkConfigServer = SdkConfigAccess.getSdkConfigServer();
218
+
219
+ // Set up constellationConfig with data that bootstrapWithAuthHeader expects
220
+ constellationBootConfig.customRendering = true;
221
+ constellationBootConfig.restServerUrl = sdkConfigServer.infinityRestServerUrl;
222
+ // NOTE: Needs a trailing slash! So add one if not provided
223
+ if( !sdkConfigServer.sdkContentServerUrl.endsWith('/') ) {
224
+ sdkConfigServer.sdkContentServerUrl = `${sdkConfigServer.sdkContentServerUrl}/`;
225
+ }
226
+ constellationBootConfig.staticContentServerUrl = `${sdkConfigServer.sdkContentServerUrl}constellation/`;
227
+ if( !constellationBootConfig.staticContentServerUrl.endsWith('/') ) {
228
+ constellationBootConfig.staticContentServerUrl = `${constellationBootConfig.staticContentServerUrl}/`;
229
+ }
230
+ // If appAlias specified, use it
231
+ if( sdkConfigServer.appAlias ) {
232
+ constellationBootConfig.appAlias = sdkConfigServer.appAlias;
233
+ }
234
+
235
+ if( tokenInfo ) {
236
+ // Pass in auth info to Constellation
237
+ constellationBootConfig.authInfo = {
238
+ authType: "OAuth2.0",
239
+ tokenInfo,
240
+ // Set whether we want constellation to try to do a full re-Auth or not ()
241
+ // true doesn't seem to be working in SDK scenario so always passing false for now
242
+ popupReauth: false /* !authNoRedirect() */,
243
+ client_id: authConfig.clientId,
244
+ authentication_service: authConfig.authService,
245
+ redirect_uri: authConfig.redirectUri,
246
+ endPoints: {
247
+ authorize: authConfig.authorizeUri,
248
+ token: authConfig.tokenUri,
249
+ revoke: authConfig.revokeUri
250
+ },
251
+ // TODO: setup callback so we can update own storage
252
+ onTokenRetrieval: authTokenUpdated
253
+ }
254
+ } else {
255
+ constellationBootConfig.authorizationHeader = sdkGetAuthHeader();
256
+ }
257
+
258
+
259
+ // Turn off dynamic load components (should be able to do it here instead of after load?)
260
+ constellationBootConfig.dynamicLoadComponents = false;
261
+
262
+ if( gbC11NBootstrapInProgress ) {
263
+ return;
264
+ } else {
265
+ gbC11NBootstrapInProgress = true;
266
+ }
267
+
268
+ // Note that staticContentServerUrl already ends with a slash (see above), so no slash added.
269
+ // In order to have this import succeed and to have it done with the webpackIgnore magic comment tag.
270
+ // See: https://webpack.js.org/api/module-methods/
271
+ import(/* webpackIgnore: true */ `${constellationBootConfig.staticContentServerUrl}bootstrap-shell.js`).then((bootstrapShell) => {
272
+ // NOTE: once this callback is done, we lose the ability to access loadMashup.
273
+ // So, create a reference to it
274
+ window.myLoadMashup = bootstrapShell.loadMashup;
275
+ window.myLoadPortal = bootstrapShell.loadPortal;
276
+ window.myLoadDefaultPortal = bootstrapShell.loadDefaultPortal;
277
+
278
+ bootstrapShell.bootstrapWithAuthHeader(constellationBootConfig, 'pega-root').then(() => {
279
+ // eslint-disable-next-line no-console
280
+ console.log('Bootstrap successful!');
281
+ gbC11NBootstrapInProgress = false;
282
+
283
+ // Setup listener for the reauth event
284
+ if( tokenInfo ) {
285
+ PCore.getPubSubUtils().subscribe(PCore.getConstants().PUB_SUB_EVENTS.EVENT_FULL_REAUTH, fnReauth, "authFullReauth");
286
+ } else {
287
+ // customReauth event introduced with 8.8
288
+ const sEvent = PCore.getConstants().PUB_SUB_EVENTS.EVENT_CUSTOM_REAUTH;
289
+ if( sEvent ) {
290
+ PCore.getPubSubUtils().subscribe(sEvent, fnReauth, "doReauth");
291
+ }
292
+ }
293
+
294
+ // Fire SdkConstellationReady event so bridge and app route can do expected post PCore initializations
295
+ const event = new CustomEvent('SdkConstellationReady', {});
296
+ document.dispatchEvent(event);
297
+ })
298
+ .catch( e => {
299
+ // Assume error caught is because token is not valid and attempt a full reauth
300
+ // eslint-disable-next-line no-console
301
+ console.error(`Constellation JS Engine bootstrap failed. ${e}`);
302
+ gbC11NBootstrapInProgress = false;
303
+ fnReauth();
304
+ })
305
+ });
306
+ /* Ends here */
307
+ };
308
+
309
+ export const updateLoginStatus = () => {
310
+ const sAuthHdr = sdkGetAuthHeader();
311
+ gbLoggedIn = sAuthHdr && sAuthHdr.length > 0;
312
+ };
313
+
314
+ const getCurrentTokens = () => {
315
+ let tokens = null;
316
+ const sTI = sessionStorage.getItem('rsdk_TI');
317
+ if(sTI) {
318
+ try {
319
+ tokens = JSON.parse(sTI);
320
+ } catch(e) {
321
+ tokens = null;
322
+ }
323
+ }
324
+ return tokens;
325
+ };
326
+
327
+ const fireTokenAvailable = (token, bLoadC11N=true) => {
328
+ if( !token ) {
329
+ // This is used on page reload to load the token from sessionStorage and carry on
330
+ token = getCurrentTokens();
331
+ if( !token ) {
332
+ return;
333
+ }
334
+ }
335
+
336
+ sessionStorage.setItem('rsdk_AH', `${token.token_type} ${token.access_token}`);
337
+ updateLoginStatus();
338
+
339
+ // gbLoggedIn is getting updated in updateLoginStatus
340
+ gbLoggedIn = true;
341
+ gbLoginInProgress = false;
342
+ sessionStorage.removeItem("rsdk_loggingIn");
343
+ forcePopupForReauths(true);
344
+
345
+ const sSI = sessionStorage.getItem("rsdk_CI");
346
+ let authConfig = null;
347
+ if( sSI ) {
348
+ try {
349
+ authConfig = JSON.parse(sSI);
350
+ } catch(e) {
351
+ // do nothing
352
+ }
353
+ }
354
+
355
+ if( !window.PCore && bLoadC11N ) {
356
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
357
+ constellationInit( authConfig, token, authTokenUpdated, authFullReauth );
358
+ }
359
+
360
+ /*
361
+ // Create and dispatch the SdkLoggedIn event to trigger constellationInit
362
+ const event = new CustomEvent('SdkLoggedIn', { detail: { authConfig, tokenInfo: token } });
363
+ document.dispatchEvent(event);
364
+ */
365
+ };
366
+
367
+ const processTokenOnLogin = ( token, bLoadC11N=true ) => {
368
+ sessionStorage.setItem("rsdk_TI", JSON.stringify(token));
369
+ if( window.PCore ) {
370
+ window.PCore.getAuthUtils().setTokens(token);
371
+ } else {
372
+ fireTokenAvailable(token, bLoadC11N);
373
+ }
374
+ };
375
+
376
+ const updateRedirectUri = (aMgr, sRedirectUri) => {
377
+ const sSI = sessionStorage.getItem("rsdk_CI");
378
+ let authConfig = null;
379
+ if( sSI ) {
380
+ try {
381
+ authConfig = JSON.parse(sSI);
382
+ } catch(e) {
383
+ // do nothing
384
+ }
385
+ }
386
+ authConfig.redirectUri = sRedirectUri;
387
+ sessionStorage.setItem("rsdk_CI", JSON.stringify(authConfig));
388
+ aMgr.reloadConfig();
389
+ };
390
+
391
+
392
+ // TODO: Cope with 401 and refresh token if possible (or just hope that it succeeds during login)
393
+ /**
394
+ * Retrieve UserInfo for current authentication service
395
+ */
396
+ export const getUserInfo = (bUseSS=true) => {
397
+ const ssUserInfo = sessionStorage.getItem("rsdk_UI");
398
+ let userInfo = null;
399
+ if( bUseSS && ssUserInfo ) {
400
+ try {
401
+ userInfo = JSON.parse(ssUserInfo);
402
+ return Promise.resolve(userInfo);
403
+ } catch(e) {
404
+ // do nothing
405
+ }
406
+ }
407
+ getAuthMgr(false).then( (aMgr) => {
408
+ const tokenInfo = getCurrentTokens();
409
+ return aMgr.getUserinfo(tokenInfo.access_token).then( data => {
410
+ userInfo = data;
411
+ if( userInfo ) {
412
+ sessionStorage.setItem("rsdk_UI", JSON.stringify(userInfo));
413
+ } else {
414
+ sessionStorage.removeItem("rsdk_UI");
415
+ }
416
+ return Promise.resolve(userInfo);
417
+ });
418
+ });
419
+
420
+ };
421
+
422
+ export const login = (bFullReauth=false) => {
423
+
424
+ if( gbCustomAuth ) return;
425
+
426
+ gbLoginInProgress = true;
427
+ // Needed so a redirect to login screen and back will know we are still in process of logging in
428
+ sessionStorage.setItem("rsdk_loggingIn", `${Date.now()}`);
429
+
430
+ getAuthMgr(!bFullReauth).then( (aMgr) => {
431
+ const bMainRedirect = !authNoRedirect();
432
+ const sdkConfigAuth = SdkConfigAccess.getSdkConfigAuth();
433
+ let sRedirectUri=sdkConfigAuth.redirectUri;
434
+
435
+ // If initial main redirect is OK, redirect to main page, otherwise will authorize in a popup window
436
+ if (bMainRedirect && !bFullReauth) {
437
+ // update redirect uri to be the root
438
+ updateRedirectUri(aMgr, sRedirectUri);
439
+ aMgr.loginRedirect();
440
+ // Don't have token til after the redirect
441
+ return Promise.resolve(undefined);
442
+ } else {
443
+ // Construct path to redirect uri
444
+ const nLastPathSep = sRedirectUri.lastIndexOf("/");
445
+ sRedirectUri = nLastPathSep !== -1 ? `${sRedirectUri.substring(0,nLastPathSep+1)}auth.html` : `${sRedirectUri}/auth.html`;
446
+ // Set redirectUri to static auth.html
447
+ updateRedirectUri(aMgr, sRedirectUri);
448
+ return new Promise( (resolve, reject) => {
449
+ aMgr.login().then(token => {
450
+ processTokenOnLogin(token);
451
+ // getUserInfo();
452
+ resolve(token.access_token);
453
+ }).catch( (e) => {
454
+ gbLoginInProgress = false;
455
+ sessionStorage.removeItem("rsdk_loggingIn");
456
+ // eslint-disable-next-line no-console
457
+ console.log(e);
458
+ reject(e);
459
+ });
460
+ });
461
+ }
462
+ });
463
+
464
+ };
465
+
466
+ export const authRedirectCallback = ( href, fnLoggedInCB=null ) => {
467
+ // Get code from href and swap for token
468
+ const aHrefParts = href.split('?');
469
+ const urlParams = new URLSearchParams(aHrefParts.length>1 ? `?${aHrefParts[1]}` : '');
470
+ const code = urlParams.get("code");
471
+
472
+ getAuthMgr(false).then( (aMgr) => {
473
+ aMgr.getToken(code).then(token => {
474
+ if( token && token.access_token ) {
475
+ processTokenOnLogin(token, false);
476
+ // getUserInfo();
477
+ if( fnLoggedInCB ) {
478
+ fnLoggedInCB( token.access_token );
479
+ }
480
+ }
481
+ });
482
+ });
483
+ };
484
+
485
+ /**
486
+ * Silent or visible login based on login status
487
+ * @param {string} appName - unique name for application route (will be used to clear an session storage for another route)
488
+ * @param {boolean} noMainRedirect - avoid the initial main window redirect that happens in scenarios where it is OK to transition
489
+ * away from the main page
490
+ * @param {boolean} deferLogin - defer logging in (if not already authenticated)
491
+ */
492
+ export const loginIfNecessary = (appName, noMainRedirect=false, deferLogin=false) => {
493
+ // If no initial redirect status of page changed...clearAuthMgr
494
+ const currNoMainRedirect = authNoRedirect();
495
+ const currAppName = sessionStorage.getItem("rsdk_appName");
496
+ if( appName !== currAppName || noMainRedirect !== currNoMainRedirect) {
497
+ clearAuthMgr();
498
+ sessionStorage.setItem("rsdk_appName", appName);
499
+ }
500
+ setNoInitialRedirect(noMainRedirect);
501
+ // If custom auth no need to do any OAuth logic
502
+ if( gbCustomAuth ) {
503
+ if( !window.PCore ) {
504
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
505
+ constellationInit( null, null, null, authCustomReauth );
506
+ }
507
+ return;
508
+ }
509
+
510
+ if( window.location.href.indexOf("?code") !== -1 ) {
511
+ // initialize authMgr
512
+ initOAuth(false);
513
+ return getAuthMgr(false).then(() => {
514
+ authRedirectCallback(window.location.href, ()=> {
515
+ window.location.href = window.location.pathname;
516
+ });
517
+ });
518
+ }
519
+ if( !deferLogin && (!gbLoginInProgress || isLoginExpired()) ) {
520
+ initOAuth(false);
521
+ return getAuthMgr(false).then(() => {
522
+ updateLoginStatus();
523
+ if( gbLoggedIn ) {
524
+ fireTokenAvailable(getCurrentTokens());
525
+ // getUserInfo();
526
+ } else {
527
+ return login();
528
+ }
529
+ });
530
+ }
531
+ };
532
+
533
+ export const getHomeUrl = () => {
534
+ return `${window.location.origin}/`;
535
+ };
536
+
537
+
538
+ export const authIsMainRedirect = () => {
539
+ // Even with main redirect, we want to use it only for the first login (so it doesn't wipe out any state or the reload)
540
+ return !authNoRedirect() && !usePopupForRestOfSession;
541
+ };
542
+
543
+ // Passive update where just session storage is updated so can be used on a window refresh
544
+ export const authTokenUpdated = (tokenInfo ) => {
545
+ sessionStorage.setItem("rsdk_TI", JSON.stringify(tokenInfo));
546
+ };
547
+
548
+ export const logout = () => {
549
+ sessionStorage.removeItem('rsdk_portalName');
550
+ return new Promise((resolve) => {
551
+ const fnClearAndResolve = () => {
552
+ clearAuthMgr();
553
+
554
+ const event = new Event('SdkLoggedOut');
555
+ document.dispatchEvent(event);
556
+
557
+ resolve();
558
+ };
559
+ if( gbCustomAuth ) {
560
+ sessionStorage.removeItem("rsdk_AH");
561
+ fnClearAndResolve();
562
+ return;
563
+ }
564
+ const tokenInfo = getCurrentTokens();
565
+ if( tokenInfo && tokenInfo.access_token ) {
566
+ if( window.PCore ) {
567
+ window.PCore.getAuthUtils().revokeTokens().then(() => {
568
+ fnClearAndResolve();
569
+ }).catch(err => {
570
+ // eslint-disable-next-line no-console
571
+ console.log("Error:",err?.message);
572
+ });
573
+ } else {
574
+ getAuthMgr(false).then( (aMgr) => {
575
+ aMgr.revokeTokens(tokenInfo.access_token, tokenInfo.refresh_token)
576
+ .then(() => {
577
+ // Go to finally
578
+ })
579
+ .finally(() => {
580
+ fnClearAndResolve();
581
+ });
582
+ });
583
+ }
584
+ } else {
585
+ fnClearAndResolve();
586
+ }
587
+ });
588
+ };
589
+
590
+ // Callback routine for custom event to ask for updated tokens
591
+ export const authUpdateTokens = (token) => {
592
+ processTokenOnLogin( token );
593
+ };
594
+
595
+
596
+ // Initiate a full OAuth re-authorization (any refresh token has also expired).
597
+ export const authFullReauth = () => {
598
+ const bHandleHere = true; // Other alternative is to raise an event and have someone else handle it
599
+
600
+ if( bHandleHere ) {
601
+ // Don't want to do a full clear of authMgr as will loose sessionIndex. Rather just clear the tokens
602
+ clearAuthMgr(true);
603
+ login(true);
604
+ } else {
605
+ // Fire the SdkFullReauth event to indicate a new token is needed (PCore.getAuthUtils.setTokens method
606
+ // should be used to communicate the new token to Constellation JS Engine.
607
+ const event = new CustomEvent('SdkFullReauth', { detail: authUpdateTokens });
608
+ document.dispatchEvent(event);
609
+ }
610
+ };
611
+
612
+ // Set the custom authorization header for the SDK (and Constellation JS Engine) to
613
+ // utilize for every DX API request
614
+ export const sdkSetAuthHeader = (authHeader) => {
615
+ // set this within session storage so it survives a browser reload
616
+ if( authHeader ) {
617
+ sessionStorage.setItem("rsdk_AH", authHeader);
618
+ // setAuthorizationHeader method not available til 8.8 so do safety check
619
+ if( window.PCore?.getAuthUtils().setAuthorizationHeader ) {
620
+ window.PCore.getAuthUtils().setAuthorizationHeader(authHeader);
621
+ }
622
+ } else {
623
+ sessionStorage.removeItem("rsdk_AH");
624
+ }
625
+ gbCustomAuth = true;
626
+ };
627
+
628
+ // Initiate a custom re-authorization.
629
+ export const authCustomReauth = () => {
630
+ // Fire the SdkCustomReauth event to indicate a new authHeader is needed. Event listener should invoke sdkSetAuthHeader
631
+ // to communicate the new token to sdk (and Constellation JS Engine)
632
+ const event = new CustomEvent('SdkCustomReauth', { detail: sdkSetAuthHeader });
633
+ document.dispatchEvent(event);
634
+ };
@@ -1,8 +1,7 @@
1
1
  import React from 'react';
2
- import { getComponentFromMap } from '@pega/react-sdk-components/lib/bridge/helpers/sdk_component_map';
2
+ import AlertBanner from '@pega/react-sdk-components/lib/components/designSystemExtension/AlertBanner';
3
3
 
4
- // Remove this and use "real" PCore type once .d.ts is fixed (currently shows 1 error)
5
- declare const PCore: any;
4
+ declare let PCore: any;
6
5
 
7
6
  /**
8
7
  * Function that accepts array of messages as input and group them by their type and returns the resulting object
@@ -25,7 +24,7 @@ function getMessagesGrouped(inputMessages) {
25
24
  const messages = {};
26
25
 
27
26
  if (inputMessages && inputMessages instanceof Array && inputMessages.length > 0) {
28
- inputMessages.forEach((item) => {
27
+ inputMessages.forEach(item => {
29
28
  const { message, type } = item;
30
29
  messages[type] = [...(messages[type] || []), message];
31
30
  });
@@ -41,7 +40,8 @@ function getMessagesGrouped(inputMessages) {
41
40
  * Eg: 'urgent'
42
41
  */
43
42
  function getVariant(type) {
44
- const { BANNER_VARIANT_SUCCESS, BANNER_VARIANT_INFO, BANNER_VARIANT_URGENT, MESSAGES } = PCore.getConstants();
43
+ const { BANNER_VARIANT_SUCCESS, BANNER_VARIANT_INFO, BANNER_VARIANT_URGENT, MESSAGES } =
44
+ PCore.getConstants();
45
45
  const { MESSAGES_TYPE_ERROR, MESSAGES_TYPE_INFO, MESSAGES_TYPE_SUCCESS } = MESSAGES;
46
46
 
47
47
  let variant;
@@ -62,14 +62,13 @@ function getVariant(type) {
62
62
  }
63
63
 
64
64
  function getBanners(config) {
65
- const AlertBanner = getComponentFromMap('AlertBanner');
66
65
  const { target, pageMessages, httpMessages } = config;
67
66
  const { PAGE } = PCore.getConstants();
68
67
  const { clearMessages } = PCore.getMessageManager();
69
68
  const banners: any = [];
70
69
  const groupedPageMessages = getMessagesGrouped(pageMessages);
71
70
 
72
- Object.keys(groupedPageMessages).forEach((type) => {
71
+ Object.keys(groupedPageMessages).forEach(type => {
73
72
  const messagesByType = groupedPageMessages[type];
74
73
  const variant = getVariant(type);
75
74
  const pageMessagesBannerID = `${target}_${PAGE}_${type}`.toLowerCase().replace('/', '_');
@@ -94,7 +93,9 @@ function getBanners(config) {
94
93
  });
95
94
 
96
95
  if (httpMessages && httpMessages.length > 0) {
97
- banners.push(<AlertBanner id="modalViewContainerBanner" variant="urgent" messages={httpMessages} />);
96
+ banners.push(
97
+ <AlertBanner id='modalViewContainerBanner' variant='urgent' messages={httpMessages} />
98
+ );
98
99
  }
99
100
 
100
101
  return banners;
@@ -1,4 +1,4 @@
1
1
  // eslint-disable-next-line import/prefer-default-export
2
- export function isEmptyObject(obj: Object): boolean {
2
+ export function isEmptyObject(obj: Object): Boolean {
3
3
  return Object.keys(obj).length === 0;
4
4
  }