@thoughtspot/visual-embed-sdk 1.26.1 → 1.26.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 (267) hide show
  1. package/cjs/package.json +2 -2
  2. package/cjs/src/auth.d.ts +0 -12
  3. package/cjs/src/auth.d.ts.map +1 -1
  4. package/cjs/src/auth.js +16 -54
  5. package/cjs/src/auth.js.map +1 -1
  6. package/cjs/src/auth.spec.d.ts.map +1 -1
  7. package/cjs/src/auth.spec.js +42 -32
  8. package/cjs/src/auth.spec.js.map +1 -1
  9. package/cjs/src/authToken.d.ts +4 -0
  10. package/cjs/src/authToken.d.ts.map +1 -0
  11. package/cjs/src/authToken.js +61 -0
  12. package/cjs/src/authToken.js.map +1 -0
  13. package/cjs/src/embed/TsEmbed.d.ts +302 -0
  14. package/cjs/src/embed/TsEmbed.d.ts.map +1 -0
  15. package/cjs/src/embed/TsEmbed.js +851 -0
  16. package/cjs/src/embed/TsEmbed.js.map +1 -0
  17. package/cjs/src/embed/base.d.ts +0 -9
  18. package/cjs/src/embed/base.d.ts.map +1 -1
  19. package/cjs/src/embed/base.js +21 -44
  20. package/cjs/src/embed/base.js.map +1 -1
  21. package/cjs/src/embed/base.spec.js +15 -14
  22. package/cjs/src/embed/base.spec.js.map +1 -1
  23. package/cjs/src/embed/embedConfig.d.ts +18 -0
  24. package/cjs/src/embed/embedConfig.d.ts.map +1 -0
  25. package/cjs/src/embed/embedConfig.js +25 -0
  26. package/cjs/src/embed/embedConfig.js.map +1 -0
  27. package/cjs/src/embed/search.d.ts.map +1 -1
  28. package/cjs/src/embed/search.js +3 -1
  29. package/cjs/src/embed/search.js.map +1 -1
  30. package/cjs/src/embed/searchEmbed-basic-auth.spec.js +3 -2
  31. package/cjs/src/embed/searchEmbed-basic-auth.spec.js.map +1 -1
  32. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  33. package/cjs/src/embed/ts-embed.js +5 -3
  34. package/cjs/src/embed/ts-embed.js.map +1 -1
  35. package/cjs/src/embed/ts-embed.spec.js +58 -49
  36. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  37. package/cjs/src/index.d.ts +2 -1
  38. package/cjs/src/index.d.ts.map +1 -1
  39. package/cjs/src/index.js +2 -1
  40. package/cjs/src/index.js.map +1 -1
  41. package/cjs/src/tokenizedFetch.d.ts +2 -0
  42. package/cjs/src/tokenizedFetch.d.ts.map +1 -0
  43. package/cjs/src/tokenizedFetch.js +20 -0
  44. package/cjs/src/tokenizedFetch.js.map +1 -0
  45. package/cjs/src/types.d.ts +6 -0
  46. package/cjs/src/types.d.ts.map +1 -1
  47. package/cjs/src/types.js.map +1 -1
  48. package/cjs/src/utils/answerService.d.ts +10 -0
  49. package/cjs/src/utils/answerService.d.ts.map +1 -0
  50. package/cjs/src/utils/answerService.js +61 -0
  51. package/cjs/src/utils/answerService.js.map +1 -0
  52. package/cjs/src/utils/answerService.spec.d.ts +2 -0
  53. package/cjs/src/utils/answerService.spec.d.ts.map +1 -0
  54. package/cjs/src/utils/answerService.spec.js +31 -0
  55. package/cjs/src/utils/answerService.spec.js.map +1 -0
  56. package/cjs/src/utils/authService/authService.d.ts +45 -0
  57. package/cjs/src/utils/authService/authService.d.ts.map +1 -0
  58. package/cjs/src/utils/authService/authService.js +115 -0
  59. package/cjs/src/utils/authService/authService.js.map +1 -0
  60. package/cjs/src/utils/authService/authService.spec.d.ts +2 -0
  61. package/cjs/src/utils/authService/authService.spec.d.ts.map +1 -0
  62. package/cjs/src/utils/authService/authService.spec.js +82 -0
  63. package/cjs/src/utils/authService/authService.spec.js.map +1 -0
  64. package/cjs/src/utils/authService/index.d.ts +3 -0
  65. package/cjs/src/utils/authService/index.d.ts.map +1 -0
  66. package/cjs/src/utils/authService/index.js +14 -0
  67. package/cjs/src/utils/authService/index.js.map +1 -0
  68. package/cjs/src/utils/authService/tokenisedAuthSerice.d.ts +11 -0
  69. package/cjs/src/utils/authService/tokenisedAuthSerice.d.ts.map +1 -0
  70. package/cjs/src/utils/authService/tokenisedAuthSerice.js +44 -0
  71. package/cjs/src/utils/authService/tokenisedAuthSerice.js.map +1 -0
  72. package/cjs/src/utils/authService/tokenizedAuthService.d.ts +11 -0
  73. package/cjs/src/utils/authService/tokenizedAuthService.d.ts.map +1 -0
  74. package/cjs/src/utils/authService/tokenizedAuthService.js +44 -0
  75. package/cjs/src/utils/authService/tokenizedAuthService.js.map +1 -0
  76. package/cjs/src/utils/authService.d.ts +12 -1
  77. package/cjs/src/utils/authService.d.ts.map +1 -1
  78. package/cjs/src/utils/authService.js +32 -16
  79. package/cjs/src/utils/authService.js.map +1 -1
  80. package/cjs/src/utils/authService.spec.js +3 -4
  81. package/cjs/src/utils/authService.spec.js.map +1 -1
  82. package/cjs/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  83. package/cjs/src/utils/graphql/answerService/answerService.js +2 -1
  84. package/cjs/src/utils/graphql/answerService/answerService.js.map +1 -1
  85. package/cjs/src/utils/graphql/answerService/answerService.spec.js +15 -3
  86. package/cjs/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
  87. package/cjs/src/utils/graphql/graphql-request.spec.d.ts +2 -0
  88. package/cjs/src/utils/graphql/graphql-request.spec.d.ts.map +1 -0
  89. package/cjs/src/utils/graphql/graphql-request.spec.js +39 -0
  90. package/cjs/src/utils/graphql/graphql-request.spec.js.map +1 -0
  91. package/cjs/src/utils/logger.d.ts +28 -0
  92. package/cjs/src/utils/logger.d.ts.map +1 -0
  93. package/cjs/src/utils/logger.js +82 -0
  94. package/cjs/src/utils/logger.js.map +1 -0
  95. package/cjs/src/utils/processData.d.ts.map +1 -1
  96. package/cjs/src/utils/processData.js +5 -4
  97. package/cjs/src/utils/processData.js.map +1 -1
  98. package/cjs/src/utils/processData.spec.js +8 -7
  99. package/cjs/src/utils/processData.spec.js.map +1 -1
  100. package/dist/src/auth.d.ts +0 -12
  101. package/dist/src/auth.d.ts.map +1 -1
  102. package/dist/src/auth.spec.d.ts.map +1 -1
  103. package/dist/src/authToken.d.ts +4 -0
  104. package/dist/src/authToken.d.ts.map +1 -0
  105. package/dist/src/embed/base.d.ts +0 -9
  106. package/dist/src/embed/base.d.ts.map +1 -1
  107. package/dist/src/embed/embedConfig.d.ts +18 -0
  108. package/dist/src/embed/embedConfig.d.ts.map +1 -0
  109. package/dist/src/embed/search.d.ts.map +1 -1
  110. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  111. package/dist/src/index.d.ts +2 -1
  112. package/dist/src/index.d.ts.map +1 -1
  113. package/dist/src/tokenizedFetch.d.ts +2 -0
  114. package/dist/src/tokenizedFetch.d.ts.map +1 -0
  115. package/dist/src/types.d.ts +6 -0
  116. package/dist/src/types.d.ts.map +1 -1
  117. package/dist/src/utils/answerService.d.ts +10 -0
  118. package/dist/src/utils/answerService.d.ts.map +1 -0
  119. package/dist/src/utils/answerService.spec.d.ts +2 -0
  120. package/dist/src/utils/answerService.spec.d.ts.map +1 -0
  121. package/dist/src/utils/authService/authService.d.ts +45 -0
  122. package/dist/src/utils/authService/authService.d.ts.map +1 -0
  123. package/dist/src/utils/authService/authService.spec.d.ts +2 -0
  124. package/dist/src/utils/authService/authService.spec.d.ts.map +1 -0
  125. package/dist/src/utils/authService/index.d.ts +3 -0
  126. package/dist/src/utils/authService/index.d.ts.map +1 -0
  127. package/dist/src/utils/authService/tokenisedAuthSerice.d.ts +11 -0
  128. package/dist/src/utils/authService/tokenisedAuthSerice.d.ts.map +1 -0
  129. package/dist/src/utils/authService/tokenizedAuthService.d.ts +11 -0
  130. package/dist/src/utils/authService/tokenizedAuthService.d.ts.map +1 -0
  131. package/dist/src/utils/authService.d.ts +12 -1
  132. package/dist/src/utils/authService.d.ts.map +1 -1
  133. package/dist/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  134. package/dist/src/utils/graphql/graphql-request.spec.d.ts +2 -0
  135. package/dist/src/utils/graphql/graphql-request.spec.d.ts.map +1 -0
  136. package/dist/src/utils/logger.d.ts +28 -0
  137. package/dist/src/utils/logger.d.ts.map +1 -0
  138. package/dist/src/utils/processData.d.ts.map +1 -1
  139. package/dist/tsembed-react.es.js +201 -140
  140. package/dist/tsembed-react.js +201 -140
  141. package/dist/tsembed.es.js +230 -171
  142. package/dist/tsembed.js +230 -171
  143. package/dist/visual-embed-sdk-react-full.d.ts +23 -21
  144. package/dist/visual-embed-sdk-react.d.ts +23 -21
  145. package/dist/visual-embed-sdk.d.ts +23 -21
  146. package/lib/package.json +2 -2
  147. package/lib/src/auth.d.ts +0 -12
  148. package/lib/src/auth.d.ts.map +1 -1
  149. package/lib/src/auth.js +11 -48
  150. package/lib/src/auth.js.map +1 -1
  151. package/lib/src/auth.spec.d.ts.map +1 -1
  152. package/lib/src/auth.spec.js +42 -32
  153. package/lib/src/auth.spec.js.map +1 -1
  154. package/lib/src/authToken.d.ts +4 -0
  155. package/lib/src/authToken.d.ts.map +1 -0
  156. package/lib/src/authToken.js +56 -0
  157. package/lib/src/authToken.js.map +1 -0
  158. package/lib/src/embed/TsEmbed.d.ts +302 -0
  159. package/lib/src/embed/TsEmbed.d.ts.map +1 -0
  160. package/lib/src/embed/TsEmbed.js +847 -0
  161. package/lib/src/embed/TsEmbed.js.map +1 -0
  162. package/lib/src/embed/base.d.ts +0 -9
  163. package/lib/src/embed/base.d.ts.map +1 -1
  164. package/lib/src/embed/base.js +21 -43
  165. package/lib/src/embed/base.js.map +1 -1
  166. package/lib/src/embed/base.spec.js +15 -14
  167. package/lib/src/embed/base.spec.js.map +1 -1
  168. package/lib/src/embed/embedConfig.d.ts +18 -0
  169. package/lib/src/embed/embedConfig.d.ts.map +1 -0
  170. package/lib/src/embed/embedConfig.js +20 -0
  171. package/lib/src/embed/embedConfig.js.map +1 -0
  172. package/lib/src/embed/search.d.ts.map +1 -1
  173. package/lib/src/embed/search.js +4 -2
  174. package/lib/src/embed/search.js.map +1 -1
  175. package/lib/src/embed/searchEmbed-basic-auth.spec.js +3 -2
  176. package/lib/src/embed/searchEmbed-basic-auth.spec.js.map +1 -1
  177. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  178. package/lib/src/embed/ts-embed.js +4 -2
  179. package/lib/src/embed/ts-embed.js.map +1 -1
  180. package/lib/src/embed/ts-embed.spec.js +58 -49
  181. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  182. package/lib/src/index.d.ts +2 -1
  183. package/lib/src/index.d.ts.map +1 -1
  184. package/lib/src/index.js +2 -1
  185. package/lib/src/index.js.map +1 -1
  186. package/lib/src/tokenizedFetch.d.ts +2 -0
  187. package/lib/src/tokenizedFetch.d.ts.map +1 -0
  188. package/lib/src/tokenizedFetch.js +16 -0
  189. package/lib/src/tokenizedFetch.js.map +1 -0
  190. package/lib/src/types.d.ts +6 -0
  191. package/lib/src/types.d.ts.map +1 -1
  192. package/lib/src/types.js.map +1 -1
  193. package/lib/src/utils/answerService.d.ts +10 -0
  194. package/lib/src/utils/answerService.d.ts.map +1 -0
  195. package/lib/src/utils/answerService.js +57 -0
  196. package/lib/src/utils/answerService.js.map +1 -0
  197. package/lib/src/utils/answerService.spec.d.ts +2 -0
  198. package/lib/src/utils/answerService.spec.d.ts.map +1 -0
  199. package/lib/src/utils/answerService.spec.js +29 -0
  200. package/lib/src/utils/answerService.spec.js.map +1 -0
  201. package/lib/src/utils/authService/authService.d.ts +45 -0
  202. package/lib/src/utils/authService/authService.d.ts.map +1 -0
  203. package/lib/src/utils/authService/authService.js +107 -0
  204. package/lib/src/utils/authService/authService.js.map +1 -0
  205. package/lib/src/utils/authService/authService.spec.d.ts +2 -0
  206. package/lib/src/utils/authService/authService.spec.d.ts.map +1 -0
  207. package/lib/src/utils/authService/authService.spec.js +80 -0
  208. package/lib/src/utils/authService/authService.spec.js.map +1 -0
  209. package/lib/src/utils/authService/index.d.ts +3 -0
  210. package/lib/src/utils/authService/index.d.ts.map +1 -0
  211. package/lib/src/utils/authService/index.js +3 -0
  212. package/lib/src/utils/authService/index.js.map +1 -0
  213. package/lib/src/utils/authService/tokenisedAuthSerice.d.ts +11 -0
  214. package/lib/src/utils/authService/tokenisedAuthSerice.d.ts.map +1 -0
  215. package/lib/src/utils/authService/tokenisedAuthSerice.js +39 -0
  216. package/lib/src/utils/authService/tokenisedAuthSerice.js.map +1 -0
  217. package/lib/src/utils/authService/tokenizedAuthService.d.ts +11 -0
  218. package/lib/src/utils/authService/tokenizedAuthService.d.ts.map +1 -0
  219. package/lib/src/utils/authService/tokenizedAuthService.js +39 -0
  220. package/lib/src/utils/authService/tokenizedAuthService.js.map +1 -0
  221. package/lib/src/utils/authService.d.ts +12 -1
  222. package/lib/src/utils/authService.d.ts.map +1 -1
  223. package/lib/src/utils/authService.js +26 -10
  224. package/lib/src/utils/authService.js.map +1 -1
  225. package/lib/src/utils/authService.spec.js +1 -2
  226. package/lib/src/utils/authService.spec.js.map +1 -1
  227. package/lib/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  228. package/lib/src/utils/graphql/answerService/answerService.js +2 -1
  229. package/lib/src/utils/graphql/answerService/answerService.js.map +1 -1
  230. package/lib/src/utils/graphql/answerService/answerService.spec.js +14 -3
  231. package/lib/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
  232. package/lib/src/utils/graphql/graphql-request.spec.d.ts +2 -0
  233. package/lib/src/utils/graphql/graphql-request.spec.d.ts.map +1 -0
  234. package/lib/src/utils/graphql/graphql-request.spec.js +36 -0
  235. package/lib/src/utils/graphql/graphql-request.spec.js.map +1 -0
  236. package/lib/src/utils/logger.d.ts +28 -0
  237. package/lib/src/utils/logger.d.ts.map +1 -0
  238. package/lib/src/utils/logger.js +75 -0
  239. package/lib/src/utils/logger.js.map +1 -0
  240. package/lib/src/utils/processData.d.ts.map +1 -1
  241. package/lib/src/utils/processData.js +4 -3
  242. package/lib/src/utils/processData.js.map +1 -1
  243. package/lib/src/utils/processData.spec.js +8 -7
  244. package/lib/src/utils/processData.spec.js.map +1 -1
  245. package/lib/src/visual-embed-sdk.d.ts +28 -22
  246. package/package.json +2 -2
  247. package/src/auth.spec.ts +77 -63
  248. package/src/auth.ts +12 -55
  249. package/src/authToken.ts +66 -0
  250. package/src/embed/base.spec.ts +18 -17
  251. package/src/embed/base.ts +26 -51
  252. package/src/embed/embedConfig.ts +23 -0
  253. package/src/embed/search.ts +10 -10
  254. package/src/embed/searchEmbed-basic-auth.spec.ts +3 -2
  255. package/src/embed/ts-embed.spec.ts +87 -75
  256. package/src/embed/ts-embed.ts +11 -20
  257. package/src/index.ts +8 -2
  258. package/src/tokenizedFetch.ts +18 -0
  259. package/src/types.ts +34 -23
  260. package/src/utils/{authService.spec.ts → authService/authService.spec.ts} +2 -3
  261. package/src/utils/{authService.ts → authService/authService.ts} +29 -34
  262. package/src/utils/authService/index.ts +9 -0
  263. package/src/utils/authService/tokenizedAuthService.ts +40 -0
  264. package/src/utils/graphql/answerService/answerService.spec.ts +16 -4
  265. package/src/utils/graphql/answerService/answerService.ts +2 -1
  266. package/src/utils/processData.spec.ts +19 -16
  267. package/src/utils/processData.ts +3 -2
package/src/auth.ts CHANGED
@@ -4,16 +4,15 @@ import {
4
4
  AuthType, DOMSelector, EmbedConfig, EmbedEvent, Param,
5
5
  } from './types';
6
6
  import { getDOMNode, getRedirectUrl } from './utils';
7
- // eslint-disable-next-line import/no-cycle
8
7
  import {
9
8
  fetchSessionInfoService,
10
- fetchAuthTokenService,
11
9
  fetchAuthService,
12
10
  fetchBasicAuthService,
13
11
  fetchLogoutService,
14
12
  fetchAuthPostService,
15
- verifyTokenService,
13
+ EndPoints,
16
14
  } from './utils/authService';
15
+ import { getAuthenticationToken, resetCachedAuthToken } from './authToken';
17
16
 
18
17
  // eslint-disable-next-line import/no-mutable-exports
19
18
  export let loggedInStatus = false;
@@ -30,18 +29,6 @@ let releaseVersion = '';
30
29
 
31
30
  export const SSO_REDIRECTION_MARKER_GUID = '5e16222e-ef02-43e9-9fbd-24226bf3ce5b';
32
31
 
33
- export const EndPoints = {
34
- AUTH_VERIFICATION: '/callosum/v1/session/info',
35
- SAML_LOGIN_TEMPLATE: (targetUrl: string) => `/callosum/v1/saml/login?targetURLPath=${targetUrl}`,
36
- OIDC_LOGIN_TEMPLATE: (targetUrl: string) => `/callosum/v1/oidc/login?targetURLPath=${targetUrl}`,
37
- TOKEN_LOGIN: '/callosum/v1/session/login/token',
38
- BASIC_LOGIN: '/callosum/v1/session/login',
39
- LOGOUT: '/callosum/v1/session/logout',
40
- EXECUTE_TML: '/api/rest/2.0/metadata/tml/import',
41
- EXPORT_TML: '/api/rest/2.0/metadata/tml/export',
42
- IS_ACTIVE: '/callosum/v1/session/isactive',
43
- };
44
-
45
32
  interface sessionInfoInterface {
46
33
  userGUID: any;
47
34
  isPublicUser: any;
@@ -270,22 +257,6 @@ export function getSessionInfo(): Promise<sessionInfoInterface> {
270
257
  return sessionInfoPromise;
271
258
  }
272
259
 
273
- const DUPLICATE_TOKEN_ERR = 'Duplicate token, please issue a new token every time getAuthToken callback is called.'
274
- + 'See https://developers.thoughtspot.com/docs/?pageid=embed-auth#trusted-auth-embed for more details.';
275
- let prevAuthToken: string = null;
276
- /**
277
- *
278
- * @param authtoken
279
- */
280
- function alertForDuplicateToken(authtoken: string) {
281
- if (prevAuthToken === authtoken) {
282
- // eslint-disable-next-line no-alert
283
- alert(DUPLICATE_TOKEN_ERR);
284
- throw new Error(DUPLICATE_TOKEN_ERR);
285
- }
286
- prevAuthToken = authtoken;
287
- }
288
-
289
260
  /**
290
261
  * Check if we are stuck at the SSO redirect URL
291
262
  */
@@ -305,19 +276,6 @@ function removeSSORedirectUrlMarker(): void {
305
276
  window.location.hash = window.location.hash.replace(SSO_REDIRECTION_MARKER_GUID, '');
306
277
  }
307
278
 
308
- export const getAuthenticationToken = async (embedConfig: EmbedConfig): Promise<any> => {
309
- const { authEndpoint, getAuthToken } = embedConfig;
310
- let authToken = null;
311
- if (getAuthToken) {
312
- authToken = await getAuthToken();
313
- alertForDuplicateToken(authToken);
314
- } else {
315
- const response = await fetchAuthTokenService(authEndpoint);
316
- authToken = await response.text();
317
- }
318
- return authToken;
319
- };
320
-
321
279
  /**
322
280
  * Perform token based authentication
323
281
  *
@@ -360,15 +318,17 @@ export const doCookielessTokenAuth = async (embedConfig: EmbedConfig): Promise<b
360
318
  if (!authEndpoint && !getAuthToken) {
361
319
  throw new Error('Either auth endpoint or getAuthToken function must be provided');
362
320
  }
321
+ let authSuccess = false;
363
322
  try {
364
323
  const authToken = await getAuthenticationToken(embedConfig);
365
- const response = await verifyTokenService(embedConfig.thoughtSpotHost, authToken);
366
- if (!response.ok) return false;
367
- } catch (e) {
368
- return false;
324
+ if (authToken) {
325
+ authSuccess = true;
326
+ }
327
+ } catch {
328
+ authSuccess = false;
369
329
  }
370
330
 
371
- return true;
331
+ return authSuccess;
372
332
  };
373
333
 
374
334
  /**
@@ -462,11 +422,7 @@ const doSSOAuth = async (embedConfig: EmbedConfig, ssoEndPoint: string): Promise
462
422
 
463
423
  const ssoURL = `${thoughtSpotHost}${ssoEndPoint}`;
464
424
  if (embedConfig.inPopup) {
465
- await samlPopupFlow(
466
- ssoURL,
467
- embedConfig.authTriggerContainer,
468
- embedConfig.authTriggerText,
469
- );
425
+ await samlPopupFlow(ssoURL, embedConfig.authTriggerContainer, embedConfig.authTriggerText);
470
426
  loggedInStatus = await isLoggedIn(thoughtSpotHost);
471
427
  return;
472
428
  }
@@ -514,7 +470,8 @@ export const doOIDCAuth = async (embedConfig: EmbedConfig) => {
514
470
 
515
471
  export const logout = async (embedConfig: EmbedConfig): Promise<boolean> => {
516
472
  const { thoughtSpotHost } = embedConfig;
517
- const response = await fetchLogoutService(thoughtSpotHost);
473
+ await fetchLogoutService(thoughtSpotHost);
474
+ resetCachedAuthToken();
518
475
  loggedInStatus = false;
519
476
  return loggedInStatus;
520
477
  };
@@ -0,0 +1,66 @@
1
+ import { EmbedConfig } from './types';
2
+ import { fetchAuthTokenService, verifyTokenService } from './utils/authService/authService';
3
+
4
+ const DUPLICATE_TOKEN_ERR = 'Duplicate token, please issue a new token every time getAuthToken callback is called.'
5
+ + 'See https://developers.thoughtspot.com/docs/?pageid=embed-auth#trusted-auth-embed for more details.';
6
+
7
+ const INVALID_TOKEN_ERR = 'Invalid token received form token callback or authToken endpoint.';
8
+
9
+ let cachedAuthToken: string | null = null;
10
+
11
+ // This method can be used to get the authToken using the embedConfig
12
+ export const getAuthenticationToken = async (embedConfig: EmbedConfig): Promise<string> => {
13
+ if (cachedAuthToken) {
14
+ let isCachedTokenStillValid;
15
+ try {
16
+ isCachedTokenStillValid = await validateAuthToken(embedConfig, cachedAuthToken, true);
17
+ } catch {
18
+ isCachedTokenStillValid = false;
19
+ }
20
+
21
+ if (isCachedTokenStillValid) return cachedAuthToken;
22
+ }
23
+
24
+ const { authEndpoint, getAuthToken } = embedConfig;
25
+
26
+ let authToken = null;
27
+ if (getAuthToken) {
28
+ authToken = await getAuthToken();
29
+ } else {
30
+ const response = await fetchAuthTokenService(authEndpoint);
31
+ authToken = await response.text();
32
+ }
33
+
34
+ // this will throw error if the token is not valid
35
+ await validateAuthToken(embedConfig, authToken);
36
+
37
+ cachedAuthToken = authToken;
38
+ return authToken;
39
+ };
40
+
41
+ const validateAuthToken = async (
42
+ embedConfig: EmbedConfig,
43
+ authToken: string,
44
+ suppressAlert?: boolean,
45
+ ): Promise<boolean> => {
46
+ try {
47
+ const isTokenValid = await verifyTokenService(embedConfig.thoughtSpotHost, authToken);
48
+ if (isTokenValid) return true;
49
+ } catch {
50
+ return false;
51
+ }
52
+
53
+ if (cachedAuthToken && cachedAuthToken === authToken) {
54
+ if (!embedConfig.suppressErrorAlerts && !suppressAlert) {
55
+ // eslint-disable-next-line no-alert
56
+ alert(DUPLICATE_TOKEN_ERR);
57
+ }
58
+ throw new Error(DUPLICATE_TOKEN_ERR);
59
+ } else {
60
+ throw new Error(INVALID_TOKEN_ERR);
61
+ }
62
+ };
63
+
64
+ export const resetCachedAuthToken = (): void => {
65
+ cachedAuthToken = null;
66
+ };
@@ -3,16 +3,20 @@
3
3
  import EventEmitter from 'eventemitter3';
4
4
  import { EmbedConfig } from '../index';
5
5
  import * as auth from '../auth';
6
+ import * as authService from '../utils/authService/authService';
7
+ import * as authTokenService from '../authToken';
6
8
  import * as index from '../index';
7
9
  import * as base from './base';
10
+ import * as embedConfigInstance from './embedConfig';
11
+
8
12
  import {
9
13
  executeAfterWait,
10
14
  getAllIframeEl,
11
15
  getDocumentBody,
12
16
  getRootEl,
13
- getRootEl2,
14
17
  getIFrameSrc,
15
18
  } from '../test/test-utils';
19
+ import * as tokenizedFetchInstance from '../tokenizedFetch';
16
20
 
17
21
  const thoughtSpotHost = 'tshost';
18
22
  let authEE: EventEmitter;
@@ -107,7 +111,7 @@ describe('Base TS Embed', () => {
107
111
  };
108
112
  await index.executeTML(data);
109
113
  expect(window.fetch).toHaveBeenCalledWith(
110
- `http://${thoughtSpotHost}${auth.EndPoints.EXECUTE_TML}`,
114
+ `http://${thoughtSpotHost}${authService.EndPoints.EXECUTE_TML}`,
111
115
  {
112
116
  credentials: 'include',
113
117
  headers: {
@@ -121,32 +125,29 @@ describe('Base TS Embed', () => {
121
125
  });
122
126
 
123
127
  test('should call the executeTML API and import TML for cookiless auth', async () => {
124
- jest.spyOn(window, 'fetch').mockResolvedValue({
128
+ jest.spyOn(authTokenService, 'getAuthenticationToken').mockResolvedValue('mockAuthToken');
129
+ jest.spyOn(tokenizedFetchInstance, 'tokenizedFetch').mockResolvedValueOnce({
125
130
  ok: true,
126
131
  json: jest.fn().mockResolvedValue({}),
127
- text: jest.fn().mockResolvedValue('mockAuthToken'),
128
132
  });
129
133
  index.init({
130
134
  thoughtSpotHost,
131
135
  authType: index.AuthType.TrustedAuthTokenCookieless,
132
136
  autoLogin: true,
133
137
  });
134
- const embedConfig = base.getEmbedConfig();
135
- const authToken = await auth.getAuthenticationToken(embedConfig);
136
138
  const data: base.executeTMLInput = {
137
139
  metadata_tmls: ['{"liveboard":{"name":"Parameters Liveboard"}}'],
138
140
  import_policy: 'PARTIAL',
139
141
  create_new: false,
140
142
  };
141
143
  await index.executeTML(data);
142
- expect(window.fetch).toHaveBeenCalledWith(
143
- `http://${thoughtSpotHost}${auth.EndPoints.EXECUTE_TML}`,
144
+ expect(tokenizedFetchInstance.tokenizedFetch).toHaveBeenCalledWith(
145
+ `http://${thoughtSpotHost}${authService.EndPoints.EXECUTE_TML}`,
144
146
  {
145
147
  credentials: 'include',
146
148
  headers: expect.objectContaining({
147
149
  'Content-Type': 'application/json',
148
150
  'x-requested-by': 'ThoughtSpot',
149
- Authorization: `Bearer ${authToken}`,
150
151
  }),
151
152
  body: JSON.stringify(data),
152
153
  method: 'POST',
@@ -193,7 +194,7 @@ describe('Base TS Embed', () => {
193
194
  });
194
195
 
195
196
  test('should call the exportTML API and export TML', async () => {
196
- jest.spyOn(window, 'fetch').mockResolvedValue({
197
+ jest.spyOn(tokenizedFetchInstance, 'tokenizedFetch').mockResolvedValueOnce({
197
198
  ok: true,
198
199
  json: jest.fn().mockResolvedValue({}),
199
200
  });
@@ -209,8 +210,8 @@ describe('Base TS Embed', () => {
209
210
  edoc_format: 'YAML',
210
211
  };
211
212
  await index.exportTML(data);
212
- expect(window.fetch).toHaveBeenCalledWith(
213
- `http://${thoughtSpotHost}${auth.EndPoints.EXPORT_TML}`,
213
+ expect(tokenizedFetchInstance.tokenizedFetch).toHaveBeenCalledWith(
214
+ `http://${thoughtSpotHost}${authService.EndPoints.EXPORT_TML}`,
214
215
  {
215
216
  credentials: 'include',
216
217
  headers: {
@@ -341,7 +342,7 @@ describe('Base TS Embed', () => {
341
342
  });
342
343
 
343
344
  test('Logout method should disable autoLogin', () => {
344
- jest.spyOn(window, 'fetch').mockResolvedValue({
345
+ jest.spyOn(window, 'fetch').mockResolvedValueOnce({
345
346
  type: 'opaque',
346
347
  });
347
348
  index.init({
@@ -351,7 +352,7 @@ describe('Base TS Embed', () => {
351
352
  });
352
353
  index.logout();
353
354
  expect(window.fetch).toHaveBeenCalledWith(
354
- `http://${thoughtSpotHost}${auth.EndPoints.LOGOUT}`,
355
+ `http://${thoughtSpotHost}${authService.EndPoints.LOGOUT}`,
355
356
  {
356
357
  credentials: 'include',
357
358
  headers: {
@@ -360,7 +361,7 @@ describe('Base TS Embed', () => {
360
361
  method: 'POST',
361
362
  },
362
363
  );
363
- expect(base.getEmbedConfig().autoLogin).toBe(false);
364
+ expect(embedConfigInstance.getEmbedConfig().autoLogin).toBe(false);
364
365
  });
365
366
 
366
367
  test('config sanity, no ts host', () => {
@@ -395,7 +396,7 @@ describe('Base TS Embed', () => {
395
396
  thoughtSpotHost,
396
397
  noRedirect: true,
397
398
  });
398
- expect(base.getEmbedConfig().inPopup).toBe(true);
399
+ expect(embedConfigInstance.getEmbedConfig().inPopup).toBe(true);
399
400
  });
400
401
  test('config backward compat, should not override inPopup with noRedirect', () => {
401
402
  index.init({
@@ -404,7 +405,7 @@ describe('Base TS Embed', () => {
404
405
  noRedirect: true,
405
406
  inPopup: false,
406
407
  });
407
- expect(base.getEmbedConfig().inPopup).toBe(false);
408
+ expect(embedConfigInstance.getEmbedConfig().inPopup).toBe(false);
408
409
  });
409
410
  });
410
411
 
package/src/embed/base.ts CHANGED
@@ -10,6 +10,8 @@
10
10
  */
11
11
  import EventEmitter from 'eventemitter3';
12
12
  import uniq from 'lodash/uniq';
13
+ import { tokenizedFetch } from '../tokenizedFetch';
14
+ import { EndPoints } from '../utils/authService/authService';
13
15
  import { getThoughtSpotHost } from '../config';
14
16
  import { AuthType, EmbedConfig, PrefetchFeatures } from '../types';
15
17
  import {
@@ -24,12 +26,10 @@ import {
24
26
  notifyLogout,
25
27
  setAuthEE,
26
28
  AuthEventEmitter,
27
- EndPoints,
28
- getAuthenticationToken,
29
29
  } from '../auth';
30
30
  import { uploadMixpanelEvent, MIXPANEL_EVENT } from '../mixpanel-service';
31
+ import { getEmbedConfig, setEmbedConfig } from './embedConfig';
31
32
 
32
- let config = {} as EmbedConfig;
33
33
  const CONFIG_DEFAULTS: Partial<EmbedConfig> = {
34
34
  loginFailedMessage: 'Not logged in',
35
35
  authTriggerText: 'Authorize',
@@ -53,14 +53,6 @@ export interface exportTMLInput {
53
53
  }
54
54
 
55
55
  export let authPromise: Promise<boolean>;
56
- /**
57
- * Gets the configuration embed was initialized with.
58
- *
59
- * @returns {@link EmbedConfig} The configuration embed was initialized with.
60
- * @version SDK: 1.19.0 | ThoughtSpot: *
61
- * @group Global methods
62
- */
63
- export const getEmbedConfig = (): EmbedConfig => config;
64
56
 
65
57
  export const getAuthPromise = (): Promise<boolean> => authPromise;
66
58
 
@@ -72,7 +64,7 @@ export {
72
64
  * Perform authentication on the ThoughtSpot app as applicable.
73
65
  */
74
66
  export const handleAuth = (): Promise<boolean> => {
75
- authPromise = authenticate(config);
67
+ authPromise = authenticate(getEmbedConfig());
76
68
  authPromise.then(
77
69
  (isLoggedIn) => {
78
70
  if (!isLoggedIn) {
@@ -111,7 +103,7 @@ export const prefetch = (url?: string, prefetchFeatures?: PrefetchFeatures[]): v
111
103
  console.warn('The prefetch method does not have a valid URL');
112
104
  } else {
113
105
  const features = prefetchFeatures || [PrefetchFeatures.FullApp];
114
- let hostUrl = url || config.thoughtSpotHost;
106
+ let hostUrl = url || getEmbedConfig().thoughtSpotHost;
115
107
  hostUrl = hostUrl[hostUrl.length - 1] === '/' ? hostUrl : `${hostUrl}/`;
116
108
  uniq(features.map((feature) => hostUrlToFeatureUrl[feature](hostUrl))).forEach(
117
109
  (prefetchUrl, index) => {
@@ -182,17 +174,18 @@ function backwardCompat(embedConfig: EmbedConfig): EmbedConfig {
182
174
  */
183
175
  export const init = (embedConfig: EmbedConfig): AuthEventEmitter => {
184
176
  sanity(embedConfig);
185
- config = {
186
- ...CONFIG_DEFAULTS,
187
- ...embedConfig,
188
- thoughtSpotHost: getThoughtSpotHost(embedConfig),
189
- };
190
- config = backwardCompat(config);
177
+ setEmbedConfig(
178
+ backwardCompat({
179
+ ...CONFIG_DEFAULTS,
180
+ ...embedConfig,
181
+ thoughtSpotHost: getThoughtSpotHost(embedConfig),
182
+ }),
183
+ );
191
184
  const authEE = new EventEmitter<AuthStatus | AuthEvent>();
192
185
  setAuthEE(authEE);
193
186
  handleAuth();
194
187
 
195
- const { password, ...configToTrack } = config;
188
+ const { password, ...configToTrack } = getEmbedConfig();
196
189
  uploadMixpanelEvent(MIXPANEL_EVENT.VISUAL_SDK_CALLED_INIT, {
197
190
  ...configToTrack,
198
191
  usedCustomizationSheet: embedConfig.customizations?.style?.customCSSUrl != null,
@@ -203,8 +196,8 @@ export const init = (embedConfig: EmbedConfig): AuthEventEmitter => {
203
196
  usedCustomizationIconSprite: !!embedConfig.customizations?.iconSpriteUrl,
204
197
  });
205
198
 
206
- if (config.callPrefetch) {
207
- prefetch(config.thoughtSpotHost);
199
+ if (getEmbedConfig().callPrefetch) {
200
+ prefetch(getEmbedConfig().thoughtSpotHost);
208
201
  }
209
202
  return authEE as AuthEventEmitter;
210
203
  };
@@ -213,7 +206,7 @@ export const init = (embedConfig: EmbedConfig): AuthEventEmitter => {
213
206
  *
214
207
  */
215
208
  export function disableAutoLogin(): void {
216
- config.autoLogin = false;
209
+ getEmbedConfig().autoLogin = false;
217
210
  }
218
211
 
219
212
  /**
@@ -232,7 +225,7 @@ export const logout = (doNotDisableAutoLogin = false): Promise<boolean> => {
232
225
  if (!doNotDisableAutoLogin) {
233
226
  disableAutoLogin();
234
227
  }
235
- return _logout(config).then((isLoggedIn) => {
228
+ return _logout(getEmbedConfig()).then((isLoggedIn) => {
236
229
  notifyLogout();
237
230
  return isLoggedIn;
238
231
  });
@@ -247,13 +240,13 @@ let renderQueue: Promise<any> = Promise.resolve();
247
240
  * @param fn The function being registered
248
241
  */
249
242
  export const renderInQueue = (fn: (next?: (val?: any) => void) => Promise<any>): Promise<any> => {
250
- const { queueMultiRenders = false } = config;
243
+ const { queueMultiRenders = false } = getEmbedConfig();
251
244
  if (queueMultiRenders) {
252
245
  renderQueue = renderQueue.then(() => new Promise((res) => fn(res)));
253
246
  return renderQueue;
254
247
  }
255
248
  // Sending an empty function to keep it consistent with the above usage.
256
- return fn(() => { }); // eslint-disable-line @typescript-eslint/no-empty-function
249
+ return fn(() => {}); // eslint-disable-line @typescript-eslint/no-empty-function
257
250
  };
258
251
 
259
252
  /**
@@ -280,32 +273,24 @@ export const renderInQueue = (fn: (next?: (val?: any) => void) => Promise<any>):
280
273
  * @group Global methods
281
274
  */
282
275
  export const executeTML = async (data: executeTMLInput): Promise<any> => {
283
- const { thoughtSpotHost, authType } = config;
284
276
  try {
285
- sanity(config);
277
+ sanity(getEmbedConfig());
286
278
  } catch (err) {
287
279
  return Promise.reject(err);
288
280
  }
289
- let authToken = '';
290
- if (authType === AuthType.TrustedAuthTokenCookieless) {
291
- authToken = await getAuthenticationToken(config);
292
- }
293
281
 
282
+ const { thoughtSpotHost, authType } = getEmbedConfig();
294
283
  const headers: Record<string, string | undefined> = {
295
284
  'Content-Type': 'application/json',
296
285
  'x-requested-by': 'ThoughtSpot',
297
286
  };
298
287
 
299
- if (authToken) {
300
- headers.Authorization = `Bearer ${authToken}`;
301
- }
302
-
303
288
  const payload = {
304
289
  metadata_tmls: data.metadata_tmls,
305
290
  import_policy: data.import_policy || 'PARTIAL',
306
291
  create_new: data.create_new || false,
307
292
  };
308
- return fetch(`${thoughtSpotHost}${EndPoints.EXECUTE_TML}`, {
293
+ return tokenizedFetch(`${thoughtSpotHost}${EndPoints.EXECUTE_TML}`, {
309
294
  method: 'POST',
310
295
  headers,
311
296
  body: JSON.stringify(payload),
@@ -351,14 +336,13 @@ export const executeTML = async (data: executeTMLInput): Promise<any> => {
351
336
  console.error(error);
352
337
  });
353
338
  * ```
354
- *
355
339
  * @version SDK: 1.23.0 | ThoughtSpot: 9.4.0.cl
356
340
  * @group Global methods
357
341
  */
358
342
  export const exportTML = async (data: exportTMLInput): Promise<any> => {
359
- const { thoughtSpotHost, authType } = config;
343
+ const { thoughtSpotHost, authType } = getEmbedConfig();
360
344
  try {
361
- sanity(config);
345
+ sanity(getEmbedConfig());
362
346
  } catch (err) {
363
347
  return Promise.reject(err);
364
348
  }
@@ -369,21 +353,12 @@ export const exportTML = async (data: exportTMLInput): Promise<any> => {
369
353
  edoc_format: data.edoc_format || 'YAML',
370
354
  };
371
355
 
372
- let authToken = '';
373
- if (authType === AuthType.TrustedAuthTokenCookieless) {
374
- authToken = await getAuthenticationToken(config);
375
- }
376
-
377
356
  const headers: Record<string, string | undefined> = {
378
357
  'Content-Type': 'application/json',
379
358
  'x-requested-by': 'ThoughtSpot',
380
359
  };
381
360
 
382
- if (authToken) {
383
- headers.Authorization = `Bearer ${authToken}`;
384
- }
385
-
386
- return fetch(`${thoughtSpotHost}${EndPoints.EXPORT_TML}`, {
361
+ return tokenizedFetch(`${thoughtSpotHost}${EndPoints.EXPORT_TML}`, {
387
362
  method: 'POST',
388
363
  headers,
389
364
  body: JSON.stringify(payload),
@@ -407,7 +382,7 @@ export const exportTML = async (data: exportTMLInput): Promise<any> => {
407
382
  *
408
383
  */
409
384
  export function reset(): void {
410
- config = {} as any;
385
+ setEmbedConfig({} as any);
411
386
  setAuthEE(null);
412
387
  authPromise = null;
413
388
  }
@@ -0,0 +1,23 @@
1
+ import { EmbedConfig } from '../types';
2
+
3
+ let config = {} as EmbedConfig;
4
+
5
+ /**
6
+ * Gets the configuration embed was initialized with.
7
+ *
8
+ * @returns {@link EmbedConfig} The configuration embed was initialized with.
9
+ * @version SDK: 1.19.0 | ThoughtSpot: *
10
+ * @group Global methods
11
+ */
12
+ export const getEmbedConfig = (): EmbedConfig => config;
13
+
14
+ /**
15
+ * Sets the configuration embed was initialized with.
16
+ *
17
+ * @param newConfig The configuration to set.
18
+ * @version SDK: 1.27.0 | ThoughtSpot: *
19
+ * @group Global methods
20
+ */
21
+ export const setEmbedConfig = (newConfig: EmbedConfig) => {
22
+ config = newConfig;
23
+ };
@@ -8,12 +8,7 @@
8
8
  */
9
9
 
10
10
  import {
11
- DataSourceVisualMode,
12
- DOMSelector,
13
- Param,
14
- Action,
15
- ViewConfig,
16
- RuntimeFilter,
11
+ DataSourceVisualMode, DOMSelector, Param, Action, ViewConfig,
17
12
  } from '../types';
18
13
  import {
19
14
  getQueryParamString,
@@ -22,10 +17,10 @@ import {
22
17
  getRuntimeParameters,
23
18
  } from '../utils';
24
19
  import { TsEmbed } from './ts-embed';
25
- import { version } from '../../package.json';
26
20
  import { ERROR_MESSAGE } from '../errors';
27
- import { getAuthPromise, getEmbedConfig } from './base';
21
+ import { getAuthPromise } from './base';
28
22
  import { getReleaseVersion } from '../auth';
23
+ import { getEmbedConfig } from './embedConfig';
29
24
 
30
25
  /**
31
26
  * Configuration for search options
@@ -52,7 +47,11 @@ export interface SearchOptions {
52
47
  export interface SearchViewConfig
53
48
  extends Omit<
54
49
  ViewConfig,
55
- 'hiddenHomepageModules' | 'hiddenHomeLeftNavItems' | 'hiddenTabs' | 'visibleTabs' | 'reorderedHomepageModules'
50
+ | 'hiddenHomepageModules'
51
+ | 'hiddenHomeLeftNavItems'
52
+ | 'hiddenTabs'
53
+ | 'visibleTabs'
54
+ | 'reorderedHomepageModules'
56
55
  > {
57
56
  /**
58
57
  * If set to true, the data sources panel is collapsed on load,
@@ -274,7 +273,8 @@ export class SearchEmbed extends TsEmbed {
274
273
  if (
275
274
  checkReleaseVersionInBeta(
276
275
  getReleaseVersion(),
277
- getEmbedConfig().suppressSearchEmbedBetaWarning,
276
+ getEmbedConfig().suppressSearchEmbedBetaWarning
277
+ || getEmbedConfig().suppressErrorAlerts,
278
278
  )
279
279
  ) {
280
280
  alert(ERROR_MESSAGE.SEARCHEMBED_BETA_WRANING_MESSAGE);
@@ -3,6 +3,7 @@ import * as baseInstance from './base';
3
3
  import * as authService from '../utils/authService';
4
4
  import * as authInstance from '../auth';
5
5
  import * as config from '../config';
6
+ import * as embedConfigInstance from './embedConfig';
6
7
 
7
8
  import { init } from '../index';
8
9
  import { AuthType } from '../types';
@@ -86,7 +87,7 @@ describe('Search embed tests when authType is Basic', () => {
86
87
  test('Alert should not appear when suppressSearchEmbedBetaWarning is true and releaseVersion is ts7.dec.cl', async () => {
87
88
  setupVersion('ts7.dec.cl');
88
89
  jest.spyOn(config, 'getThoughtSpotHost').mockImplementation(() => 'http://tshost');
89
- jest.spyOn(baseInstance, 'getEmbedConfig').mockReturnValue({
90
+ jest.spyOn(embedConfigInstance, 'getEmbedConfig').mockReturnValue({
90
91
  suppressSearchEmbedBetaWarning: true,
91
92
  });
92
93
  const mockAlert = jest.spyOn(window, 'alert');
@@ -98,7 +99,7 @@ describe('Search embed tests when authType is Basic', () => {
98
99
  test('Alert should not appear when suppressSearchEmbedBetaWarning is true and releaseVersion is 8.4.0.sw', async () => {
99
100
  setupVersion('8.4.0.sw');
100
101
  jest.spyOn(config, 'getThoughtSpotHost').mockImplementation(() => 'http://tshost');
101
- jest.spyOn(baseInstance, 'getEmbedConfig').mockReturnValue({
102
+ jest.spyOn(embedConfigInstance, 'getEmbedConfig').mockReturnValue({
102
103
  suppressSearchEmbedBetaWarning: true,
103
104
  });
104
105
  const mockAlert = jest.spyOn(window, 'alert');