@thoughtspot/visual-embed-sdk 1.29.0-alpha.8 → 1.29.0-alpha.SCAL-205893-2

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 (229) hide show
  1. package/cjs/package.json +1 -1
  2. package/cjs/src/auth.d.ts +14 -17
  3. package/cjs/src/auth.d.ts.map +1 -1
  4. package/cjs/src/auth.js +50 -59
  5. package/cjs/src/auth.js.map +1 -1
  6. package/cjs/src/auth.spec.d.ts +12 -0
  7. package/cjs/src/auth.spec.d.ts.map +1 -1
  8. package/cjs/src/auth.spec.js +89 -67
  9. package/cjs/src/auth.spec.js.map +1 -1
  10. package/cjs/src/authToken.d.ts +1 -1
  11. package/cjs/src/authToken.d.ts.map +1 -1
  12. package/cjs/src/authToken.js +10 -4
  13. package/cjs/src/authToken.js.map +1 -1
  14. package/cjs/src/embed/app.spec.js +4 -2
  15. package/cjs/src/embed/app.spec.js.map +1 -1
  16. package/cjs/src/embed/base.d.ts.map +1 -1
  17. package/cjs/src/embed/base.js +2 -0
  18. package/cjs/src/embed/base.js.map +1 -1
  19. package/cjs/src/embed/base.spec.js +1 -0
  20. package/cjs/src/embed/base.spec.js.map +1 -1
  21. package/cjs/src/embed/embed.spec.js +3 -0
  22. package/cjs/src/embed/embed.spec.js.map +1 -1
  23. package/cjs/src/embed/events.spec.js +3 -0
  24. package/cjs/src/embed/events.spec.js.map +1 -1
  25. package/cjs/src/embed/liveboard.spec.js +2 -0
  26. package/cjs/src/embed/liveboard.spec.js.map +1 -1
  27. package/cjs/src/embed/pinboard.spec.js +3 -0
  28. package/cjs/src/embed/pinboard.spec.js.map +1 -1
  29. package/cjs/src/embed/sage.spec.js +3 -0
  30. package/cjs/src/embed/sage.spec.js.map +1 -1
  31. package/cjs/src/embed/search.spec.js +1 -0
  32. package/cjs/src/embed/search.spec.js.map +1 -1
  33. package/cjs/src/embed/ts-embed-trigger.spec.js +3 -0
  34. package/cjs/src/embed/ts-embed-trigger.spec.js.map +1 -1
  35. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  36. package/cjs/src/embed/ts-embed.js +1 -0
  37. package/cjs/src/embed/ts-embed.js.map +1 -1
  38. package/cjs/src/embed/ts-embed.spec.js +7 -0
  39. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  40. package/cjs/src/index.d.ts +2 -1
  41. package/cjs/src/index.d.ts.map +1 -1
  42. package/cjs/src/index.js +2 -1
  43. package/cjs/src/index.js.map +1 -1
  44. package/cjs/src/mixpanel-service.d.ts +2 -1
  45. package/cjs/src/mixpanel-service.d.ts.map +1 -1
  46. package/cjs/src/mixpanel-service.js +1 -0
  47. package/cjs/src/mixpanel-service.js.map +1 -1
  48. package/cjs/src/mixpanel-service.spec.js +7 -0
  49. package/cjs/src/mixpanel-service.spec.js.map +1 -1
  50. package/cjs/src/react/index.d.ts +1 -1
  51. package/cjs/src/react/index.d.ts.map +1 -1
  52. package/cjs/src/react/index.js +2 -1
  53. package/cjs/src/react/index.js.map +1 -1
  54. package/cjs/src/react/index.spec.js +6 -0
  55. package/cjs/src/react/index.spec.js.map +1 -1
  56. package/cjs/src/types.d.ts +1 -1
  57. package/cjs/src/types.js +1 -1
  58. package/cjs/src/utils/authService/authService.d.ts +1 -0
  59. package/cjs/src/utils/authService/authService.d.ts.map +1 -1
  60. package/cjs/src/utils/authService/authService.js +1 -0
  61. package/cjs/src/utils/authService/authService.js.map +1 -1
  62. package/cjs/src/utils/authService/authService.spec.js +18 -5
  63. package/cjs/src/utils/authService/authService.spec.js.map +1 -1
  64. package/cjs/src/utils/authService/tokenizedAuthService.d.ts +15 -2
  65. package/cjs/src/utils/authService/tokenizedAuthService.d.ts.map +1 -1
  66. package/cjs/src/utils/authService/tokenizedAuthService.js +39 -9
  67. package/cjs/src/utils/authService/tokenizedAuthService.js.map +1 -1
  68. package/cjs/src/utils/authService/tokenizedAuthService.spec.d.ts +2 -0
  69. package/cjs/src/utils/authService/tokenizedAuthService.spec.d.ts.map +1 -0
  70. package/cjs/src/utils/authService/tokenizedAuthService.spec.js +32 -0
  71. package/cjs/src/utils/authService/tokenizedAuthService.spec.js.map +1 -0
  72. package/cjs/src/utils/graphql/answerService/answerService.d.ts +10 -0
  73. package/cjs/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  74. package/cjs/src/utils/graphql/answerService/answerService.js +10 -0
  75. package/cjs/src/utils/graphql/answerService/answerService.js.map +1 -1
  76. package/cjs/src/utils/processData.js +2 -2
  77. package/cjs/src/utils/processData.js.map +1 -1
  78. package/cjs/src/utils/processData.spec.js +3 -2
  79. package/cjs/src/utils/processData.spec.js.map +1 -1
  80. package/cjs/src/utils/sessionInfoService.d.ts +66 -0
  81. package/cjs/src/utils/sessionInfoService.d.ts.map +1 -0
  82. package/cjs/src/utils/sessionInfoService.js +92 -0
  83. package/cjs/src/utils/sessionInfoService.js.map +1 -0
  84. package/dist/src/auth.d.ts +14 -17
  85. package/dist/src/auth.d.ts.map +1 -1
  86. package/dist/src/auth.spec.d.ts +12 -0
  87. package/dist/src/auth.spec.d.ts.map +1 -1
  88. package/dist/src/authToken.d.ts +1 -1
  89. package/dist/src/authToken.d.ts.map +1 -1
  90. package/dist/src/embed/base.d.ts.map +1 -1
  91. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  92. package/dist/src/index.d.ts +2 -1
  93. package/dist/src/index.d.ts.map +1 -1
  94. package/dist/src/mixpanel-service.d.ts +2 -1
  95. package/dist/src/mixpanel-service.d.ts.map +1 -1
  96. package/dist/src/react/index.d.ts +1 -1
  97. package/dist/src/react/index.d.ts.map +1 -1
  98. package/dist/src/types.d.ts +1 -1
  99. package/dist/src/utils/authService/authService.d.ts +1 -0
  100. package/dist/src/utils/authService/authService.d.ts.map +1 -1
  101. package/dist/src/utils/authService/tokenizedAuthService.d.ts +15 -2
  102. package/dist/src/utils/authService/tokenizedAuthService.d.ts.map +1 -1
  103. package/dist/src/utils/authService/tokenizedAuthService.spec.d.ts +2 -0
  104. package/dist/src/utils/authService/tokenizedAuthService.spec.d.ts.map +1 -0
  105. package/dist/src/utils/graphql/answerService/answerService.d.ts +10 -0
  106. package/dist/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  107. package/dist/src/utils/sessionInfoService.d.ts +66 -0
  108. package/dist/src/utils/sessionInfoService.d.ts.map +1 -0
  109. package/dist/tsembed-react.es.js +153 -58
  110. package/dist/tsembed-react.js +153 -57
  111. package/dist/tsembed.es.js +161 -69
  112. package/dist/tsembed.js +161 -69
  113. package/dist/visual-embed-sdk-react-full.d.ts +93 -20
  114. package/dist/visual-embed-sdk-react.d.ts +93 -20
  115. package/dist/visual-embed-sdk.d.ts +93 -20
  116. package/lib/package.json +1 -1
  117. package/lib/src/auth.d.ts +14 -17
  118. package/lib/src/auth.d.ts.map +1 -1
  119. package/lib/src/auth.js +49 -56
  120. package/lib/src/auth.js.map +1 -1
  121. package/lib/src/auth.spec.d.ts +12 -0
  122. package/lib/src/auth.spec.d.ts.map +1 -1
  123. package/lib/src/auth.spec.js +88 -66
  124. package/lib/src/auth.spec.js.map +1 -1
  125. package/lib/src/authToken.d.ts +1 -1
  126. package/lib/src/authToken.d.ts.map +1 -1
  127. package/lib/src/authToken.js +10 -4
  128. package/lib/src/authToken.js.map +1 -1
  129. package/lib/src/embed/app.spec.js +4 -2
  130. package/lib/src/embed/app.spec.js.map +1 -1
  131. package/lib/src/embed/base.d.ts.map +1 -1
  132. package/lib/src/embed/base.js +3 -1
  133. package/lib/src/embed/base.js.map +1 -1
  134. package/lib/src/embed/base.spec.js +1 -0
  135. package/lib/src/embed/base.spec.js.map +1 -1
  136. package/lib/src/embed/embed.spec.js +2 -0
  137. package/lib/src/embed/embed.spec.js.map +1 -1
  138. package/lib/src/embed/events.spec.js +2 -0
  139. package/lib/src/embed/events.spec.js.map +1 -1
  140. package/lib/src/embed/liveboard.spec.js +2 -0
  141. package/lib/src/embed/liveboard.spec.js.map +1 -1
  142. package/lib/src/embed/pinboard.spec.js +2 -0
  143. package/lib/src/embed/pinboard.spec.js.map +1 -1
  144. package/lib/src/embed/sage.spec.js +2 -0
  145. package/lib/src/embed/sage.spec.js.map +1 -1
  146. package/lib/src/embed/search.spec.js +1 -0
  147. package/lib/src/embed/search.spec.js.map +1 -1
  148. package/lib/src/embed/ts-embed-trigger.spec.js +2 -0
  149. package/lib/src/embed/ts-embed-trigger.spec.js.map +1 -1
  150. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  151. package/lib/src/embed/ts-embed.js +1 -0
  152. package/lib/src/embed/ts-embed.js.map +1 -1
  153. package/lib/src/embed/ts-embed.spec.js +7 -0
  154. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  155. package/lib/src/index.d.ts +2 -1
  156. package/lib/src/index.d.ts.map +1 -1
  157. package/lib/src/index.js +2 -1
  158. package/lib/src/index.js.map +1 -1
  159. package/lib/src/mixpanel-service.d.ts +2 -1
  160. package/lib/src/mixpanel-service.d.ts.map +1 -1
  161. package/lib/src/mixpanel-service.js +1 -0
  162. package/lib/src/mixpanel-service.js.map +1 -1
  163. package/lib/src/mixpanel-service.spec.js +7 -0
  164. package/lib/src/mixpanel-service.spec.js.map +1 -1
  165. package/lib/src/react/index.d.ts +1 -1
  166. package/lib/src/react/index.d.ts.map +1 -1
  167. package/lib/src/react/index.js +1 -1
  168. package/lib/src/react/index.js.map +1 -1
  169. package/lib/src/react/index.spec.js +6 -0
  170. package/lib/src/react/index.spec.js.map +1 -1
  171. package/lib/src/types.d.ts +1 -1
  172. package/lib/src/types.js +1 -1
  173. package/lib/src/utils/authService/authService.d.ts +1 -0
  174. package/lib/src/utils/authService/authService.d.ts.map +1 -1
  175. package/lib/src/utils/authService/authService.js +1 -0
  176. package/lib/src/utils/authService/authService.js.map +1 -1
  177. package/lib/src/utils/authService/authService.spec.js +18 -5
  178. package/lib/src/utils/authService/authService.spec.js.map +1 -1
  179. package/lib/src/utils/authService/tokenizedAuthService.d.ts +15 -2
  180. package/lib/src/utils/authService/tokenizedAuthService.d.ts.map +1 -1
  181. package/lib/src/utils/authService/tokenizedAuthService.js +37 -8
  182. package/lib/src/utils/authService/tokenizedAuthService.js.map +1 -1
  183. package/lib/src/utils/authService/tokenizedAuthService.spec.d.ts +2 -0
  184. package/lib/src/utils/authService/tokenizedAuthService.spec.d.ts.map +1 -0
  185. package/lib/src/utils/authService/tokenizedAuthService.spec.js +29 -0
  186. package/lib/src/utils/authService/tokenizedAuthService.spec.js.map +1 -0
  187. package/lib/src/utils/graphql/answerService/answerService.d.ts +10 -0
  188. package/lib/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  189. package/lib/src/utils/graphql/answerService/answerService.js +10 -0
  190. package/lib/src/utils/graphql/answerService/answerService.js.map +1 -1
  191. package/lib/src/utils/processData.js +3 -3
  192. package/lib/src/utils/processData.js.map +1 -1
  193. package/lib/src/utils/processData.spec.js +3 -2
  194. package/lib/src/utils/processData.spec.js.map +1 -1
  195. package/lib/src/utils/sessionInfoService.d.ts +66 -0
  196. package/lib/src/utils/sessionInfoService.d.ts.map +1 -0
  197. package/lib/src/utils/sessionInfoService.js +85 -0
  198. package/lib/src/utils/sessionInfoService.js.map +1 -0
  199. package/lib/src/visual-embed-sdk.d.ts +98 -21
  200. package/package.json +1 -1
  201. package/src/auth.spec.ts +92 -72
  202. package/src/auth.ts +50 -68
  203. package/src/authToken.ts +9 -4
  204. package/src/embed/app.spec.ts +4 -2
  205. package/src/embed/base.spec.ts +1 -0
  206. package/src/embed/base.ts +3 -0
  207. package/src/embed/embed.spec.ts +2 -0
  208. package/src/embed/events.spec.ts +2 -0
  209. package/src/embed/liveboard.spec.ts +2 -0
  210. package/src/embed/pinboard.spec.ts +2 -0
  211. package/src/embed/sage.spec.ts +3 -0
  212. package/src/embed/search.spec.ts +1 -0
  213. package/src/embed/ts-embed-trigger.spec.ts +3 -0
  214. package/src/embed/ts-embed.spec.ts +8 -0
  215. package/src/embed/ts-embed.ts +1 -0
  216. package/src/index.ts +2 -1
  217. package/src/mixpanel-service.spec.ts +12 -3
  218. package/src/mixpanel-service.ts +3 -1
  219. package/src/react/index.spec.tsx +7 -0
  220. package/src/react/index.tsx +1 -0
  221. package/src/types.ts +1 -1
  222. package/src/utils/authService/authService.spec.ts +18 -5
  223. package/src/utils/authService/authService.ts +1 -0
  224. package/src/utils/authService/tokenizedAuthService.spec.ts +36 -0
  225. package/src/utils/authService/tokenizedAuthService.ts +38 -8
  226. package/src/utils/graphql/answerService/answerService.ts +10 -0
  227. package/src/utils/processData.spec.ts +3 -2
  228. package/src/utils/processData.ts +3 -3
  229. package/src/utils/sessionInfoService.ts +101 -0
package/src/auth.ts CHANGED
@@ -1,20 +1,21 @@
1
1
  import EventEmitter from 'eventemitter3';
2
+ import { getAuthenticationToken, resetCachedAuthToken } from './authToken';
3
+ import { getEmbedConfig } from './embed/embedConfig';
2
4
  import { initMixpanel } from './mixpanel-service';
3
5
  import {
4
- AuthType, DOMSelector, EmbedConfig, EmbedEvent, Param,
6
+ AuthType, DOMSelector, EmbedConfig, EmbedEvent,
5
7
  } from './types';
6
8
  import { getDOMNode, getRedirectUrl } from './utils';
7
9
  import {
8
- fetchSessionInfoService,
10
+ EndPoints,
11
+ fetchAuthPostService,
9
12
  fetchAuthService,
10
13
  fetchBasicAuthService,
11
14
  fetchLogoutService,
12
- fetchAuthPostService,
13
- EndPoints,
14
15
  } from './utils/authService';
15
- import { getAuthenticationToken, resetCachedAuthToken } from './authToken';
16
+ import { isActiveService } from './utils/authService/tokenizedAuthService';
16
17
  import { logger } from './utils/logger';
17
- import { getEmbedConfig } from './embed/embedConfig';
18
+ import { getSessionInfo } from './utils/sessionInfoService';
18
19
 
19
20
  // eslint-disable-next-line import/no-mutable-exports
20
21
  export let loggedInStatus = false;
@@ -22,22 +23,11 @@ export let loggedInStatus = false;
22
23
  export let samlAuthWindow: Window = null;
23
24
  // eslint-disable-next-line import/no-mutable-exports
24
25
  export let samlCompletionPromise: Promise<void> = null;
25
- let sessionInfo: sessionInfoInterface = null;
26
- let sessionInfoResolver: (value: sessionInfoInterface) => void = null;
27
- const sessionInfoPromise = new Promise((resolve: (value: sessionInfoInterface) => void) => {
28
- sessionInfoResolver = resolve;
29
- });
26
+
30
27
  let releaseVersion = '';
31
28
 
32
29
  export const SSO_REDIRECTION_MARKER_GUID = '5e16222e-ef02-43e9-9fbd-24226bf3ce5b';
33
30
 
34
- interface sessionInfoInterface {
35
- userGUID: any;
36
- isPublicUser: any;
37
- mixpanelToken: any;
38
- [key: string]: any;
39
- }
40
-
41
31
  /**
42
32
  * Enum for auth failure types. This is the parameter passed to the listner
43
33
  * of {@link AuthStatus.FAILURE}.
@@ -180,12 +170,17 @@ export function notifyAuthSDKSuccess(): void {
180
170
  /**
181
171
  *
182
172
  */
183
- export function notifyAuthSuccess(): void {
173
+ export async function notifyAuthSuccess(): Promise<void> {
184
174
  if (!authEE) {
185
175
  logger.error('SDK not initialized');
186
176
  return;
187
177
  }
188
- authEE.emit(AuthStatus.SUCCESS, sessionInfo);
178
+ try {
179
+ const sessionInfo = await getSessionInfo();
180
+ authEE.emit(AuthStatus.SUCCESS, sessionInfo);
181
+ } catch (e) {
182
+ logger.error('Failed to get session info');
183
+ }
189
184
  }
190
185
 
191
186
  /**
@@ -211,70 +206,50 @@ export function notifyLogout(): void {
211
206
  authEE.emit(AuthStatus.LOGOUT);
212
207
  }
213
208
 
214
- export const initSession = (sessionDetails: sessionInfoInterface) => {
215
- const embedConfig = getEmbedConfig();
216
- if (sessionInfo == null) {
217
- sessionInfo = sessionDetails;
218
- if (!embedConfig.disableSDKTracking) {
219
- initMixpanel(sessionInfo);
220
- }
221
- sessionInfoResolver(sessionInfo);
222
- }
223
- };
224
-
225
- export const getSessionDetails = (sessionInfoResp: any): sessionInfoInterface => {
226
- const devMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.devSdkKey;
227
- const prodMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.prodSdkKey;
228
- const mixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.production
229
- ? prodMixpanelToken
230
- : devMixpanelToken;
231
- return {
232
- userGUID: sessionInfoResp.userGUID,
233
- mixpanelToken,
234
- isPublicUser: sessionInfoResp.configInfo.isPublicUser,
235
- releaseVersion: sessionInfoResp.releaseVersion,
236
- clusterId: sessionInfoResp.configInfo.selfClusterId,
237
- clusterName: sessionInfoResp.configInfo.selfClusterName,
238
- ...sessionInfoResp,
239
- };
240
- };
241
-
242
209
  /**
243
210
  * Check if we are logged into the ThoughtSpot cluster
244
211
  *
245
212
  * @param thoughtSpotHost The ThoughtSpot cluster hostname or IP
246
213
  */
247
214
  async function isLoggedIn(thoughtSpotHost: string): Promise<boolean> {
248
- const authVerificationUrl = `${thoughtSpotHost}${EndPoints.AUTH_VERIFICATION}`;
249
- let response = null;
250
215
  try {
251
- response = await fetchSessionInfoService(authVerificationUrl);
252
- const sessionInfoResp = await response.json();
253
- const sessionDetails = getSessionDetails(sessionInfoResp);
254
- // Store user session details from session info
255
- initSession(sessionDetails);
256
- releaseVersion = sessionInfoResp.releaseVersion;
216
+ const response = await isActiveService(thoughtSpotHost);
217
+ return response;
257
218
  } catch (e) {
258
219
  return false;
259
220
  }
260
- return response.status === 200;
261
221
  }
262
222
 
263
223
  /**
264
- * Return releaseVersion if available
224
+ * Services to be called after the login is successful,
225
+ * This should be called after the cookie is set for cookie auth or
226
+ * after the token is set for cookieless.
227
+ *
228
+ * @return {Promise<void>}
229
+ * @example
230
+ * ```js
231
+ * await postLoginService();
232
+ * ```
233
+ * @version SDK: 1.28.3 | ThoughtSpot: *
265
234
  */
266
- export function getReleaseVersion() {
267
- return releaseVersion;
235
+ export async function postLoginService(): Promise<void> {
236
+ try {
237
+ const sessionInfo = await getSessionInfo();
238
+ releaseVersion = sessionInfo.releaseVersion;
239
+ const embedConfig = getEmbedConfig();
240
+ if (!embedConfig.disableSDKTracking) {
241
+ initMixpanel(sessionInfo);
242
+ }
243
+ } catch (e) {
244
+ logger.error('Post login services failed', e.message);
245
+ }
268
246
  }
269
247
 
270
248
  /**
271
- * Return a promise that resolves with the session information when
272
- * authentication is successful. And info is available.
273
- *
274
- * @group Global methods
249
+ * Return releaseVersion if available
275
250
  */
276
- export function getSessionInfo(): Promise<sessionInfoInterface> {
277
- return sessionInfoPromise;
251
+ export function getReleaseVersion() {
252
+ return releaseVersion;
278
253
  }
279
254
 
280
255
  /**
@@ -309,8 +284,15 @@ export const doTokenAuth = async (embedConfig: EmbedConfig): Promise<boolean> =>
309
284
  throw new Error('Either auth endpoint or getAuthToken function must be provided');
310
285
  }
311
286
  loggedInStatus = await isLoggedIn(thoughtSpotHost);
287
+
312
288
  if (!loggedInStatus) {
313
- const authToken = await getAuthenticationToken(embedConfig);
289
+ let authToken: string;
290
+ try {
291
+ authToken = await getAuthenticationToken(embedConfig);
292
+ } catch (e) {
293
+ loggedInStatus = false;
294
+ throw e;
295
+ }
314
296
  let resp;
315
297
  try {
316
298
  resp = await fetchAuthPostService(thoughtSpotHost, username, authToken);
@@ -492,7 +474,7 @@ export const logout = async (embedConfig: EmbedConfig): Promise<boolean> => {
492
474
  const { thoughtSpotHost } = embedConfig;
493
475
  await fetchLogoutService(thoughtSpotHost);
494
476
  resetCachedAuthToken();
495
- const thoughtspotIframes = document.querySelectorAll('[data-ts-iframe=\'true\']');
477
+ const thoughtspotIframes = document.querySelectorAll("[data-ts-iframe='true']");
496
478
  if (thoughtspotIframes?.length) {
497
479
  thoughtspotIframes.forEach((el) => {
498
480
  el.parentElement.innerHTML = embedConfig.loginFailedMessage;
package/src/authToken.ts CHANGED
@@ -10,7 +10,7 @@ const INVALID_TOKEN_ERR = 'Invalid token received form token callback or authTok
10
10
  let cachedAuthToken: string | null = null;
11
11
 
12
12
  // This method can be used to get the authToken using the embedConfig
13
- export const getAuthenticationToken = async (embedConfig: EmbedConfig): Promise<string> => {
13
+ export async function getAuthenticationToken(embedConfig: EmbedConfig): Promise<string> {
14
14
  // Since we don't have token validation enabled , we cannot tell if the
15
15
  // cached token is valid or not. So we will always fetch a new token.
16
16
  if (cachedAuthToken && !embedConfig.disableTokenVerification) {
@@ -34,12 +34,17 @@ export const getAuthenticationToken = async (embedConfig: EmbedConfig): Promise<
34
34
  authToken = await response.text();
35
35
  }
36
36
 
37
- // this will throw error if the token is not valid
38
- await validateAuthToken(embedConfig, authToken);
37
+ try {
38
+ // this will throw error if the token is not valid
39
+ await validateAuthToken(embedConfig, authToken);
40
+ } catch (e) {
41
+ logger.error(`Received invalid token from getAuthToken callback or authToken endpoint. Error : ${e.message}`);
42
+ throw e;
43
+ }
39
44
 
40
45
  cachedAuthToken = authToken;
41
46
  return authToken;
42
- };
47
+ }
43
48
 
44
49
  const validateAuthToken = async (
45
50
  embedConfig: EmbedConfig,
@@ -24,6 +24,7 @@ import { version } from '../../package.json';
24
24
  import * as config from '../config';
25
25
  import { TsEmbed, V1Embed } from './ts-embed';
26
26
  import { logger } from '../utils/logger';
27
+ import * as auth from '../auth';
27
28
 
28
29
  const defaultViewConfig = {
29
30
  frameParams: {
@@ -40,6 +41,7 @@ beforeAll(() => {
40
41
  thoughtSpotHost,
41
42
  authType: AuthType.None,
42
43
  });
44
+ jest.spyOn(auth, 'postLoginService').mockImplementation(() => Promise.resolve({}));
43
45
  (window as any).ResizeObserver = window.ResizeObserver
44
46
  || jest.fn().mockImplementation(() => ({
45
47
  disconnect: jest.fn(),
@@ -72,13 +74,13 @@ describe('App embed tests', () => {
72
74
  test('should hide the primary nav bar', async () => {
73
75
  const appEmbed = new AppEmbed(getRootEl(), {
74
76
  ...defaultViewConfig,
75
- showPrimaryNavbar: true,
77
+ showPrimaryNavbar: false,
76
78
  } as AppViewConfig);
77
79
  appEmbed.render();
78
80
  await executeAfterWait(() => {
79
81
  expectUrlMatchesWithParams(
80
82
  getIFrameSrc(),
81
- `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=false&profileAndHelpInNavBarHidden=false${defaultParams}${defaultParamsPost}#/home`,
83
+ `http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false${defaultParams}${defaultParamsPost}#/home`,
82
84
  );
83
85
  });
84
86
  });
@@ -28,6 +28,7 @@ describe('Base TS Embed', () => {
28
28
  thoughtSpotHost,
29
29
  authType: index.AuthType.None,
30
30
  }) as EventEmitter;
31
+ jest.spyOn(auth, 'postLoginService').mockImplementation(() => Promise.resolve({}));
31
32
  });
32
33
 
33
34
  beforeEach(() => {
package/src/embed/base.ts CHANGED
@@ -30,6 +30,7 @@ import {
30
30
  notifyLogout,
31
31
  setAuthEE,
32
32
  AuthEventEmitter,
33
+ postLoginService,
33
34
  } from '../auth';
34
35
  import { uploadMixpanelEvent, MIXPANEL_EVENT } from '../mixpanel-service';
35
36
  import { getEmbedConfig, setEmbedConfig } from './embedConfig';
@@ -75,6 +76,8 @@ export const handleAuth = (): Promise<boolean> => {
75
76
  if (!isLoggedIn) {
76
77
  notifyAuthFailure(AuthFailureType.SDK);
77
78
  } else {
79
+ // Post login service is called after successful login.
80
+ postLoginService();
78
81
  notifyAuthSDKSuccess();
79
82
  }
80
83
  },
@@ -9,6 +9,7 @@ import {
9
9
  getIFrameEl,
10
10
  getRootEl,
11
11
  } from '../test/test-utils';
12
+ import * as authInstance from '../auth';
12
13
 
13
14
  const thoughtSpotHost = 'tshost';
14
15
  const defaultViewConfig = {
@@ -24,6 +25,7 @@ beforeAll(() => {
24
25
  authType: AuthType.None,
25
26
  });
26
27
  spyOn(window, 'alert');
28
+ jest.spyOn(authInstance, 'postLoginService').mockResolvedValue(true);
27
29
  });
28
30
 
29
31
  describe('test view config', () => {
@@ -20,6 +20,7 @@ import {
20
20
  postMessageToParent,
21
21
  } from '../test/test-utils';
22
22
  import { LiveboardViewConfig } from './liveboard';
23
+ import * as authInstance from '../auth';
23
24
 
24
25
  const thoughtSpotHost = 'tshost';
25
26
  const defaultViewConfig = {
@@ -36,6 +37,7 @@ beforeAll(() => {
36
37
  authType: AuthType.None,
37
38
  });
38
39
  spyOn(window, 'alert');
40
+ jest.spyOn(authInstance, 'postLoginService').mockReturnValue(true);
39
41
  });
40
42
 
41
43
  describe('test communication between host app and ThoughtSpot', () => {
@@ -23,6 +23,7 @@ import {
23
23
  } from '../test/test-utils';
24
24
  import * as tsEmbed from './ts-embed';
25
25
  import * as processTriggerInstance from '../utils/processTrigger';
26
+ import * as auth from '../auth';
26
27
 
27
28
  const defaultViewConfig = {
28
29
  frameParams: {
@@ -43,6 +44,7 @@ beforeAll(() => {
43
44
  thoughtSpotHost,
44
45
  authType: AuthType.None,
45
46
  });
47
+ jest.spyOn(auth, 'postLoginService').mockImplementation(() => Promise.resolve({}));
46
48
  });
47
49
 
48
50
  describe('Liveboard/viz embed tests', () => {
@@ -13,6 +13,7 @@ import {
13
13
  expectUrlMatchesWithParams,
14
14
  } from '../test/test-utils';
15
15
  import { version } from '../../package.json';
16
+ import * as auth from '../auth';
16
17
 
17
18
  const defaultViewConfig = {
18
19
  frameParams: {
@@ -30,6 +31,7 @@ beforeAll(() => {
30
31
  thoughtSpotHost,
31
32
  authType: AuthType.None,
32
33
  });
34
+ jest.spyOn(auth, 'postLoginService').mockReturnValue(true);
33
35
  });
34
36
 
35
37
  describe('Pinboard/viz embed tests', () => {
@@ -9,6 +9,8 @@ import {
9
9
  getRootEl,
10
10
  } from '../test/test-utils';
11
11
 
12
+ import * as authInstance from '../auth';
13
+
12
14
  const defaultConfig: SageViewConfig = {
13
15
  disableWorksheetChange: false,
14
16
  hideWorksheetSelector: false,
@@ -26,6 +28,7 @@ beforeAll(() => {
26
28
  authType: AuthType.None,
27
29
  });
28
30
  spyOn(window, 'alert');
31
+ jest.spyOn(authInstance, 'postLoginService').mockResolvedValue(true);
29
32
  });
30
33
 
31
34
  describe('Sage embed tests', () => {
@@ -36,6 +36,7 @@ beforeAll(() => {
36
36
  thoughtSpotHost,
37
37
  authType: AuthType.None,
38
38
  });
39
+ jest.spyOn(authInstance, 'postLoginService').mockImplementation(() => Promise.resolve({}));
39
40
  spyOn(window, 'alert');
40
41
  });
41
42
 
@@ -8,9 +8,12 @@ import {
8
8
  getRootEl,
9
9
  } from '../test/test-utils';
10
10
 
11
+ import * as authInstance from '../auth';
12
+
11
13
  describe('Trigger', () => {
12
14
  beforeEach(() => {
13
15
  document.body.innerHTML = getDocumentBody();
16
+ jest.spyOn(authInstance, 'postLoginService').mockResolvedValue(true);
14
17
  });
15
18
  test('should trigger the event', async (done) => {
16
19
  init({
@@ -83,6 +83,10 @@ describe('Unit test case for ts embed', () => {
83
83
  resetCachedAuthToken();
84
84
  });
85
85
 
86
+ beforeAll(() => {
87
+ jest.spyOn(authInstance, 'postLoginService').mockResolvedValue(true);
88
+ });
89
+
86
90
  describe('AuthExpire embedEvent in cookieless authentication authType', () => {
87
91
  beforeAll(() => {
88
92
  jest.spyOn(authInstance, 'doCookielessTokenAuth').mockResolvedValueOnce(true);
@@ -680,6 +684,7 @@ describe('Unit test case for ts embed', () => {
680
684
  const mockPort: any = {
681
685
  postMessage: jest.fn(),
682
686
  };
687
+ const loggerSpy = jest.spyOn(logger, 'error').mockResolvedValueOnce(true);
683
688
  await executeAfterWait(() => {
684
689
  const iframe = getIFrameEl();
685
690
  postMessageToParent(iframe.contentWindow, mockEmbedEventPayload, mockPort);
@@ -689,6 +694,7 @@ describe('Unit test case for ts embed', () => {
689
694
  expect(baseInstance.notifyAuthFailure).toBeCalledWith(
690
695
  authInstance.AuthFailureType.EXPIRY,
691
696
  );
697
+ expect(loggerSpy).toHaveBeenCalledTimes(1);
692
698
  });
693
699
 
694
700
  jest.spyOn(authService, 'verifyTokenService').mockClear();
@@ -707,6 +713,7 @@ describe('Unit test case for ts embed', () => {
707
713
  const searchEmbed = new SearchEmbed(getRootEl(), { ...defaultViewConfig, preRenderId: 'test' });
708
714
  jest.spyOn(baseInstance, 'notifyAuthFailure');
709
715
  searchEmbed.preRender();
716
+ const loggerSpy = jest.spyOn(logger, 'error').mockResolvedValueOnce(true);
710
717
  const mockPort: any = {
711
718
  postMessage: jest.fn(),
712
719
  };
@@ -720,6 +727,7 @@ describe('Unit test case for ts embed', () => {
720
727
  expect(baseInstance.notifyAuthFailure).toBeCalledWith(
721
728
  authInstance.AuthFailureType.EXPIRY,
722
729
  );
730
+ expect(loggerSpy).toHaveBeenCalledTimes(1);
723
731
  });
724
732
 
725
733
  jest.spyOn(authService, 'verifyTokenService').mockClear();
@@ -349,6 +349,7 @@ export class TsEmbed {
349
349
  data: { authToken },
350
350
  });
351
351
  } catch (e) {
352
+ logger.error(`Received invalid token. Error : ${e?.message}`);
352
353
  processAuthFailure(e, this.isPreRendered ? this.preRenderWrapper : this.el);
353
354
  }
354
355
  } else if (autoLogin) {
package/src/index.ts CHANGED
@@ -21,8 +21,9 @@ import { PinboardEmbed, LiveboardViewConfig, LiveboardEmbed } from './embed/live
21
21
  import { SearchEmbed, SearchViewConfig } from './embed/search';
22
22
  import { SearchBarEmbed, SearchBarViewConfig } from './embed/search-bar';
23
23
  import {
24
- AuthFailureType, AuthStatus, AuthEvent, AuthEventEmitter, getSessionInfo,
24
+ AuthFailureType, AuthStatus, AuthEvent, AuthEventEmitter,
25
25
  } from './auth';
26
+ import { getSessionInfo } from './utils/sessionInfoService';
26
27
  import {
27
28
  AuthType,
28
29
  RuntimeFilter,
@@ -6,6 +6,8 @@ import {
6
6
  testResetMixpanel,
7
7
  } from './mixpanel-service';
8
8
  import { AuthType } from './types';
9
+ import { SessionInfo } from './utils/sessionInfoService';
10
+ import { logger } from './utils/logger';
9
11
 
10
12
  const config = {
11
13
  thoughtSpotHost: 'https://10.87.89.232',
@@ -29,7 +31,7 @@ describe('Unit test for mixpanel', () => {
29
31
  mixpanelToken: 'abc123',
30
32
  userGUID: '12345',
31
33
  isPublicUser: false,
32
- };
34
+ } as SessionInfo;
33
35
  initMixpanel(sessionInfo);
34
36
  expect(mixpanel.init).toHaveBeenCalledWith(sessionInfo.mixpanelToken, undefined, 'tsEmbed');
35
37
  expect(mixpanel.identify).toHaveBeenCalledWith(sessionInfo.userGUID);
@@ -49,7 +51,7 @@ describe('Unit test for mixpanel', () => {
49
51
  clusterId: 'newClusterId',
50
52
  clusterName: 'newClusterName',
51
53
  releaseVersion: 'newReleaseVersion',
52
- };
54
+ } as SessionInfo;
53
55
  initMixpanel(sessionInfo);
54
56
 
55
57
  expect(mixpanel.init).toHaveBeenCalledWith(sessionInfo.mixpanelToken, undefined, 'tsEmbed');
@@ -74,8 +76,15 @@ describe('Unit test for mixpanel', () => {
74
76
  mixpanelToken: 'abc123',
75
77
  userGUID: '12345',
76
78
  isPublicUser: false,
77
- };
79
+ } as SessionInfo;
78
80
  initMixpanel(sessionInfo);
79
81
  expect(mixpanel.track).toHaveBeenCalledTimes(2);
80
82
  });
83
+
84
+ test('init mixpanel with no mixpanel token', () => {
85
+ jest.spyOn(logger, 'error').mockReturnValueOnce(true);
86
+ initMixpanel({ test: 'dummy' } as any);
87
+ expect(logger.error).toHaveBeenCalled();
88
+ expect(mixpanel.register_once).not.toHaveBeenCalled();
89
+ });
81
90
  });
@@ -1,5 +1,6 @@
1
1
  import * as mixpanel from 'mixpanel-browser';
2
2
  import { logger } from './utils/logger';
3
+ import { SessionInfo } from './utils/sessionInfoService';
3
4
 
4
5
  export const EndPoints = {
5
6
  CONFIG: '/callosum/v1/system/config',
@@ -55,8 +56,9 @@ function emptyQueue() {
55
56
  *
56
57
  * @param sessionInfo
57
58
  */
58
- export function initMixpanel(sessionInfo: any): void {
59
+ export function initMixpanel(sessionInfo: SessionInfo): void {
59
60
  if (!sessionInfo || !sessionInfo.mixpanelToken) {
61
+ logger.error('Mixpanel token not found in session info');
60
62
  return;
61
63
  }
62
64
  // On a public cluster the user is anonymous, so don't set the identify to
@@ -24,6 +24,9 @@ import {
24
24
 
25
25
  import { version } from '../../package.json';
26
26
 
27
+ import * as auth from '../auth';
28
+ import * as sessionService from '../utils/sessionInfoService';
29
+
27
30
  const thoughtSpotHost = 'localhost';
28
31
 
29
32
  beforeAll(() => {
@@ -31,6 +34,10 @@ beforeAll(() => {
31
34
  thoughtSpotHost,
32
35
  authType: AuthType.None,
33
36
  });
37
+ jest.spyOn(auth, 'postLoginService').mockReturnValue(true);
38
+ jest.spyOn(sessionService, 'getSessionInfo').mockReturnValue({
39
+ userGUID: 'abcd',
40
+ });
34
41
  spyOn(window, 'alert');
35
42
  });
36
43
 
@@ -381,4 +381,5 @@ export {
381
381
  HomeLeftNavItem,
382
382
  HomepageModule,
383
383
  LogLevel,
384
+ getSessionInfo,
384
385
  } from '../index';
package/src/types.ts CHANGED
@@ -2482,7 +2482,7 @@ export enum HostEvent {
2482
2482
  *
2483
2483
  * @example
2484
2484
  * ```js
2485
- * liveboardEmbed.trigger(HostEvent.getexportrequestforcurrentpinboard).then(
2485
+ * liveboardEmbed.trigger(HostEvent.getExportRequestForCurrentPinboard).then(
2486
2486
  * data=>console.log(data))
2487
2487
  * ```
2488
2488
  * @version SDK: 1.13.0 | ThoughtSpot: 8.5.0.cl, 8.8.1.sw
@@ -26,9 +26,10 @@ describe('Unit test for authService', () => {
26
26
  status: 200,
27
27
  ok: true,
28
28
  }));
29
- const response = await fetchSessionInfoService(authVerificationUrl);
30
- expect(response.status).toBe(200);
29
+ const response = await fetchSessionInfoService(thoughtSpotHost);
30
+ expect(response.success).toBe(true);
31
31
  expect(fetch).toHaveBeenCalledTimes(1);
32
+ expect(fetch).toBeCalledWith(`${thoughtSpotHost}${EndPoints.SESSION_INFO}`, {});
32
33
  });
33
34
 
34
35
  test('fetchAuthTokenService', async () => {
@@ -108,11 +109,15 @@ describe('Unit test for authService', () => {
108
109
  status: 500,
109
110
  ok: false,
110
111
  }));
111
- await fetchSessionInfoService(authVerificationUrl);
112
- expect(logger.error).toHaveBeenCalledWith('Failure', 'error');
112
+ try {
113
+ await fetchSessionInfoService(authVerificationUrl);
114
+ } catch (e) {
115
+ expect(e.message).toContain('Failed to fetch session info');
116
+ }
117
+ expect(logger.error).toHaveBeenCalledWith('Failed to fetch http://localhost:3000/callosum/v1/session/info', 'error');
113
118
  });
114
119
 
115
- test('verifyTokenService', async () => {
120
+ test('verifyTokenService if token api works', async () => {
116
121
  global.fetch = jest.fn(() => Promise.resolve({ success: true, ok: true }));
117
122
  await verifyTokenService(thoughtSpotHost, authToken);
118
123
  expect(fetch).toBeCalledWith(`${thoughtSpotHost}${EndPoints.IS_ACTIVE}`, {
@@ -123,4 +128,12 @@ describe('Unit test for authService', () => {
123
128
  },
124
129
  });
125
130
  });
131
+
132
+ test('verifyTokenService if token api fails', async () => {
133
+ global.fetch = jest.fn(() => Promise.reject(new Error('error')));
134
+ jest.spyOn(logger, 'warn');
135
+ const status = await verifyTokenService(thoughtSpotHost, authToken);
136
+ expect(status).toBe(false);
137
+ expect(logger.warn).toHaveBeenCalledWith('Token Verification Service failed : error');
138
+ });
126
139
  });
@@ -2,6 +2,7 @@ import { logger } from '../logger';
2
2
 
3
3
  export const EndPoints = {
4
4
  AUTH_VERIFICATION: '/callosum/v1/session/info',
5
+ SESSION_INFO: '/callosum/v1/session/info',
5
6
  SAML_LOGIN_TEMPLATE: (targetUrl: string) => `/callosum/v1/saml/login?targetURLPath=${targetUrl}`,
6
7
  OIDC_LOGIN_TEMPLATE: (targetUrl: string) => `/callosum/v1/oidc/login?targetURLPath=${targetUrl}`,
7
8
  TOKEN_LOGIN: '/callosum/v1/session/login/token',
@@ -0,0 +1,36 @@
1
+ import * as tokenizedFetchModule from '../../tokenizedFetch';
2
+ import { isActiveService } from './tokenizedAuthService';
3
+ import { logger } from '../logger';
4
+
5
+ describe('tokenizedAuthService', () => {
6
+ test('isActiveService is fetch returns ok', async () => {
7
+ jest.spyOn(tokenizedFetchModule, 'tokenizedFetch').mockResolvedValueOnce({
8
+ ok: true,
9
+ });
10
+
11
+ const isActiveResp = await isActiveService('http://thoughtspotHost');
12
+
13
+ expect(isActiveResp).toEqual(true);
14
+ });
15
+ test('isActiveService if fetch returns not ok', async () => {
16
+ jest.spyOn(tokenizedFetchModule, 'tokenizedFetch').mockResolvedValueOnce({
17
+ ok: false,
18
+ });
19
+
20
+ const isActiveResp = await isActiveService('http://thoughtspotHost');
21
+
22
+ expect(isActiveResp).toEqual(false);
23
+ });
24
+
25
+ test('isActiveService if fetch fails', async () => {
26
+ jest.spyOn(tokenizedFetchModule, 'tokenizedFetch').mockRejectedValueOnce({
27
+ ok: false,
28
+ });
29
+ jest.spyOn(logger, 'warn');
30
+
31
+ const isActiveResp = await isActiveService('http://thoughtspotHost');
32
+
33
+ expect(isActiveResp).toEqual(false);
34
+ expect(logger.warn).toHaveBeenCalled();
35
+ });
36
+ });