@microsoft/omnichannel-chat-widget 1.8.4-main.cbab5fc → 1.8.4-main.cd79f08
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 +12 -3
- package/lib/cjs/common/Constants.js +2 -0
- package/lib/cjs/common/facades/FacadeChatSDK.js +235 -9
- package/lib/cjs/common/telemetry/TelemetryConstants.js +13 -0
- package/lib/cjs/common/telemetry/loggers/appInsightsLogger.js +7 -7
- package/lib/cjs/common/utils/xssUtils.js +23 -51
- package/lib/cjs/common/utils.js +15 -2
- package/lib/cjs/components/errorboundary/ErrorBoundary.js +2 -1
- package/lib/cjs/components/livechatwidget/LiveChatWidget.js +9 -1
- package/lib/cjs/components/livechatwidget/common/ActivitySubscriber/BotAuthActivitySubscriber.js +23 -6
- package/lib/cjs/components/livechatwidget/common/ChatWidgetEvents.js +1 -0
- package/lib/cjs/components/livechatwidget/common/PersistentConversationHandler.js +9 -0
- package/lib/cjs/components/livechatwidget/common/authHelper.js +44 -4
- package/lib/cjs/components/livechatwidget/common/createAdapter.js +3 -2
- package/lib/cjs/components/livechatwidget/common/liveChatConfigUtils.js +36 -4
- package/lib/cjs/components/livechatwidget/common/startChat.js +31 -14
- package/lib/cjs/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +62 -2
- package/lib/cjs/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +6 -4
- package/lib/cjs/components/proactivechatpanestateful/ProactiveChatPaneStateful.js +0 -1
- package/lib/cjs/components/webchatcontainerstateful/WebChatContainerStateful.js +42 -27
- package/lib/cjs/components/webchatcontainerstateful/common/activityConverters/convertPersistentChatHistoryMessageToActivity.js +117 -16
- package/lib/cjs/components/webchatcontainerstateful/common/defaultStyles/defaultAdaptiveCardStyles.js +3 -1
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/WebChatEventSubscribers.js +13 -2
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activities/LazyLoadActivity.js +160 -167
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activityMiddleware.js +1 -1
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/timestamps/NotDeliveredTimestamp.js +2 -0
- package/lib/cjs/contexts/common/LiveChatWidgetActionType.js +1 -0
- package/lib/cjs/contexts/common/LiveChatWidgetContextInitialState.js +6 -1
- package/lib/cjs/contexts/createReducer.js +15 -0
- package/lib/cjs/controller/componentController.js +13 -1
- package/lib/cjs/plugins/newMessageEventHandler.js +20 -3
- package/lib/esm/common/Constants.js +2 -0
- package/lib/esm/common/facades/FacadeChatSDK.js +236 -10
- package/lib/esm/common/telemetry/TelemetryConstants.js +13 -0
- package/lib/esm/common/telemetry/loggers/appInsightsLogger.js +7 -7
- package/lib/esm/common/utils/xssUtils.js +23 -51
- package/lib/esm/common/utils.js +12 -1
- package/lib/esm/components/errorboundary/ErrorBoundary.js +4 -2
- package/lib/esm/components/livechatwidget/LiveChatWidget.js +9 -1
- package/lib/esm/components/livechatwidget/common/ActivitySubscriber/BotAuthActivitySubscriber.js +23 -6
- package/lib/esm/components/livechatwidget/common/ChatWidgetEvents.js +1 -0
- package/lib/esm/components/livechatwidget/common/PersistentConversationHandler.js +9 -0
- package/lib/esm/components/livechatwidget/common/authHelper.js +44 -4
- package/lib/esm/components/livechatwidget/common/createAdapter.js +3 -2
- package/lib/esm/components/livechatwidget/common/liveChatConfigUtils.js +33 -2
- package/lib/esm/components/livechatwidget/common/startChat.js +31 -14
- package/lib/esm/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +62 -2
- package/lib/esm/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +6 -4
- package/lib/esm/components/proactivechatpanestateful/ProactiveChatPaneStateful.js +1 -2
- package/lib/esm/components/webchatcontainerstateful/WebChatContainerStateful.js +43 -28
- package/lib/esm/components/webchatcontainerstateful/common/activityConverters/convertPersistentChatHistoryMessageToActivity.js +117 -16
- package/lib/esm/components/webchatcontainerstateful/common/defaultStyles/defaultAdaptiveCardStyles.js +3 -1
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/WebChatEventSubscribers.js +13 -2
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activities/LazyLoadActivity.js +160 -171
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activityMiddleware.js +1 -1
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/timestamps/NotDeliveredTimestamp.js +2 -0
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/channelDataMiddleware.js +1 -0
- package/lib/esm/contexts/common/LiveChatWidgetActionType.js +1 -0
- package/lib/esm/contexts/common/LiveChatWidgetContextInitialState.js +6 -1
- package/lib/esm/contexts/createReducer.js +15 -0
- package/lib/esm/controller/componentController.js +13 -1
- package/lib/esm/plugins/newMessageEventHandler.js +20 -3
- package/lib/types/common/Constants.d.ts +2 -0
- package/lib/types/common/facades/FacadeChatSDK.d.ts +29 -0
- package/lib/types/common/facades/types/IFacadeChatSDKInput.d.ts +3 -1
- package/lib/types/common/telemetry/TelemetryConstants.d.ts +13 -2
- package/lib/types/common/utils/xssUtils.d.ts +5 -21
- package/lib/types/common/utils.d.ts +9 -1
- package/lib/types/components/errorboundary/ErrorBoundary.d.ts +1 -1
- package/lib/types/components/livechatwidget/common/ActivitySubscriber/BotAuthActivitySubscriber.d.ts +1 -0
- package/lib/types/components/livechatwidget/common/ChatWidgetEvents.d.ts +2 -1
- package/lib/types/components/livechatwidget/common/authHelper.d.ts +9 -2
- package/lib/types/components/livechatwidget/common/liveChatConfigUtils.d.ts +11 -0
- package/lib/types/components/livechatwidget/interfaces/IBotAuthActivitySubscriberOptionalParams.d.ts +1 -0
- package/lib/types/components/webchatcontainerstateful/interfaces/IAdaptiveCardStyles.d.ts +2 -0
- package/lib/types/components/webchatcontainerstateful/interfaces/IBotAuthConfig.d.ts +7 -0
- package/lib/types/components/webchatcontainerstateful/interfaces/IExtendedChatConffig.d.ts +1 -1
- package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activities/LazyLoadActivity.d.ts +14 -38
- package/lib/types/contexts/common/ILiveChatWidgetContext.d.ts +1 -0
- package/lib/types/contexts/common/LiveChatWidgetActionType.d.ts +2 -1
- package/package.json +15 -6
|
@@ -5,7 +5,7 @@ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key i
|
|
|
5
5
|
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
6
6
|
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
7
7
|
import { BroadcastEvent, LogLevel, TelemetryEvent } from "../telemetry/TelemetryConstants";
|
|
8
|
-
import { getAuthClientFunction, handleAuthentication } from "../../components/livechatwidget/common/authHelper";
|
|
8
|
+
import { getAuthClientFunction, handleAuthentication, isMidAuthEnabled } from "../../components/livechatwidget/common/authHelper";
|
|
9
9
|
import { BroadcastService } from "@microsoft/omnichannel-chat-components";
|
|
10
10
|
import { TelemetryHelper } from "../telemetry/TelemetryHelper";
|
|
11
11
|
import { isNullOrEmptyString } from "../utils";
|
|
@@ -20,6 +20,8 @@ export let FacadeChatSDK = /*#__PURE__*/function () {
|
|
|
20
20
|
_defineProperty(this, "getAuthToken", void 0);
|
|
21
21
|
_defineProperty(this, "sdkMocked", void 0);
|
|
22
22
|
_defineProperty(this, "disableReauthentication", void 0);
|
|
23
|
+
// Stays true so CASE 1 re-triggers on every startChat to set deferInitialAuth
|
|
24
|
+
_defineProperty(this, "pendingMidAuthUnauthenticatedState", false);
|
|
23
25
|
this.chatSDK = input.chatSDK;
|
|
24
26
|
this.chatConfig = input.chatConfig;
|
|
25
27
|
this.getAuthToken = input.getAuthToken;
|
|
@@ -44,6 +46,12 @@ export let FacadeChatSDK = /*#__PURE__*/function () {
|
|
|
44
46
|
value: function destroy() {
|
|
45
47
|
this.token = null;
|
|
46
48
|
this.expiration = 0;
|
|
49
|
+
if (isMidAuthEnabled(this.chatConfig)) {
|
|
50
|
+
this.pendingMidAuthUnauthenticatedState = false;
|
|
51
|
+
this.isAuthenticated = true;
|
|
52
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
53
|
+
this.chatSDK.deferInitialAuth = false;
|
|
54
|
+
}
|
|
47
55
|
}
|
|
48
56
|
}, {
|
|
49
57
|
key: "isTokenSet",
|
|
@@ -208,6 +216,10 @@ export let FacadeChatSDK = /*#__PURE__*/function () {
|
|
|
208
216
|
message: "Token is valid"
|
|
209
217
|
};
|
|
210
218
|
}
|
|
219
|
+
|
|
220
|
+
// Token missing or expired - need to get a new one via getAuthToken
|
|
221
|
+
// For mid-auth: getAuthToken receives { isMidAuthEnabled: true } so customer implementations
|
|
222
|
+
// can check portal state and return null for logged-out users
|
|
211
223
|
TelemetryHelper.logFacadeChatSDKEventToAllTelemetry(LogLevel.INFO, {
|
|
212
224
|
Event: TelemetryEvent.NewTokenValidationStarted,
|
|
213
225
|
Description: "Token validation started."
|
|
@@ -228,6 +240,7 @@ export let FacadeChatSDK = /*#__PURE__*/function () {
|
|
|
228
240
|
this.token = "";
|
|
229
241
|
this.expiration = 0;
|
|
230
242
|
try {
|
|
243
|
+
var _ring$error, _ring$error2;
|
|
231
244
|
const ring = await handleAuthentication(this.chatSDK, this.chatConfig, this.getAuthToken);
|
|
232
245
|
if ((ring === null || ring === void 0 ? void 0 : ring.result) === true && ring !== null && ring !== void 0 && ring.token) {
|
|
233
246
|
await this.setToken(ring.token);
|
|
@@ -242,18 +255,35 @@ export let FacadeChatSDK = /*#__PURE__*/function () {
|
|
|
242
255
|
result: true,
|
|
243
256
|
message: "New Token obtained"
|
|
244
257
|
};
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Mid-auth: no token available - set pending flag for startChat to handle
|
|
261
|
+
const isEmptyTokenWithoutError = isNullOrEmptyString(ring === null || ring === void 0 ? void 0 : ring.token) && ((ring === null || ring === void 0 ? void 0 : ring.result) === true || (ring === null || ring === void 0 ? void 0 : ring.result) === false && !(ring !== null && ring !== void 0 && ring.error));
|
|
262
|
+
if (isMidAuthEnabled(this.chatConfig) && isEmptyTokenWithoutError) {
|
|
263
|
+
// Clear Facade and SDK token state so API calls use unauthenticated endpoints
|
|
264
|
+
this.token = "";
|
|
265
|
+
this.expiration = 0;
|
|
266
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
267
|
+
this.chatSDK.authenticatedUserToken = null;
|
|
268
|
+
this.pendingMidAuthUnauthenticatedState = true;
|
|
269
|
+
TelemetryHelper.logFacadeChatSDKEventToAllTelemetry(LogLevel.INFO, {
|
|
270
|
+
Event: TelemetryEvent.NewTokenValidationCompleted,
|
|
271
|
+
Description: "Mid-auth enabled: no token returned; proceeding as unauthenticated"
|
|
251
272
|
});
|
|
252
273
|
return {
|
|
253
|
-
result:
|
|
254
|
-
message:
|
|
274
|
+
result: true,
|
|
275
|
+
message: "Mid-auth: proceeding as unauthenticated"
|
|
255
276
|
};
|
|
256
277
|
}
|
|
278
|
+
TelemetryHelper.logFacadeChatSDKEventToAllTelemetry(LogLevel.ERROR, {
|
|
279
|
+
Event: TelemetryEvent.NewTokenValidationFailed,
|
|
280
|
+
Description: (_ring$error = ring.error) === null || _ring$error === void 0 ? void 0 : _ring$error.message,
|
|
281
|
+
ExceptionDetails: ring === null || ring === void 0 ? void 0 : ring.error
|
|
282
|
+
});
|
|
283
|
+
return {
|
|
284
|
+
result: false,
|
|
285
|
+
message: (ring === null || ring === void 0 ? void 0 : (_ring$error2 = ring.error) === null || _ring$error2 === void 0 ? void 0 : _ring$error2.message) || "Failed to get token"
|
|
286
|
+
};
|
|
257
287
|
} catch (e) {
|
|
258
288
|
console.error("Unexpected error while getting token", e);
|
|
259
289
|
TelemetryHelper.logFacadeChatSDKEventToAllTelemetry(LogLevel.ERROR, {
|
|
@@ -267,6 +297,155 @@ export let FacadeChatSDK = /*#__PURE__*/function () {
|
|
|
267
297
|
};
|
|
268
298
|
}
|
|
269
299
|
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Sets unauthenticated state for mid-auth flow.
|
|
303
|
+
* Clears SDK internal state to prevent reconnection to previous authenticated session.
|
|
304
|
+
*/
|
|
305
|
+
}, {
|
|
306
|
+
key: "setMidAuthUnauthenticatedState",
|
|
307
|
+
value: function setMidAuthUnauthenticatedState() {
|
|
308
|
+
var _sdk$chatToken, _sdk$chatToken2;
|
|
309
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
310
|
+
const sdk = this.chatSDK;
|
|
311
|
+
const hadExistingChat = !!((_sdk$chatToken = sdk.chatToken) !== null && _sdk$chatToken !== void 0 && _sdk$chatToken.chatId);
|
|
312
|
+
const previousChatId = (_sdk$chatToken2 = sdk.chatToken) === null || _sdk$chatToken2 === void 0 ? void 0 : _sdk$chatToken2.chatId;
|
|
313
|
+
this.clearAuthState();
|
|
314
|
+
|
|
315
|
+
// Clear SDK internal state for fresh unauthenticated chat
|
|
316
|
+
sdk.chatToken = {};
|
|
317
|
+
sdk.reconnectId = null;
|
|
318
|
+
sdk.requestId = null;
|
|
319
|
+
sdk.sessionId = null;
|
|
320
|
+
sdk.conversation = null;
|
|
321
|
+
TelemetryHelper.logFacadeChatSDKEventToAllTelemetry(LogLevel.INFO, {
|
|
322
|
+
Event: TelemetryEvent.MidConversationAuthReset,
|
|
323
|
+
Description: hadExistingChat ? "Mid-auth without token: local state cleared" : "Mid-auth: initialized as unauthenticated (no prior chat)",
|
|
324
|
+
Data: hadExistingChat ? {
|
|
325
|
+
previousChatId
|
|
326
|
+
} : undefined
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/** Clears authentication state in both FacadeChatSDK and underlying SDK */
|
|
331
|
+
}, {
|
|
332
|
+
key: "clearAuthState",
|
|
333
|
+
value: function clearAuthState() {
|
|
334
|
+
this.token = "";
|
|
335
|
+
this.expiration = 0;
|
|
336
|
+
this.isAuthenticated = false;
|
|
337
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
338
|
+
this.chatSDK.authenticatedUserToken = null;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Migrates conversation from unauthenticated to authenticated via authenticateChat.
|
|
343
|
+
* Called after startChat() when user has a valid token but the backend conversation
|
|
344
|
+
* was started as unauthenticated.
|
|
345
|
+
*/
|
|
346
|
+
}, {
|
|
347
|
+
key: "migrateConversationToAuthenticated",
|
|
348
|
+
value: async function migrateConversationToAuthenticated() {
|
|
349
|
+
try {
|
|
350
|
+
await this.chatSDK.authenticateChat(this.token, {
|
|
351
|
+
refreshChatToken: true
|
|
352
|
+
});
|
|
353
|
+
this.isAuthenticated = true;
|
|
354
|
+
TelemetryHelper.logFacadeChatSDKEventToAllTelemetry(LogLevel.INFO, {
|
|
355
|
+
Event: TelemetryEvent.MidConversationAuthSucceeded,
|
|
356
|
+
Description: "Mid-auth: authenticateChat completed, conversation migrated to authenticated"
|
|
357
|
+
});
|
|
358
|
+
} catch (e) {
|
|
359
|
+
// Non-fatal: Chat is already active via startChat, will retry on next reconnect
|
|
360
|
+
TelemetryHelper.logFacadeChatSDKEventToAllTelemetry(LogLevel.WARN, {
|
|
361
|
+
Event: TelemetryEvent.MidConversationAuthFailed,
|
|
362
|
+
Description: "Mid-auth: authenticateChat returned error after startChat, chat still active",
|
|
363
|
+
ExceptionDetails: {
|
|
364
|
+
message: e === null || e === void 0 ? void 0 : e.message
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Configures SDK auth state before startChat.
|
|
372
|
+
* CASE 1: Pending unauthenticated (no token) - sets deferInitialAuth=true
|
|
373
|
+
* CASE 2: Authenticated with valid token - sets SDK token and deferInitialAuth based on scenario
|
|
374
|
+
*/
|
|
375
|
+
}, {
|
|
376
|
+
key: "configureMidAuthState",
|
|
377
|
+
value: function configureMidAuthState(isReconnect, wasPreviousSessionAuthenticated) {
|
|
378
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
379
|
+
const sdk = this.chatSDK;
|
|
380
|
+
|
|
381
|
+
// CASE 1: No token available (user not logged in)
|
|
382
|
+
// pendingMidAuthUnauthenticatedState stays true until user logs in (cleared in tokenRing)
|
|
383
|
+
if (this.pendingMidAuthUnauthenticatedState) {
|
|
384
|
+
const shouldClear = this.handlePendingUnauthenticatedState(wasPreviousSessionAuthenticated);
|
|
385
|
+
sdk.deferInitialAuth = true;
|
|
386
|
+
TelemetryHelper.logFacadeChatSDKEventToAllTelemetry(LogLevel.INFO, {
|
|
387
|
+
Event: TelemetryEvent.MidConversationAuthReset,
|
|
388
|
+
Description: "Mid-auth configureMidAuthState: CASE 1 - unauthenticated, deferInitialAuth=true",
|
|
389
|
+
Data: {
|
|
390
|
+
isReconnect: String(isReconnect),
|
|
391
|
+
wasPreviousSessionAuthenticated: String(wasPreviousSessionAuthenticated),
|
|
392
|
+
shouldClearReconnectParams: String(shouldClear)
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
return {
|
|
396
|
+
shouldClearReconnectParams: shouldClear
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// CASE 2: Authenticated with valid token
|
|
401
|
+
if (this.isTokenSet() && !this.isTokenExpired()) {
|
|
402
|
+
this.handleAuthenticatedState(isReconnect, wasPreviousSessionAuthenticated);
|
|
403
|
+
}
|
|
404
|
+
return {
|
|
405
|
+
shouldClearReconnectParams: false
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* CASE 1 handler: Returns true if reconnect params should be cleared (Auth -> Unauth transition)
|
|
411
|
+
*/
|
|
412
|
+
}, {
|
|
413
|
+
key: "handlePendingUnauthenticatedState",
|
|
414
|
+
value: function handlePendingUnauthenticatedState(wasPreviousSessionAuthenticated) {
|
|
415
|
+
if (wasPreviousSessionAuthenticated) {
|
|
416
|
+
// Auth -> Unauth: user logged out, clear state for fresh chat
|
|
417
|
+
this.setMidAuthUnauthenticatedState();
|
|
418
|
+
return true;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// Unauth -> Unauth: keep liveChatContext for reconnection
|
|
422
|
+
this.isAuthenticated = false;
|
|
423
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
424
|
+
this.chatSDK.authenticatedUserToken = null;
|
|
425
|
+
return false;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* CASE 2 handler: Sets deferInitialAuth only for reconnects to unauthenticated sessions (need migration).
|
|
430
|
+
* For new chats or reconnects to authenticated sessions, SDK handles auth internally.
|
|
431
|
+
*/
|
|
432
|
+
}, {
|
|
433
|
+
key: "handleAuthenticatedState",
|
|
434
|
+
value: function handleAuthenticatedState(isReconnect, wasPreviousSessionAuthenticated) {
|
|
435
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
436
|
+
const sdk = this.chatSDK;
|
|
437
|
+
sdk.authenticatedUserToken = this.token;
|
|
438
|
+
if (isReconnect && !wasPreviousSessionAuthenticated) {
|
|
439
|
+
sdk.deferInitialAuth = true;
|
|
440
|
+
TelemetryHelper.logFacadeChatSDKEventToAllTelemetry(LogLevel.INFO, {
|
|
441
|
+
Event: TelemetryEvent.MidConversationAuthSucceeded,
|
|
442
|
+
Description: "Mid-auth handleAuthenticatedState: CASE 2 - reconnect to unauth session, deferInitialAuth=true (migration needed)"
|
|
443
|
+
});
|
|
444
|
+
} else {
|
|
445
|
+
// Reset to prevent inheriting deferInitialAuth=true from a previous unauthenticated chat
|
|
446
|
+
sdk.deferInitialAuth = false;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
270
449
|
}, {
|
|
271
450
|
key: "validateAndExecuteCall",
|
|
272
451
|
value: async function validateAndExecuteCall(functionName, fn) {
|
|
@@ -301,7 +480,53 @@ export let FacadeChatSDK = /*#__PURE__*/function () {
|
|
|
301
480
|
key: "startChat",
|
|
302
481
|
value: async function startChat() {
|
|
303
482
|
let optionalParams = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
304
|
-
|
|
483
|
+
const midAuthEnabled = isMidAuthEnabled(this.chatConfig);
|
|
484
|
+
const isReconnect = !!optionalParams.liveChatContext || !!optionalParams.reconnectId;
|
|
485
|
+
const wasPreviousSessionAuthenticated = optionalParams.wasAuthenticated === true;
|
|
486
|
+
return this.validateAndExecuteCall("startChat", async () => {
|
|
487
|
+
if (midAuthEnabled) {
|
|
488
|
+
const {
|
|
489
|
+
shouldClearReconnectParams
|
|
490
|
+
} = this.configureMidAuthState(isReconnect, wasPreviousSessionAuthenticated);
|
|
491
|
+
if (shouldClearReconnectParams) {
|
|
492
|
+
delete optionalParams.liveChatContext;
|
|
493
|
+
delete optionalParams.reconnectId;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
await this.chatSDK.startChat(optionalParams);
|
|
497
|
+
|
|
498
|
+
// Migrate to authenticated if needed (reconnects to unauthenticated sessions only)
|
|
499
|
+
if (midAuthEnabled) {
|
|
500
|
+
const shouldMigrateToAuth = isReconnect && this.isTokenSet() && !this.isTokenExpired() && !wasPreviousSessionAuthenticated;
|
|
501
|
+
if (shouldMigrateToAuth) {
|
|
502
|
+
TelemetryHelper.logFacadeChatSDKEventToAllTelemetry(LogLevel.INFO, {
|
|
503
|
+
Event: TelemetryEvent.MidConversationAuthSucceeded,
|
|
504
|
+
Description: "Mid-auth startChat: initiating migration to authenticated",
|
|
505
|
+
Data: {
|
|
506
|
+
isReconnect: String(isReconnect),
|
|
507
|
+
wasPreviousSessionAuthenticated: String(wasPreviousSessionAuthenticated)
|
|
508
|
+
}
|
|
509
|
+
});
|
|
510
|
+
await this.migrateConversationToAuthenticated();
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// Broadcast final auth state after startChat completes (only on state change)
|
|
515
|
+
if (midAuthEnabled) {
|
|
516
|
+
const isAuthenticatedAfterStart = this.isTokenSet() && !this.isTokenExpired();
|
|
517
|
+
const authStateChanged = !isReconnect || isAuthenticatedAfterStart !== wasPreviousSessionAuthenticated;
|
|
518
|
+
if (authStateChanged) {
|
|
519
|
+
BroadcastService.postMessage({
|
|
520
|
+
eventName: isAuthenticatedAfterStart ? BroadcastEvent.MidConversationAuthSucceeded : BroadcastEvent.MidConversationAuthReset,
|
|
521
|
+
payload: {
|
|
522
|
+
isAuthenticated: isAuthenticatedAfterStart,
|
|
523
|
+
isStartChatComplete: true,
|
|
524
|
+
isReconnect
|
|
525
|
+
}
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
});
|
|
305
530
|
}
|
|
306
531
|
}, {
|
|
307
532
|
key: "endChat",
|
|
@@ -439,6 +664,7 @@ export let FacadeChatSDK = /*#__PURE__*/function () {
|
|
|
439
664
|
let optionalParams = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
440
665
|
return this.validateAndExecuteCall("getAgentAvailability", () => this.chatSDK.getAgentAvailability(optionalParams));
|
|
441
666
|
}
|
|
667
|
+
|
|
442
668
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
443
669
|
}, {
|
|
444
670
|
key: "getReconnectableChats",
|
|
@@ -69,6 +69,8 @@ export let BroadcastEvent;
|
|
|
69
69
|
BroadcastEvent["FMLTrackingCompletedAck"] = "FMLTrackingCompletedAck";
|
|
70
70
|
BroadcastEvent["FMLTrackingCompleted"] = "FMLTrackingCompleted";
|
|
71
71
|
BroadcastEvent["PersistentConversationReset"] = "PersistentConversationReset";
|
|
72
|
+
BroadcastEvent["MidConversationAuthSucceeded"] = "MidConversationAuthSucceeded";
|
|
73
|
+
BroadcastEvent["MidConversationAuthReset"] = "MidConversationAuthReset";
|
|
72
74
|
})(BroadcastEvent || (BroadcastEvent = {}));
|
|
73
75
|
export let TelemetryEvent;
|
|
74
76
|
(function (TelemetryEvent) {
|
|
@@ -102,6 +104,9 @@ export let TelemetryEvent;
|
|
|
102
104
|
TelemetryEvent["CallingSDKInitFailed"] = "CallingSDKInitFailed";
|
|
103
105
|
TelemetryEvent["CallingSDKLoadSuccess"] = "CallingSDKLoadSuccess";
|
|
104
106
|
TelemetryEvent["CallingSDKLoadFailed"] = "CallingSDKLoadFailed";
|
|
107
|
+
TelemetryEvent["MidConversationAuthSucceeded"] = "MidConversationAuthSucceeded";
|
|
108
|
+
TelemetryEvent["MidConversationAuthFailed"] = "MidConversationAuthFailed";
|
|
109
|
+
TelemetryEvent["MidConversationAuthReset"] = "MidConversationAuthReset";
|
|
105
110
|
TelemetryEvent["GetConversationDetailsCallStarted"] = "GetConversationDetailsCallStarted";
|
|
106
111
|
TelemetryEvent["GetConversationDetailsCallFailed"] = "GetConversationDetailsCallFailed";
|
|
107
112
|
TelemetryEvent["EndChatSDKCallFailed"] = "EndChatSDKCallFailed";
|
|
@@ -312,10 +317,16 @@ export let TelemetryEvent;
|
|
|
312
317
|
TelemetryEvent["LCWLazyLoadNoMoreHistory"] = "LCWLazyLoadNoMoreHistory";
|
|
313
318
|
TelemetryEvent["LCWLazyLoadHistoryError"] = "LCWLazyLoadHistoryError";
|
|
314
319
|
TelemetryEvent["LCWLazyLoadDestroyed"] = "LCWLazyLoadDestroyed";
|
|
320
|
+
TelemetryEvent["LCWLazyLoadTriggerFired"] = "LCWLazyLoadTriggerFired";
|
|
321
|
+
TelemetryEvent["LCWLazyLoadBatchReceived"] = "LCWLazyLoadBatchReceived";
|
|
322
|
+
TelemetryEvent["LCWLazyLoadInitialLoadComplete"] = "LCWLazyLoadInitialLoadComplete";
|
|
323
|
+
TelemetryEvent["LCWLazyLoadScrollAnchorApplied"] = "LCWLazyLoadScrollAnchorApplied";
|
|
315
324
|
TelemetryEvent["SecureEventBusUnauthorizedDispatch"] = "SecureEventBusUnauthorizedDispatch";
|
|
316
325
|
TelemetryEvent["SecureEventBusListenerError"] = "SecureEventBusListenerError";
|
|
317
326
|
TelemetryEvent["SecureEventBusDispatchError"] = "SecureEventBusDispatchError";
|
|
318
327
|
TelemetryEvent["StartChatComplete"] = "StartChatComplete";
|
|
328
|
+
TelemetryEvent["AgentJoinedConversation"] = "AgentJoinedConversation";
|
|
329
|
+
TelemetryEvent["BrowserTabHidden"] = "BrowserTabHidden";
|
|
319
330
|
})(TelemetryEvent || (TelemetryEvent = {}));
|
|
320
331
|
export let TelemetryConstants = /*#__PURE__*/function () {
|
|
321
332
|
function TelemetryConstants() {
|
|
@@ -386,6 +397,8 @@ export let TelemetryConstants = /*#__PURE__*/function () {
|
|
|
386
397
|
case TelemetryEvent.SecureEventBusUnauthorizedDispatch:
|
|
387
398
|
case TelemetryEvent.SecureEventBusListenerError:
|
|
388
399
|
case TelemetryEvent.SecureEventBusDispatchError:
|
|
400
|
+
case TelemetryEvent.AgentJoinedConversation:
|
|
401
|
+
case TelemetryEvent.BrowserTabHidden:
|
|
389
402
|
return ScenarioType.ACTIONS;
|
|
390
403
|
case TelemetryEvent.StartChatSDKCall:
|
|
391
404
|
case TelemetryEvent.StartChatEventReceived:
|
|
@@ -5,11 +5,11 @@ import { AppInsightsTelemetryMessage } from "../../Constants";
|
|
|
5
5
|
import { AppInsightsEventMapping } from "../AppInsightsEvents";
|
|
6
6
|
var AllowedKeys;
|
|
7
7
|
(function (AllowedKeys) {
|
|
8
|
-
AllowedKeys["OrganizationId"] = "
|
|
9
|
-
AllowedKeys["ConversationId"] = "
|
|
8
|
+
AllowedKeys["OrganizationId"] = "powerplatform.analytics.resource.organization.id";
|
|
9
|
+
AllowedKeys["ConversationId"] = "powerplatform.analytics.resource.id";
|
|
10
10
|
AllowedKeys["ElapsedTimeInMilliseconds"] = "Duration";
|
|
11
|
-
AllowedKeys["Description"] = "
|
|
12
|
-
AllowedKeys["ChannelId"] = "
|
|
11
|
+
AllowedKeys["Description"] = "omnichannel.description";
|
|
12
|
+
AllowedKeys["ChannelId"] = "omnichannel.channel.type";
|
|
13
13
|
AllowedKeys["LCWRuntimeId"] = "ClientSessionId";
|
|
14
14
|
})(AllowedKeys || (AllowedKeys = {}));
|
|
15
15
|
let initializationPromise = null;
|
|
@@ -86,8 +86,8 @@ export const appInsightsLogger = appInsightsKey => {
|
|
|
86
86
|
if (eventName) {
|
|
87
87
|
const trackingEventName = getTrackingEventName(logLevel, eventName);
|
|
88
88
|
const eventProperties = setEventProperties(trackingEventName, telemetryInfo);
|
|
89
|
-
_logger.
|
|
90
|
-
|
|
89
|
+
_logger.trackTrace({
|
|
90
|
+
message: trackingEventName,
|
|
91
91
|
properties: eventProperties
|
|
92
92
|
});
|
|
93
93
|
}
|
|
@@ -133,7 +133,7 @@ export const appInsightsLogger = appInsightsKey => {
|
|
|
133
133
|
// Additional properties
|
|
134
134
|
eventProperties["ConversationStage"] = customProperties.ConversationStage ?? ConversationStage.CSREngagement;
|
|
135
135
|
eventProperties["Scenario"] = "Conversation Diagnostics";
|
|
136
|
-
eventProperties["
|
|
136
|
+
eventProperties["powerplatform.analytics.subscenario"] = eventName.includes(": ") ? eventName.split(": ")[1] : eventName;
|
|
137
137
|
return eventProperties;
|
|
138
138
|
}
|
|
139
139
|
function getTrackingEventName(logLevel, eventName) {
|
|
@@ -1,70 +1,42 @@
|
|
|
1
1
|
import DOMPurify from "dompurify";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Sanitizes text input and detects XSS attack patterns.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* against various XSS techniques including script injection, event handler injection, style-based
|
|
9
|
-
* attacks, and encoded payloads.
|
|
6
|
+
* Sanitizes first with DOMPurify, then checks for malicious patterns in both
|
|
7
|
+
* the original and sanitized text to catch mutation XSS attacks.
|
|
10
8
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* - HTML event handlers (onmouseover, onclick, etc.)
|
|
14
|
-
* - Script tags (<script>)
|
|
15
|
-
* - CSS expression() functions
|
|
16
|
-
* - CSS url() functions
|
|
17
|
-
* - Position-based CSS attacks (position: fixed/absolute)
|
|
18
|
-
* - VBScript protocol URLs
|
|
19
|
-
* - Data URLs with HTML content
|
|
20
|
-
* - Fragment identifiers with escaped quotes
|
|
21
|
-
* - HTML entity-encoded angle brackets
|
|
22
|
-
*
|
|
23
|
-
* @param text - The input text to be analyzed and sanitized
|
|
24
|
-
* @returns An object containing:
|
|
25
|
-
* - cleanText: The sanitized version of the input text with all HTML tags and attributes removed
|
|
26
|
-
* - isXSSDetected: Boolean flag indicating whether potential XSS patterns were found in the original text
|
|
9
|
+
* @param text - Input text to sanitize
|
|
10
|
+
* @returns Object with cleanText (sanitized) and isXSSDetected flag
|
|
27
11
|
*/
|
|
28
12
|
export const detectAndCleanXSS = text => {
|
|
29
|
-
//
|
|
30
|
-
const xssPatterns = [/javascript\s*:/gi,
|
|
31
|
-
// JavaScript protocol URLs (with optional spaces)
|
|
32
|
-
/vbscript\s*:/gi,
|
|
33
|
-
// VBScript protocol URLs (with optional spaces)
|
|
34
|
-
/on\w+\s*=/gi,
|
|
35
|
-
// HTML event handlers (onmouseover, onclick, onload, etc.)
|
|
36
|
-
/<\s*script/gi,
|
|
37
|
-
// Script tag opening (with optional spaces)
|
|
38
|
-
/expression\s*\(/gi,
|
|
39
|
-
// CSS expression() function (IE-specific)
|
|
40
|
-
/url\s*\(/gi,
|
|
41
|
-
// CSS url() function
|
|
42
|
-
/style\s*=.*position\s*:\s*fixed/gi,
|
|
43
|
-
// CSS position fixed attacks
|
|
44
|
-
/style\s*=.*position\s*:\s*absolute/gi,
|
|
45
|
-
// CSS position absolute attacks
|
|
46
|
-
/data\s*:\s*text\s*\/\s*html/gi,
|
|
47
|
-
// Data URLs containing HTML
|
|
48
|
-
/#.*\\"/gi,
|
|
49
|
-
// Fragment identifiers with escaped quotes
|
|
50
|
-
/>.*</gi // HTML entity-encoded angle brackets indicating tag structure
|
|
51
|
-
];
|
|
52
|
-
|
|
53
|
-
// Check if any XSS patterns are detected in the input text
|
|
54
|
-
const isXSSDetected = xssPatterns.some(pattern => pattern.test(text));
|
|
55
|
-
|
|
56
|
-
// Clean the text using DOMPurify with strict config
|
|
13
|
+
// Sanitize first to prevent mutation XSS (e.g., "s<iframe></iframe>tyle" → "style")
|
|
57
14
|
const cleanText = DOMPurify.sanitize(text, {
|
|
58
15
|
ALLOWED_TAGS: [],
|
|
59
|
-
// No HTML tags allowed in title
|
|
60
16
|
ALLOWED_ATTR: [],
|
|
61
17
|
KEEP_CONTENT: true,
|
|
62
|
-
// Keep text content
|
|
63
18
|
ALLOW_DATA_ATTR: false,
|
|
64
19
|
ALLOW_UNKNOWN_PROTOCOLS: false,
|
|
65
20
|
SANITIZE_DOM: true,
|
|
66
21
|
FORCE_BODY: false
|
|
67
22
|
});
|
|
23
|
+
const contentChanged = text !== cleanText;
|
|
24
|
+
|
|
25
|
+
// Non-global regex patterns to avoid stateful .test() issues
|
|
26
|
+
const xssPatterns = [/javascript\s*:/i, /vbscript\s*:/i, /on\w+\s*=/i,
|
|
27
|
+
// Event handlers
|
|
28
|
+
/<\s*script/i, /<\s*iframe/i, /<\s*object/i, /<\s*embed/i, /<\s*svg/i, /expression\s*\(/i,
|
|
29
|
+
// IE CSS expressions
|
|
30
|
+
/style\s*=.*position\s*:\s*(fixed|absolute)/i, /data\s*:\s*text\s*\/\s*html/i, /#.*\\"/i, /&(lt|gt|#x3c|#60|#x3e|#62);/i,
|
|
31
|
+
// HTML entities
|
|
32
|
+
/&#x?[0-9a-f]+;.*</i, /\u003c.*\u003e/i,
|
|
33
|
+
// Unicode escapes
|
|
34
|
+
/src\s*=\s*["']?\s*javascript:/i, /href\s*=\s*["']?\s*javascript:/i];
|
|
35
|
+
const hasXSSPattern = xssPatterns.some(pattern => {
|
|
36
|
+
return pattern.test(text) || pattern.test(cleanText);
|
|
37
|
+
});
|
|
38
|
+
const hasHTMLStructure = /<[^>]+>/.test(text) && !/<[^>]+>/.test(cleanText);
|
|
39
|
+
const isXSSDetected = contentChanged || hasXSSPattern || hasHTMLStructure;
|
|
68
40
|
return {
|
|
69
41
|
cleanText,
|
|
70
42
|
isXSSDetected
|
package/lib/esm/common/utils.js
CHANGED
|
@@ -436,7 +436,7 @@ export const setOcUserAgent = chatSDK => {
|
|
|
436
436
|
// eslint-disable-line @typescript-eslint/no-explicit-any
|
|
437
437
|
if ((_chatSDK$OCClient = chatSDK.OCClient) !== null && _chatSDK$OCClient !== void 0 && _chatSDK$OCClient.ocUserAgent && !((_chatSDK$OCClient2 = chatSDK.OCClient) !== null && _chatSDK$OCClient2 !== void 0 && _chatSDK$OCClient2.ocUserAgent.join(" ").includes("omnichannel-chat-widget/"))) {
|
|
438
438
|
try {
|
|
439
|
-
const version = require("
|
|
439
|
+
const version = require("../../package.json").version; // eslint-disable-line @typescript-eslint/no-var-requires
|
|
440
440
|
const userAgent = `omnichannel-chat-widget/${version}`;
|
|
441
441
|
chatSDK.OCClient.ocUserAgent = [userAgent, ...chatSDK.OCClient.ocUserAgent];
|
|
442
442
|
} catch (error) {
|
|
@@ -474,4 +474,15 @@ export const getCustomEventValue = customEventPayload => {
|
|
|
474
474
|
export function isEndConversationDueToOverflowActivity(activity) {
|
|
475
475
|
var _activity$channelData, _activity$channelData2;
|
|
476
476
|
return (activity === null || activity === void 0 ? void 0 : (_activity$channelData = activity.channelData) === null || _activity$channelData === void 0 ? void 0 : _activity$channelData.tags) && Array.isArray(activity === null || activity === void 0 ? void 0 : (_activity$channelData2 = activity.channelData) === null || _activity$channelData2 === void 0 ? void 0 : _activity$channelData2.tags) && activity.channelData.tags.includes(Constants.EndConversationDueToOverflow);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Parses a value that can be boolean or string ("true"/"false") into a boolean.
|
|
481
|
+
* Handles null/undefined by returning false.
|
|
482
|
+
*
|
|
483
|
+
* @param value - The value to parse (can be boolean, string, null, or undefined)
|
|
484
|
+
* @returns true if value is true or "true" (case-insensitive), false otherwise
|
|
485
|
+
*/
|
|
486
|
+
export function parseBooleanFromConfig(value) {
|
|
487
|
+
return value === true || (value === null || value === void 0 ? void 0 : value.toString().toLowerCase()) === "true";
|
|
477
488
|
}
|
|
@@ -10,12 +10,14 @@ function _possibleConstructorReturn(self, call) { if (call && (typeof call === "
|
|
|
10
10
|
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
|
|
11
11
|
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
|
|
12
12
|
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
|
|
13
|
-
import React, { Component } from
|
|
13
|
+
import React, { Component } from "react";
|
|
14
|
+
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
14
16
|
const RenderChildrenFunction = _ref => {
|
|
15
17
|
let {
|
|
16
18
|
children
|
|
17
19
|
} = _ref;
|
|
18
|
-
return typeof children ===
|
|
20
|
+
return typeof children === "function" ? children() : children;
|
|
19
21
|
};
|
|
20
22
|
let ErrorBoundary = /*#__PURE__*/function (_Component) {
|
|
21
23
|
_inherits(ErrorBoundary, _Component);
|
|
@@ -26,8 +26,16 @@ export const LiveChatWidget = props => {
|
|
|
26
26
|
throw new Error("chatConfig is required");
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
// Check configuration flags
|
|
29
30
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
30
|
-
const
|
|
31
|
+
const hasAuthClientFn = !!((_props$chatConfig = props.chatConfig) !== null && _props$chatConfig !== void 0 && (_props$chatConfig$Liv = _props$chatConfig.LiveChatConfigAuthSettings) !== null && _props$chatConfig$Liv !== void 0 && _props$chatConfig$Liv.msdyn_javascriptclientfunction);
|
|
32
|
+
const persistentChatEnabled = isPersistentChatEnabled((_props$chatConfig2 = props.chatConfig) === null || _props$chatConfig2 === void 0 ? void 0 : (_props$chatConfig2$Li = _props$chatConfig2.LiveWSAndLiveChatEngJoin) === null || _props$chatConfig2$Li === void 0 ? void 0 : _props$chatConfig2$Li.msdyn_conversationmode);
|
|
33
|
+
|
|
34
|
+
// isAuthenticatedChat determines if FacadeChatSDK should require authentication:
|
|
35
|
+
// REGULAR AUTH FLOW (config-based):
|
|
36
|
+
// - Persistent chat enabled ? always authenticated
|
|
37
|
+
// - Auth settings exist ? authenticated from start
|
|
38
|
+
const isAuthenticatedChat = persistentChatEnabled || hasAuthClientFn;
|
|
31
39
|
if (!facadeChatSDK) {
|
|
32
40
|
var _props$mock;
|
|
33
41
|
setFacadeChatSDK(new FacadeChatSDK({
|
package/lib/esm/components/livechatwidget/common/ActivitySubscriber/BotAuthActivitySubscriber.js
CHANGED
|
@@ -40,7 +40,7 @@ const extractSasUrl = async attachment => {
|
|
|
40
40
|
}
|
|
41
41
|
return sasUrl;
|
|
42
42
|
};
|
|
43
|
-
const fetchBotAuthConfig = async (retries, interval) => {
|
|
43
|
+
const fetchBotAuthConfig = async (retries, interval, fallback) => {
|
|
44
44
|
TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
|
|
45
45
|
Event: TelemetryEvent.SetBotAuthProviderFetchConfig
|
|
46
46
|
});
|
|
@@ -56,13 +56,23 @@ const fetchBotAuthConfig = async (retries, interval) => {
|
|
|
56
56
|
});
|
|
57
57
|
if (retries === 1) {
|
|
58
58
|
// Base Case
|
|
59
|
-
|
|
59
|
+
if (response !== undefined) {
|
|
60
|
+
return response;
|
|
61
|
+
}
|
|
62
|
+
if (fallback !== undefined) {
|
|
63
|
+
TelemetryHelper.logLoadingEvent(LogLevel.WARN, {
|
|
64
|
+
Event: TelemetryEvent.SetBotAuthProviderNotFound,
|
|
65
|
+
Description: `Failed to fetch bot auth config after maximum retries. Using fallback value: ${fallback}`
|
|
66
|
+
});
|
|
67
|
+
return fallback;
|
|
68
|
+
}
|
|
69
|
+
throw new Error("Failed to fetch bot auth config after maximum retries");
|
|
60
70
|
}
|
|
61
71
|
await delay(interval);
|
|
62
72
|
if (response !== undefined) {
|
|
63
73
|
return response;
|
|
64
74
|
}
|
|
65
|
-
return await fetchBotAuthConfig(--retries, interval);
|
|
75
|
+
return await fetchBotAuthConfig(--retries, interval, fallback);
|
|
66
76
|
};
|
|
67
77
|
export let BotAuthActivitySubscriber = /*#__PURE__*/function () {
|
|
68
78
|
function BotAuthActivitySubscriber() {
|
|
@@ -72,6 +82,7 @@ export let BotAuthActivitySubscriber = /*#__PURE__*/function () {
|
|
|
72
82
|
_defineProperty(this, "signInCardSeen", void 0);
|
|
73
83
|
_defineProperty(this, "fetchBotAuthConfigRetries", void 0);
|
|
74
84
|
_defineProperty(this, "fetchBotAuthConfigRetryInterval", void 0);
|
|
85
|
+
_defineProperty(this, "fallbackShowSignInCard", void 0);
|
|
75
86
|
this.signInCardSeen = new Set();
|
|
76
87
|
this.fetchBotAuthConfigRetries = 3;
|
|
77
88
|
this.fetchBotAuthConfigRetryInterval = 1000;
|
|
@@ -81,6 +92,11 @@ export let BotAuthActivitySubscriber = /*#__PURE__*/function () {
|
|
|
81
92
|
if (optionalParams.fetchBotAuthConfigRetryInterval) {
|
|
82
93
|
this.fetchBotAuthConfigRetryInterval = optionalParams.fetchBotAuthConfigRetryInterval;
|
|
83
94
|
}
|
|
95
|
+
this.fallbackShowSignInCard = optionalParams.fallbackShowSignInCard;
|
|
96
|
+
TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
|
|
97
|
+
Event: TelemetryEvent.SetBotAuthProviderFetchConfig,
|
|
98
|
+
Description: `BotAuthActivitySubscriber initialized with fallbackShowSignInCard: ${optionalParams.fallbackShowSignInCard}`
|
|
99
|
+
});
|
|
84
100
|
}
|
|
85
101
|
_createClass(BotAuthActivitySubscriber, [{
|
|
86
102
|
key: "applicable",
|
|
@@ -125,7 +141,7 @@ export let BotAuthActivitySubscriber = /*#__PURE__*/function () {
|
|
|
125
141
|
BroadcastService.postMessage(event);
|
|
126
142
|
}
|
|
127
143
|
try {
|
|
128
|
-
const response = await fetchBotAuthConfig(this.fetchBotAuthConfigRetries, this.fetchBotAuthConfigRetryInterval);
|
|
144
|
+
const response = await fetchBotAuthConfig(this.fetchBotAuthConfigRetries, this.fetchBotAuthConfigRetryInterval, this.fallbackShowSignInCard);
|
|
129
145
|
if (response === false) {
|
|
130
146
|
TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
|
|
131
147
|
Event: TelemetryEvent.SetBotAuthProviderHideCard
|
|
@@ -136,9 +152,10 @@ export let BotAuthActivitySubscriber = /*#__PURE__*/function () {
|
|
|
136
152
|
});
|
|
137
153
|
return activity;
|
|
138
154
|
}
|
|
139
|
-
} catch {
|
|
155
|
+
} catch (e) {
|
|
140
156
|
TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
|
|
141
|
-
Event: TelemetryEvent.SetBotAuthProviderNotFound
|
|
157
|
+
Event: TelemetryEvent.SetBotAuthProviderNotFound,
|
|
158
|
+
ExceptionDetails: e instanceof Error ? e.message : JSON.stringify(e)
|
|
142
159
|
});
|
|
143
160
|
//this is to ensure listener continues waiting for response
|
|
144
161
|
if (this.signInCardSeen.has(signInId)) {
|
|
@@ -4,5 +4,6 @@ var ChatWidgetEvents;
|
|
|
4
4
|
ChatWidgetEvents["FETCH_PERSISTENT_CHAT_HISTORY"] = "CHAT_WIDGET/FETCH_PERSISTENT_CHAT_HISTORY";
|
|
5
5
|
ChatWidgetEvents["NO_MORE_HISTORY_AVAILABLE"] = "CHAT_WIDGET/NO_MORE_HISTORY_AVAILABLE";
|
|
6
6
|
ChatWidgetEvents["HISTORY_LOAD_ERROR"] = "CHAT_WIDGET/HISTORY_LOAD_ERROR";
|
|
7
|
+
ChatWidgetEvents["HISTORY_BATCH_LOADED"] = "CHAT_WIDGET/HISTORY_BATCH_LOADED";
|
|
7
8
|
})(ChatWidgetEvents || (ChatWidgetEvents = {}));
|
|
8
9
|
export default ChatWidgetEvents;
|
|
@@ -127,6 +127,12 @@ let PersistentConversationHandler = /*#__PURE__*/function () {
|
|
|
127
127
|
}
|
|
128
128
|
const messagesDescOrder = (_ref = [...messages]) === null || _ref === void 0 ? void 0 : _ref.reverse();
|
|
129
129
|
this.processHistoryMessages(messagesDescOrder);
|
|
130
|
+
|
|
131
|
+
// Signal that a batch of history messages has been added to the store.
|
|
132
|
+
// LazyLoadActivity subscribes to this to apply scroll anchoring after render.
|
|
133
|
+
dispatchCustomEvent(ChatWidgetEvents.HISTORY_BATCH_LOADED, {
|
|
134
|
+
messageCount: messages.length
|
|
135
|
+
});
|
|
130
136
|
TelemetryHelper.logActionEvent(LogLevel.INFO, {
|
|
131
137
|
Event: TelemetryEvent.LCWPersistentHistoryPullCompleted,
|
|
132
138
|
Description: "History pull completed successfully",
|
|
@@ -235,6 +241,9 @@ let PersistentConversationHandler = /*#__PURE__*/function () {
|
|
|
235
241
|
value: function processMessageToActivity(message) {
|
|
236
242
|
try {
|
|
237
243
|
const activity = convertPersistentChatHistoryMessageToActivity(message);
|
|
244
|
+
if (!activity) {
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
238
247
|
activity.id = activity.id || `activity-${this.count}`;
|
|
239
248
|
activity.channelData = {
|
|
240
249
|
...activity.channelData,
|