@microsoft/omnichannel-chat-widget 1.7.6-main.dca3f60 → 1.7.7-main.5abcb8f
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/lib/cjs/common/facades/FacadeChatSDK.js +78 -21
- package/lib/cjs/components/footerstateful/downloadtranscriptstateful/DownloadTranscriptStateful.js +15 -0
- package/lib/cjs/components/livechatwidget/LiveChatWidget.js +3 -2
- package/lib/cjs/components/livechatwidget/interfaces/IFeatureConfigProps.js +1 -0
- package/lib/cjs/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +2 -0
- package/lib/esm/common/facades/FacadeChatSDK.js +78 -21
- package/lib/esm/components/footerstateful/downloadtranscriptstateful/DownloadTranscriptStateful.js +15 -0
- package/lib/esm/components/livechatwidget/LiveChatWidget.js +3 -2
- package/lib/esm/components/livechatwidget/interfaces/IFeatureConfigProps.js +1 -0
- package/lib/esm/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +2 -0
- package/lib/types/common/facades/FacadeChatSDK.d.ts +5 -2
- package/lib/types/components/livechatwidget/interfaces/IFeatureConfigProps.d.ts +3 -0
- package/lib/types/components/livechatwidget/interfaces/ILiveChatWidgetProps.d.ts +9 -7
- package/package.json +2 -2
|
@@ -26,7 +26,7 @@ class FacadeChatSDK {
|
|
|
26
26
|
isTokenSet() {
|
|
27
27
|
return !(0, _utils.isNullOrEmptyString)(this.token);
|
|
28
28
|
}
|
|
29
|
-
constructor(input) {
|
|
29
|
+
constructor(input, disableReauthentication) {
|
|
30
30
|
_defineProperty(this, "chatSDK", void 0);
|
|
31
31
|
_defineProperty(this, "chatConfig", void 0);
|
|
32
32
|
_defineProperty(this, "token", "");
|
|
@@ -34,11 +34,13 @@ class FacadeChatSDK {
|
|
|
34
34
|
_defineProperty(this, "isAuthenticated", void 0);
|
|
35
35
|
_defineProperty(this, "getAuthToken", void 0);
|
|
36
36
|
_defineProperty(this, "sdkMocked", void 0);
|
|
37
|
+
_defineProperty(this, "disableReauthentication", void 0);
|
|
37
38
|
this.chatSDK = input.chatSDK;
|
|
38
39
|
this.chatConfig = input.chatConfig;
|
|
39
40
|
this.getAuthToken = input.getAuthToken;
|
|
40
41
|
this.isAuthenticated = input.isAuthenticated;
|
|
41
42
|
this.sdkMocked = input.isSDKMocked;
|
|
43
|
+
this.disableReauthentication = disableReauthentication;
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
//set default expiration to zero, for undefined or missed exp in jwt
|
|
@@ -62,32 +64,77 @@ class FacadeChatSDK {
|
|
|
62
64
|
|
|
63
65
|
// compare expiration time with current time
|
|
64
66
|
if (now > this.expiration) {
|
|
65
|
-
console.
|
|
67
|
+
console.error("Token is expired", now, this.expiration, now > this.expiration);
|
|
66
68
|
return true;
|
|
67
69
|
}
|
|
68
70
|
return false;
|
|
69
71
|
}
|
|
72
|
+
enforceBase64Encoding(payload) {
|
|
73
|
+
//base64url when present, switches the "-" and "_" characters with "+" and "/"
|
|
74
|
+
const base64Payload = payload.replace(/-/g, "+").replace(/_/g, "/");
|
|
75
|
+
// since base64 encoding requires padding, we need to add padding to the payload
|
|
76
|
+
return base64Payload.padEnd(base64Payload.length + (4 - base64Payload.length % 4) % 4, "=");
|
|
77
|
+
}
|
|
78
|
+
extractExpFromToken(token) {
|
|
79
|
+
const tokenParts = token.split(".");
|
|
80
|
+
const last3digits = token.slice(-3);
|
|
81
|
+
|
|
82
|
+
// token must have 3 parts as JWT format
|
|
83
|
+
if (tokenParts.length !== 3) {
|
|
84
|
+
_TelemetryHelper.TelemetryHelper.logFacadeChatSDKEvent(_TelemetryConstants.LogLevel.ERROR, {
|
|
85
|
+
Event: _TelemetryConstants.TelemetryEvent.NewTokenFailed,
|
|
86
|
+
Description: "Invalid token format",
|
|
87
|
+
ExceptionDetails: {
|
|
88
|
+
message: "Invalid token format, must be in JWT format",
|
|
89
|
+
token: last3digits
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
throw new Error("Invalid token format, must be in JWT format");
|
|
93
|
+
}
|
|
94
|
+
const payload = this.enforceBase64Encoding(tokenParts[1]);
|
|
95
|
+
// decode payload
|
|
96
|
+
const decodedPayload = Buffer.from(payload, "base64").toString("utf-8");
|
|
97
|
+
|
|
98
|
+
// check if decoded payload is valid JSON
|
|
99
|
+
try {
|
|
100
|
+
const jsonPayload = JSON.parse(decodedPayload);
|
|
101
|
+
// check if exp is present in payload
|
|
102
|
+
if (jsonPayload) {
|
|
103
|
+
if (jsonPayload.exp) {
|
|
104
|
+
return jsonPayload.exp;
|
|
105
|
+
}
|
|
106
|
+
return 0;
|
|
107
|
+
}
|
|
108
|
+
_TelemetryHelper.TelemetryHelper.logFacadeChatSDKEvent(_TelemetryConstants.LogLevel.ERROR, {
|
|
109
|
+
Event: _TelemetryConstants.TelemetryEvent.NewTokenFailed,
|
|
110
|
+
Description: "Invalid token payload",
|
|
111
|
+
ExceptionDetails: {
|
|
112
|
+
message: "Token payload is not valid JSON",
|
|
113
|
+
token: last3digits
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
throw new Error("Invalid token payload, payload is not valid JSON");
|
|
117
|
+
} catch (e) {
|
|
118
|
+
console.error("Failed to decode token", e);
|
|
119
|
+
_TelemetryHelper.TelemetryHelper.logFacadeChatSDKEvent(_TelemetryConstants.LogLevel.ERROR, {
|
|
120
|
+
Event: _TelemetryConstants.TelemetryEvent.NewTokenFailed,
|
|
121
|
+
Description: "Failed to decode token",
|
|
122
|
+
ExceptionDetails: {
|
|
123
|
+
message: "Failed to decode token",
|
|
124
|
+
token: last3digits
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
throw new Error("Failed to decode token");
|
|
128
|
+
}
|
|
129
|
+
}
|
|
70
130
|
async setToken(token) {
|
|
71
131
|
// token must be not null, and must be new
|
|
72
132
|
if (!(0, _utils.isNullOrEmptyString)(token) && token !== this.token) {
|
|
73
|
-
|
|
133
|
+
const last3digits = token.slice(-3);
|
|
74
134
|
const instant = Math.floor(Date.now() / 1000);
|
|
75
135
|
this.token = token;
|
|
76
|
-
// decompose token
|
|
77
|
-
const tokenParts = (_this$token = this.token) === null || _this$token === void 0 ? void 0 : _this$token.split(".");
|
|
78
|
-
if (!tokenParts || tokenParts.length <= 1) {
|
|
79
|
-
_TelemetryHelper.TelemetryHelper.logFacadeChatSDKEvent(_TelemetryConstants.LogLevel.ERROR, {
|
|
80
|
-
Event: _TelemetryConstants.TelemetryEvent.NewTokenFailed,
|
|
81
|
-
Description: "Invalid token format",
|
|
82
|
-
ExceptionDetails: "Token must be in JWT format"
|
|
83
|
-
});
|
|
84
|
-
throw new Error("Invalid token format, must be in JWT format");
|
|
85
|
-
}
|
|
86
|
-
// decode token
|
|
87
|
-
const tokenDecoded = JSON.parse(atob(tokenParts[1]));
|
|
88
136
|
// calculate expiration time
|
|
89
|
-
this.expiration = this.convertExpiration(
|
|
90
|
-
|
|
137
|
+
this.expiration = this.convertExpiration(this.extractExpFromToken(token) || 0);
|
|
91
138
|
// this is a control , in case the getAuthToken function returns same token
|
|
92
139
|
if (this.expiration > 0 && this.expiration < instant) {
|
|
93
140
|
_TelemetryHelper.TelemetryHelper.logFacadeChatSDKEvent(_TelemetryConstants.LogLevel.ERROR, {
|
|
@@ -95,14 +142,23 @@ class FacadeChatSDK {
|
|
|
95
142
|
Description: "New token is already expired",
|
|
96
143
|
ExceptionDetails: {
|
|
97
144
|
"Instant": instant,
|
|
98
|
-
"Expiration": this.expiration
|
|
145
|
+
"Expiration": this.expiration,
|
|
146
|
+
"Token": last3digits
|
|
99
147
|
}
|
|
100
148
|
});
|
|
101
|
-
throw new Error(
|
|
149
|
+
throw new Error(`New token is already expired, with epoch time ${this.expiration} , last 3 digits of token: ${last3digits}`);
|
|
102
150
|
}
|
|
103
151
|
}
|
|
104
152
|
}
|
|
105
153
|
async tokenRing() {
|
|
154
|
+
if (this.disableReauthentication === true) {
|
|
155
|
+
// facade feature is disabled, so we are bypassing the re authentication and let it fail.
|
|
156
|
+
return {
|
|
157
|
+
result: true,
|
|
158
|
+
message: "Facade is disabled"
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
106
162
|
// this is needed for storybooks, specifically for reconnect pane which requires authentication bypass
|
|
107
163
|
if (this.sdkMocked === true) {
|
|
108
164
|
return {
|
|
@@ -154,7 +210,6 @@ class FacadeChatSDK {
|
|
|
154
210
|
};
|
|
155
211
|
} else {
|
|
156
212
|
var _ring$error, _ring$error2;
|
|
157
|
-
console.error("Failed to get token", ring);
|
|
158
213
|
_TelemetryHelper.TelemetryHelper.logFacadeChatSDKEvent(_TelemetryConstants.LogLevel.ERROR, {
|
|
159
214
|
Event: _TelemetryConstants.TelemetryEvent.NewTokenFailed,
|
|
160
215
|
Description: (_ring$error = ring.error) === null || _ring$error === void 0 ? void 0 : _ring$error.message,
|
|
@@ -247,7 +302,9 @@ class FacadeChatSDK {
|
|
|
247
302
|
return this.validateAndExecuteCall("sendMessage", () => this.chatSDK.sendMessage(message));
|
|
248
303
|
}
|
|
249
304
|
async onNewMessage(onNewMessageCallback) {
|
|
250
|
-
let optionalParams = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
|
|
305
|
+
let optionalParams = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
|
|
306
|
+
disablePolling: false
|
|
307
|
+
};
|
|
251
308
|
return this.validateAndExecuteCall("onNewMessage", () => this.chatSDK.onNewMessage(onNewMessageCallback, optionalParams));
|
|
252
309
|
}
|
|
253
310
|
async sendTypingEvent() {
|
package/lib/cjs/components/footerstateful/downloadtranscriptstateful/DownloadTranscriptStateful.js
CHANGED
|
@@ -14,6 +14,8 @@ var _NotificationScenarios = require("../../webchatcontainerstateful/webchatcont
|
|
|
14
14
|
var _TelemetryHelper = require("../../../common/telemetry/TelemetryHelper");
|
|
15
15
|
var _createChatTranscript = _interopRequireDefault(require("../../../plugins/createChatTranscript"));
|
|
16
16
|
var _createReducer = require("../../../contexts/createReducer");
|
|
17
|
+
var _omnichannelChatSdk = require("@microsoft/omnichannel-chat-sdk");
|
|
18
|
+
var _ConversationState = require("../../../contexts/common/ConversationState");
|
|
17
19
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
18
20
|
const processDisplayName = displayName => {
|
|
19
21
|
// if displayname matches "teamsvisitor:<some alphanumeric string>", we replace it with "Customer"
|
|
@@ -168,11 +170,24 @@ const downloadTranscript = async (facadeChatSDK, downloadTranscriptProps, state)
|
|
|
168
170
|
// Need to keep existing live chat context for scenarios when transcript is downloaded after endchat
|
|
169
171
|
let liveChatContext = state === null || state === void 0 ? void 0 : (_state$domainStates = state.domainStates) === null || _state$domainStates === void 0 ? void 0 : _state$domainStates.liveChatContext;
|
|
170
172
|
if (!liveChatContext) {
|
|
173
|
+
var _inMemoryState$appSta;
|
|
171
174
|
const inMemoryState = (0, _createReducer.executeReducer)(state, {
|
|
172
175
|
type: _LiveChatWidgetActionType.LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
|
|
173
176
|
payload: null
|
|
174
177
|
});
|
|
175
178
|
liveChatContext = inMemoryState.domainStates.liveChatContext;
|
|
179
|
+
if ((inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta = inMemoryState.appStates) === null || _inMemoryState$appSta === void 0 ? void 0 : _inMemoryState$appSta.conversationState) !== _ConversationState.ConversationState.Active && !liveChatContext) {
|
|
180
|
+
var _state$domainStates2;
|
|
181
|
+
const chatToken = (state === null || state === void 0 ? void 0 : (_state$domainStates2 = state.domainStates) === null || _state$domainStates2 === void 0 ? void 0 : _state$domainStates2.chatToken) || inMemoryState.domainStates.chatToken;
|
|
182
|
+
if (chatToken && Object.keys(chatToken).length > 0) {
|
|
183
|
+
liveChatContext = {
|
|
184
|
+
chatToken: chatToken,
|
|
185
|
+
requestId: chatToken.requestId || (0, _omnichannelChatSdk.uuidv4)()
|
|
186
|
+
};
|
|
187
|
+
} else {
|
|
188
|
+
liveChatContext = await (facadeChatSDK === null || facadeChatSDK === void 0 ? void 0 : facadeChatSDK.getCurrentLiveChatContext());
|
|
189
|
+
}
|
|
190
|
+
}
|
|
176
191
|
}
|
|
177
192
|
let data = await (facadeChatSDK === null || facadeChatSDK === void 0 ? void 0 : facadeChatSDK.getLiveChatTranscript({
|
|
178
193
|
liveChatContext
|
|
@@ -20,13 +20,14 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
20
20
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
21
21
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
22
22
|
const LiveChatWidget = props => {
|
|
23
|
-
var _props$mock, _props$chatConfig, _props$chatConfig$Liv;
|
|
23
|
+
var _props$mock, _props$featureConfigP, _props$chatConfig, _props$chatConfig$Liv;
|
|
24
24
|
const reducer = (0, _createReducer.createReducer)();
|
|
25
25
|
const [state, dispatch] = (0, _react.useReducer)(reducer, (0, _LiveChatWidgetContextInitialState.getLiveChatWidgetContextInitialState)(props));
|
|
26
26
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
27
|
const [adapter, setAdapter] = (0, _react.useState)(undefined);
|
|
28
28
|
const [facadeChatSDK, setFacadeChatSDK] = (0, _react.useState)(undefined);
|
|
29
29
|
const chatSDK = (0, _getMockChatSDKIfApplicable.getMockChatSDKIfApplicable)(props.chatSDK, props === null || props === void 0 ? void 0 : (_props$mock = props.mock) === null || _props$mock === void 0 ? void 0 : _props$mock.type);
|
|
30
|
+
const disableReauthentication = ((_props$featureConfigP = props.featureConfigProps) === null || _props$featureConfigP === void 0 ? void 0 : _props$featureConfigP.disableReauthentication) === true;
|
|
30
31
|
(0, _overridePropsOnMockIfApplicable.default)(props);
|
|
31
32
|
if (!props.chatConfig) {
|
|
32
33
|
throw new Error("chatConfig is required");
|
|
@@ -43,7 +44,7 @@ const LiveChatWidget = props => {
|
|
|
43
44
|
"getAuthToken": props === null || props === void 0 ? void 0 : props.getAuthToken,
|
|
44
45
|
//when type is not undefined, it means the SDK is mocked
|
|
45
46
|
"isSDKMocked": !(0, _utils.isNullOrUndefined)(props === null || props === void 0 ? void 0 : (_props$mock2 = props.mock) === null || _props$mock2 === void 0 ? void 0 : _props$mock2.type)
|
|
46
|
-
}));
|
|
47
|
+
}, disableReauthentication));
|
|
47
48
|
}
|
|
48
49
|
return /*#__PURE__*/_react.default.createElement(_FacadeChatSDKStore.FacadeChatSDKStore.Provider, {
|
|
49
50
|
value: [facadeChatSDK, setFacadeChatSDK]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -588,6 +588,8 @@ const LiveChatWidgetStateful = props => {
|
|
|
588
588
|
_omnichannelChatComponents.BroadcastService.postMessage({
|
|
589
589
|
eventName: _TelemetryConstants.BroadcastEvent.NewMessageNotification
|
|
590
590
|
});
|
|
591
|
+
}, {
|
|
592
|
+
disablePolling: true
|
|
591
593
|
});
|
|
592
594
|
facadeChatSDK === null || facadeChatSDK === void 0 ? void 0 : facadeChatSDK.onAgentEndSession(event => {
|
|
593
595
|
var _inMemoryState$appSta6;
|
|
@@ -20,7 +20,7 @@ export class FacadeChatSDK {
|
|
|
20
20
|
isTokenSet() {
|
|
21
21
|
return !isNullOrEmptyString(this.token);
|
|
22
22
|
}
|
|
23
|
-
constructor(input) {
|
|
23
|
+
constructor(input, disableReauthentication) {
|
|
24
24
|
_defineProperty(this, "chatSDK", void 0);
|
|
25
25
|
_defineProperty(this, "chatConfig", void 0);
|
|
26
26
|
_defineProperty(this, "token", "");
|
|
@@ -28,11 +28,13 @@ export class FacadeChatSDK {
|
|
|
28
28
|
_defineProperty(this, "isAuthenticated", void 0);
|
|
29
29
|
_defineProperty(this, "getAuthToken", void 0);
|
|
30
30
|
_defineProperty(this, "sdkMocked", void 0);
|
|
31
|
+
_defineProperty(this, "disableReauthentication", void 0);
|
|
31
32
|
this.chatSDK = input.chatSDK;
|
|
32
33
|
this.chatConfig = input.chatConfig;
|
|
33
34
|
this.getAuthToken = input.getAuthToken;
|
|
34
35
|
this.isAuthenticated = input.isAuthenticated;
|
|
35
36
|
this.sdkMocked = input.isSDKMocked;
|
|
37
|
+
this.disableReauthentication = disableReauthentication;
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
//set default expiration to zero, for undefined or missed exp in jwt
|
|
@@ -56,32 +58,77 @@ export class FacadeChatSDK {
|
|
|
56
58
|
|
|
57
59
|
// compare expiration time with current time
|
|
58
60
|
if (now > this.expiration) {
|
|
59
|
-
console.
|
|
61
|
+
console.error("Token is expired", now, this.expiration, now > this.expiration);
|
|
60
62
|
return true;
|
|
61
63
|
}
|
|
62
64
|
return false;
|
|
63
65
|
}
|
|
66
|
+
enforceBase64Encoding(payload) {
|
|
67
|
+
//base64url when present, switches the "-" and "_" characters with "+" and "/"
|
|
68
|
+
const base64Payload = payload.replace(/-/g, "+").replace(/_/g, "/");
|
|
69
|
+
// since base64 encoding requires padding, we need to add padding to the payload
|
|
70
|
+
return base64Payload.padEnd(base64Payload.length + (4 - base64Payload.length % 4) % 4, "=");
|
|
71
|
+
}
|
|
72
|
+
extractExpFromToken(token) {
|
|
73
|
+
const tokenParts = token.split(".");
|
|
74
|
+
const last3digits = token.slice(-3);
|
|
75
|
+
|
|
76
|
+
// token must have 3 parts as JWT format
|
|
77
|
+
if (tokenParts.length !== 3) {
|
|
78
|
+
TelemetryHelper.logFacadeChatSDKEvent(LogLevel.ERROR, {
|
|
79
|
+
Event: TelemetryEvent.NewTokenFailed,
|
|
80
|
+
Description: "Invalid token format",
|
|
81
|
+
ExceptionDetails: {
|
|
82
|
+
message: "Invalid token format, must be in JWT format",
|
|
83
|
+
token: last3digits
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
throw new Error("Invalid token format, must be in JWT format");
|
|
87
|
+
}
|
|
88
|
+
const payload = this.enforceBase64Encoding(tokenParts[1]);
|
|
89
|
+
// decode payload
|
|
90
|
+
const decodedPayload = Buffer.from(payload, "base64").toString("utf-8");
|
|
91
|
+
|
|
92
|
+
// check if decoded payload is valid JSON
|
|
93
|
+
try {
|
|
94
|
+
const jsonPayload = JSON.parse(decodedPayload);
|
|
95
|
+
// check if exp is present in payload
|
|
96
|
+
if (jsonPayload) {
|
|
97
|
+
if (jsonPayload.exp) {
|
|
98
|
+
return jsonPayload.exp;
|
|
99
|
+
}
|
|
100
|
+
return 0;
|
|
101
|
+
}
|
|
102
|
+
TelemetryHelper.logFacadeChatSDKEvent(LogLevel.ERROR, {
|
|
103
|
+
Event: TelemetryEvent.NewTokenFailed,
|
|
104
|
+
Description: "Invalid token payload",
|
|
105
|
+
ExceptionDetails: {
|
|
106
|
+
message: "Token payload is not valid JSON",
|
|
107
|
+
token: last3digits
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
throw new Error("Invalid token payload, payload is not valid JSON");
|
|
111
|
+
} catch (e) {
|
|
112
|
+
console.error("Failed to decode token", e);
|
|
113
|
+
TelemetryHelper.logFacadeChatSDKEvent(LogLevel.ERROR, {
|
|
114
|
+
Event: TelemetryEvent.NewTokenFailed,
|
|
115
|
+
Description: "Failed to decode token",
|
|
116
|
+
ExceptionDetails: {
|
|
117
|
+
message: "Failed to decode token",
|
|
118
|
+
token: last3digits
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
throw new Error("Failed to decode token");
|
|
122
|
+
}
|
|
123
|
+
}
|
|
64
124
|
async setToken(token) {
|
|
65
125
|
// token must be not null, and must be new
|
|
66
126
|
if (!isNullOrEmptyString(token) && token !== this.token) {
|
|
67
|
-
|
|
127
|
+
const last3digits = token.slice(-3);
|
|
68
128
|
const instant = Math.floor(Date.now() / 1000);
|
|
69
129
|
this.token = token;
|
|
70
|
-
// decompose token
|
|
71
|
-
const tokenParts = (_this$token = this.token) === null || _this$token === void 0 ? void 0 : _this$token.split(".");
|
|
72
|
-
if (!tokenParts || tokenParts.length <= 1) {
|
|
73
|
-
TelemetryHelper.logFacadeChatSDKEvent(LogLevel.ERROR, {
|
|
74
|
-
Event: TelemetryEvent.NewTokenFailed,
|
|
75
|
-
Description: "Invalid token format",
|
|
76
|
-
ExceptionDetails: "Token must be in JWT format"
|
|
77
|
-
});
|
|
78
|
-
throw new Error("Invalid token format, must be in JWT format");
|
|
79
|
-
}
|
|
80
|
-
// decode token
|
|
81
|
-
const tokenDecoded = JSON.parse(atob(tokenParts[1]));
|
|
82
130
|
// calculate expiration time
|
|
83
|
-
this.expiration = this.convertExpiration(
|
|
84
|
-
|
|
131
|
+
this.expiration = this.convertExpiration(this.extractExpFromToken(token) || 0);
|
|
85
132
|
// this is a control , in case the getAuthToken function returns same token
|
|
86
133
|
if (this.expiration > 0 && this.expiration < instant) {
|
|
87
134
|
TelemetryHelper.logFacadeChatSDKEvent(LogLevel.ERROR, {
|
|
@@ -89,14 +136,23 @@ export class FacadeChatSDK {
|
|
|
89
136
|
Description: "New token is already expired",
|
|
90
137
|
ExceptionDetails: {
|
|
91
138
|
"Instant": instant,
|
|
92
|
-
"Expiration": this.expiration
|
|
139
|
+
"Expiration": this.expiration,
|
|
140
|
+
"Token": last3digits
|
|
93
141
|
}
|
|
94
142
|
});
|
|
95
|
-
throw new Error(
|
|
143
|
+
throw new Error(`New token is already expired, with epoch time ${this.expiration} , last 3 digits of token: ${last3digits}`);
|
|
96
144
|
}
|
|
97
145
|
}
|
|
98
146
|
}
|
|
99
147
|
async tokenRing() {
|
|
148
|
+
if (this.disableReauthentication === true) {
|
|
149
|
+
// facade feature is disabled, so we are bypassing the re authentication and let it fail.
|
|
150
|
+
return {
|
|
151
|
+
result: true,
|
|
152
|
+
message: "Facade is disabled"
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
100
156
|
// this is needed for storybooks, specifically for reconnect pane which requires authentication bypass
|
|
101
157
|
if (this.sdkMocked === true) {
|
|
102
158
|
return {
|
|
@@ -148,7 +204,6 @@ export class FacadeChatSDK {
|
|
|
148
204
|
};
|
|
149
205
|
} else {
|
|
150
206
|
var _ring$error, _ring$error2;
|
|
151
|
-
console.error("Failed to get token", ring);
|
|
152
207
|
TelemetryHelper.logFacadeChatSDKEvent(LogLevel.ERROR, {
|
|
153
208
|
Event: TelemetryEvent.NewTokenFailed,
|
|
154
209
|
Description: (_ring$error = ring.error) === null || _ring$error === void 0 ? void 0 : _ring$error.message,
|
|
@@ -241,7 +296,9 @@ export class FacadeChatSDK {
|
|
|
241
296
|
return this.validateAndExecuteCall("sendMessage", () => this.chatSDK.sendMessage(message));
|
|
242
297
|
}
|
|
243
298
|
async onNewMessage(onNewMessageCallback) {
|
|
244
|
-
let optionalParams = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
|
|
299
|
+
let optionalParams = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
|
|
300
|
+
disablePolling: false
|
|
301
|
+
};
|
|
245
302
|
return this.validateAndExecuteCall("onNewMessage", () => this.chatSDK.onNewMessage(onNewMessageCallback, optionalParams));
|
|
246
303
|
}
|
|
247
304
|
async sendTypingEvent() {
|
package/lib/esm/components/footerstateful/downloadtranscriptstateful/DownloadTranscriptStateful.js
CHANGED
|
@@ -8,6 +8,8 @@ import { NotificationScenarios } from "../../webchatcontainerstateful/webchatcon
|
|
|
8
8
|
import { TelemetryHelper } from "../../../common/telemetry/TelemetryHelper";
|
|
9
9
|
import createChatTranscript from "../../../plugins/createChatTranscript";
|
|
10
10
|
import { executeReducer } from "../../../contexts/createReducer";
|
|
11
|
+
import { uuidv4 } from "@microsoft/omnichannel-chat-sdk";
|
|
12
|
+
import { ConversationState } from "../../../contexts/common/ConversationState";
|
|
11
13
|
const processDisplayName = displayName => {
|
|
12
14
|
// if displayname matches "teamsvisitor:<some alphanumeric string>", we replace it with "Customer"
|
|
13
15
|
const displayNameRegex = ".+:.+";
|
|
@@ -161,11 +163,24 @@ export const downloadTranscript = async (facadeChatSDK, downloadTranscriptProps,
|
|
|
161
163
|
// Need to keep existing live chat context for scenarios when transcript is downloaded after endchat
|
|
162
164
|
let liveChatContext = state === null || state === void 0 ? void 0 : (_state$domainStates = state.domainStates) === null || _state$domainStates === void 0 ? void 0 : _state$domainStates.liveChatContext;
|
|
163
165
|
if (!liveChatContext) {
|
|
166
|
+
var _inMemoryState$appSta;
|
|
164
167
|
const inMemoryState = executeReducer(state, {
|
|
165
168
|
type: LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
|
|
166
169
|
payload: null
|
|
167
170
|
});
|
|
168
171
|
liveChatContext = inMemoryState.domainStates.liveChatContext;
|
|
172
|
+
if ((inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta = inMemoryState.appStates) === null || _inMemoryState$appSta === void 0 ? void 0 : _inMemoryState$appSta.conversationState) !== ConversationState.Active && !liveChatContext) {
|
|
173
|
+
var _state$domainStates2;
|
|
174
|
+
const chatToken = (state === null || state === void 0 ? void 0 : (_state$domainStates2 = state.domainStates) === null || _state$domainStates2 === void 0 ? void 0 : _state$domainStates2.chatToken) || inMemoryState.domainStates.chatToken;
|
|
175
|
+
if (chatToken && Object.keys(chatToken).length > 0) {
|
|
176
|
+
liveChatContext = {
|
|
177
|
+
chatToken: chatToken,
|
|
178
|
+
requestId: chatToken.requestId || uuidv4()
|
|
179
|
+
};
|
|
180
|
+
} else {
|
|
181
|
+
liveChatContext = await (facadeChatSDK === null || facadeChatSDK === void 0 ? void 0 : facadeChatSDK.getCurrentLiveChatContext());
|
|
182
|
+
}
|
|
183
|
+
}
|
|
169
184
|
}
|
|
170
185
|
let data = await (facadeChatSDK === null || facadeChatSDK === void 0 ? void 0 : facadeChatSDK.getLiveChatTranscript({
|
|
171
186
|
liveChatContext
|
|
@@ -11,13 +11,14 @@ import { getMockChatSDKIfApplicable } from "./common/getMockChatSDKIfApplicable"
|
|
|
11
11
|
import { isNullOrUndefined } from "../../common/utils";
|
|
12
12
|
import overridePropsOnMockIfApplicable from "./common/overridePropsOnMockIfApplicable";
|
|
13
13
|
export const LiveChatWidget = props => {
|
|
14
|
-
var _props$mock, _props$chatConfig, _props$chatConfig$Liv;
|
|
14
|
+
var _props$mock, _props$featureConfigP, _props$chatConfig, _props$chatConfig$Liv;
|
|
15
15
|
const reducer = createReducer();
|
|
16
16
|
const [state, dispatch] = useReducer(reducer, getLiveChatWidgetContextInitialState(props));
|
|
17
17
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
18
|
const [adapter, setAdapter] = useState(undefined);
|
|
19
19
|
const [facadeChatSDK, setFacadeChatSDK] = useState(undefined);
|
|
20
20
|
const chatSDK = getMockChatSDKIfApplicable(props.chatSDK, props === null || props === void 0 ? void 0 : (_props$mock = props.mock) === null || _props$mock === void 0 ? void 0 : _props$mock.type);
|
|
21
|
+
const disableReauthentication = ((_props$featureConfigP = props.featureConfigProps) === null || _props$featureConfigP === void 0 ? void 0 : _props$featureConfigP.disableReauthentication) === true;
|
|
21
22
|
overridePropsOnMockIfApplicable(props);
|
|
22
23
|
if (!props.chatConfig) {
|
|
23
24
|
throw new Error("chatConfig is required");
|
|
@@ -34,7 +35,7 @@ export const LiveChatWidget = props => {
|
|
|
34
35
|
"getAuthToken": props === null || props === void 0 ? void 0 : props.getAuthToken,
|
|
35
36
|
//when type is not undefined, it means the SDK is mocked
|
|
36
37
|
"isSDKMocked": !isNullOrUndefined(props === null || props === void 0 ? void 0 : (_props$mock2 = props.mock) === null || _props$mock2 === void 0 ? void 0 : _props$mock2.type)
|
|
37
|
-
}));
|
|
38
|
+
}, disableReauthentication));
|
|
38
39
|
}
|
|
39
40
|
return /*#__PURE__*/React.createElement(FacadeChatSDKStore.Provider, {
|
|
40
41
|
value: [facadeChatSDK, setFacadeChatSDK]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -580,6 +580,8 @@ export const LiveChatWidgetStateful = props => {
|
|
|
580
580
|
BroadcastService.postMessage({
|
|
581
581
|
eventName: BroadcastEvent.NewMessageNotification
|
|
582
582
|
});
|
|
583
|
+
}, {
|
|
584
|
+
disablePolling: true
|
|
583
585
|
});
|
|
584
586
|
facadeChatSDK === null || facadeChatSDK === void 0 ? void 0 : facadeChatSDK.onAgentEndSession(event => {
|
|
585
587
|
var _inMemoryState$appSta6;
|
|
@@ -32,13 +32,16 @@ export declare class FacadeChatSDK {
|
|
|
32
32
|
private isAuthenticated;
|
|
33
33
|
private getAuthToken?;
|
|
34
34
|
private sdkMocked;
|
|
35
|
+
private disableReauthentication;
|
|
35
36
|
isSDKMocked(): boolean;
|
|
36
37
|
getChatSDK(): OmnichannelChatSDK;
|
|
37
38
|
destroy(): void;
|
|
38
39
|
isTokenSet(): boolean;
|
|
39
|
-
constructor(input: IFacadeChatSDKInput);
|
|
40
|
+
constructor(input: IFacadeChatSDKInput, disableReauthentication: boolean);
|
|
40
41
|
private convertExpiration;
|
|
41
42
|
private isTokenExpired;
|
|
43
|
+
private enforceBase64Encoding;
|
|
44
|
+
private extractExpFromToken;
|
|
42
45
|
private setToken;
|
|
43
46
|
private tokenRing;
|
|
44
47
|
private validateAndExecuteCall;
|
|
@@ -55,7 +58,7 @@ export declare class FacadeChatSDK {
|
|
|
55
58
|
getMessages(): Promise<IMessage[] | OmnichannelMessage[] | undefined>;
|
|
56
59
|
getDataMaskingRules(): Promise<MaskingRules>;
|
|
57
60
|
sendMessage(message: ChatSDKMessage): Promise<void>;
|
|
58
|
-
onNewMessage(onNewMessageCallback: CallableFunction, optionalParams?: OnNewMessageOptionalParams
|
|
61
|
+
onNewMessage(onNewMessageCallback: CallableFunction, optionalParams?: OnNewMessageOptionalParams): Promise<void>;
|
|
59
62
|
sendTypingEvent(): Promise<void>;
|
|
60
63
|
onTypingEvent(onTypingEventCallback: CallableFunction): Promise<void>;
|
|
61
64
|
onAgentEndSession(onAgentEndSessionCallback: (message: IRawThread | ParticipantsRemovedEvent) => void): Promise<void>;
|
|
@@ -3,29 +3,30 @@ import { IAudioNotificationProps } from "../../footerstateful/audionotifications
|
|
|
3
3
|
import { ICallingContainerProps } from "@microsoft/omnichannel-chat-components/lib/types/components/callingcontainer/interfaces/ICallingContainerProps";
|
|
4
4
|
import { IChatButtonProps } from "@microsoft/omnichannel-chat-components/lib/types/components/chatbutton/interfaces/IChatButtonProps";
|
|
5
5
|
import { IConfirmationPaneStatefulProps } from "../../confirmationpanestateful/interfaces/IConfirmationPaneStatefulProps";
|
|
6
|
+
import { IContextDataStore } from "../../../common/interfaces/IContextDataStore";
|
|
6
7
|
import { IDownloadTranscriptProps } from "../../footerstateful/downloadtranscriptstateful/interfaces/IDownloadTranscriptProps";
|
|
8
|
+
import { IDraggableChatWidgetProps } from "./IDraggableChatWidgetProps";
|
|
7
9
|
import { IEmailTranscriptPaneProps } from "../../emailtranscriptpanestateful/interfaces/IEmailTranscriptPaneProps";
|
|
10
|
+
import { IFeatureConfigProps } from "./IFeatureConfigProps";
|
|
8
11
|
import { IFooterProps } from "@microsoft/omnichannel-chat-components/lib/types/components/footer/interfaces/IFooterProps";
|
|
9
12
|
import { IHeaderProps } from "@microsoft/omnichannel-chat-components/lib/types/components/header/interfaces/IHeaderProps";
|
|
10
13
|
import { ILiveChatWidgetComponentOverrides } from "./ILiveChatWidgetComponentOverrides";
|
|
14
|
+
import { ILiveChatWidgetContext } from "../../../contexts/common/ILiveChatWidgetContext";
|
|
11
15
|
import { ILiveChatWidgetControlProps } from "./ILiveChatWidgetControlProps";
|
|
12
16
|
import { ILiveChatWidgetStyleProps } from "./ILiveChatWidgetStyleProps";
|
|
13
17
|
import { ILoadingPaneProps } from "@microsoft/omnichannel-chat-components/lib/types/components/loadingpane/interfaces/ILoadingPaneProps";
|
|
18
|
+
import { IMockProps } from "./IMockProps";
|
|
19
|
+
import { INotificationPaneProps } from "@microsoft/omnichannel-chat-components/lib/types/components/notificationpane/interfaces/INotificationPaneProps";
|
|
14
20
|
import { IOOOHPaneProps } from "@microsoft/omnichannel-chat-components/lib/types/components/outofofficehourspane/interfaces/IOOOHPaneProps";
|
|
21
|
+
import { IPostChatSurveyPaneStatefulProps } from "../../postchatsurveypanestateful/interfaces/IPostChatSurveyPaneStatefulProps";
|
|
15
22
|
import { IPreChatSurveyPaneProps } from "@microsoft/omnichannel-chat-components/lib/types/components/prechatsurveypane/interfaces/IPreChatSurveyPaneProps";
|
|
16
23
|
import { IProactiveChatPaneStatefulProps } from "../../proactivechatpanestateful/interfaces/IProactiveChatPaneStatefulProps";
|
|
17
24
|
import { IReconnectChatPaneStatefulProps } from "../../reconnectchatpanestateful/interfaces/IReconnectChatPaneStatefulProps";
|
|
25
|
+
import { IScrollBarProps } from "./IScrollBarProps";
|
|
18
26
|
import { IStartChatErrorPaneProps } from "../../startchaterrorpanestateful/interfaces/IStartChatErrorPaneProps";
|
|
19
27
|
import { ITelemetryConfig } from "../../../common/telemetry/interfaces/ITelemetryConfig";
|
|
20
28
|
import { IWebChatContainerStatefulProps } from "../../webchatcontainerstateful/interfaces/IWebChatContainerStatefulProps";
|
|
21
29
|
import { OmnichannelChatSDK } from "@microsoft/omnichannel-chat-sdk";
|
|
22
|
-
import { ILiveChatWidgetContext } from "../../../contexts/common/ILiveChatWidgetContext";
|
|
23
|
-
import { IContextDataStore } from "../../../common/interfaces/IContextDataStore";
|
|
24
|
-
import { IPostChatSurveyPaneStatefulProps } from "../../postchatsurveypanestateful/interfaces/IPostChatSurveyPaneStatefulProps";
|
|
25
|
-
import { IScrollBarProps } from "./IScrollBarProps";
|
|
26
|
-
import { IDraggableChatWidgetProps } from "./IDraggableChatWidgetProps";
|
|
27
|
-
import { INotificationPaneProps } from "@microsoft/omnichannel-chat-components/lib/types/components/notificationpane/interfaces/INotificationPaneProps";
|
|
28
|
-
import { IMockProps } from "./IMockProps";
|
|
29
30
|
export interface ILiveChatWidgetProps {
|
|
30
31
|
audioNotificationProps?: IAudioNotificationProps;
|
|
31
32
|
callingContainerProps?: ICallingContainerProps;
|
|
@@ -63,4 +64,5 @@ export interface ILiveChatWidgetProps {
|
|
|
63
64
|
initialCustomContext?: any;
|
|
64
65
|
draggableChatWidgetProps?: IDraggableChatWidgetProps;
|
|
65
66
|
mock?: IMockProps;
|
|
67
|
+
featureConfigProps?: IFeatureConfigProps;
|
|
66
68
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@microsoft/omnichannel-chat-widget",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.7-main.5abcb8f",
|
|
4
4
|
"description": "Microsoft Omnichannel Chat Widget",
|
|
5
5
|
"main": "lib/cjs/index.js",
|
|
6
6
|
"types": "lib/types/index.d.ts",
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"dependencies": {
|
|
79
79
|
"@azure/core-tracing": "^1.2.0",
|
|
80
80
|
"@microsoft/omnichannel-chat-components": "1.1.8",
|
|
81
|
-
"@microsoft/omnichannel-chat-sdk": "^1.10.
|
|
81
|
+
"@microsoft/omnichannel-chat-sdk": "^1.10.14",
|
|
82
82
|
"@opentelemetry/api": "^1.9.0",
|
|
83
83
|
"abort-controller-es5": "^2.0.1",
|
|
84
84
|
"dompurify": "^3.2.4",
|