@thoughtspot/visual-embed-sdk 1.26.1 → 1.26.3

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 (243) 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/app.d.ts +0 -1
  14. package/cjs/src/embed/app.d.ts.map +1 -1
  15. package/cjs/src/embed/app.js +1 -1
  16. package/cjs/src/embed/app.js.map +1 -1
  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/liveboard.d.ts +0 -1
  28. package/cjs/src/embed/liveboard.d.ts.map +1 -1
  29. package/cjs/src/embed/liveboard.js +1 -1
  30. package/cjs/src/embed/liveboard.js.map +1 -1
  31. package/cjs/src/embed/sage.d.ts +0 -1
  32. package/cjs/src/embed/sage.d.ts.map +1 -1
  33. package/cjs/src/embed/sage.js +1 -1
  34. package/cjs/src/embed/sage.js.map +1 -1
  35. package/cjs/src/embed/search.d.ts +0 -1
  36. package/cjs/src/embed/search.d.ts.map +1 -1
  37. package/cjs/src/embed/search.js +5 -4
  38. package/cjs/src/embed/search.js.map +1 -1
  39. package/cjs/src/embed/searchEmbed-basic-auth.spec.js +3 -2
  40. package/cjs/src/embed/searchEmbed-basic-auth.spec.js.map +1 -1
  41. package/cjs/src/embed/ts-embed.d.ts +0 -1
  42. package/cjs/src/embed/ts-embed.d.ts.map +1 -1
  43. package/cjs/src/embed/ts-embed.js +6 -6
  44. package/cjs/src/embed/ts-embed.js.map +1 -1
  45. package/cjs/src/embed/ts-embed.spec.js +58 -49
  46. package/cjs/src/embed/ts-embed.spec.js.map +1 -1
  47. package/cjs/src/index.d.ts +2 -1
  48. package/cjs/src/index.d.ts.map +1 -1
  49. package/cjs/src/index.js +2 -1
  50. package/cjs/src/index.js.map +1 -1
  51. package/cjs/src/tokenizedFetch.d.ts +2 -0
  52. package/cjs/src/tokenizedFetch.d.ts.map +1 -0
  53. package/cjs/src/tokenizedFetch.js +20 -0
  54. package/cjs/src/tokenizedFetch.js.map +1 -0
  55. package/cjs/src/types.d.ts +12 -0
  56. package/cjs/src/types.d.ts.map +1 -1
  57. package/cjs/src/types.js.map +1 -1
  58. package/cjs/src/utils/{authService.d.ts → authService/authService.d.ts} +12 -11
  59. package/cjs/src/utils/authService/authService.d.ts.map +1 -0
  60. package/cjs/src/utils/{authService.js → authService/authService.js} +31 -39
  61. package/cjs/src/utils/authService/authService.js.map +1 -0
  62. package/cjs/src/utils/authService/authService.spec.d.ts.map +1 -0
  63. package/cjs/src/utils/{authService.spec.js → authService/authService.spec.js} +11 -12
  64. package/cjs/src/utils/authService/authService.spec.js.map +1 -0
  65. package/cjs/src/utils/authService/index.d.ts +3 -0
  66. package/cjs/src/utils/authService/index.d.ts.map +1 -0
  67. package/cjs/src/utils/authService/index.js +14 -0
  68. package/cjs/src/utils/authService/index.js.map +1 -0
  69. package/cjs/src/utils/authService/tokenizedAuthService.d.ts +11 -0
  70. package/cjs/src/utils/authService/tokenizedAuthService.d.ts.map +1 -0
  71. package/cjs/src/utils/authService/tokenizedAuthService.js +44 -0
  72. package/cjs/src/utils/authService/tokenizedAuthService.js.map +1 -0
  73. package/cjs/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  74. package/cjs/src/utils/graphql/answerService/answerService.js +2 -1
  75. package/cjs/src/utils/graphql/answerService/answerService.js.map +1 -1
  76. package/cjs/src/utils/graphql/answerService/answerService.spec.js +15 -3
  77. package/cjs/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
  78. package/cjs/src/utils/processData.d.ts.map +1 -1
  79. package/cjs/src/utils/processData.js +5 -4
  80. package/cjs/src/utils/processData.js.map +1 -1
  81. package/cjs/src/utils/processData.spec.js +8 -7
  82. package/cjs/src/utils/processData.spec.js.map +1 -1
  83. package/dist/src/auth.d.ts +0 -12
  84. package/dist/src/auth.d.ts.map +1 -1
  85. package/dist/src/auth.spec.d.ts.map +1 -1
  86. package/dist/src/authToken.d.ts +4 -0
  87. package/dist/src/authToken.d.ts.map +1 -0
  88. package/dist/src/embed/app.d.ts +0 -1
  89. package/dist/src/embed/app.d.ts.map +1 -1
  90. package/dist/src/embed/base.d.ts +0 -9
  91. package/dist/src/embed/base.d.ts.map +1 -1
  92. package/dist/src/embed/embedConfig.d.ts +18 -0
  93. package/dist/src/embed/embedConfig.d.ts.map +1 -0
  94. package/dist/src/embed/liveboard.d.ts +0 -1
  95. package/dist/src/embed/liveboard.d.ts.map +1 -1
  96. package/dist/src/embed/sage.d.ts +0 -1
  97. package/dist/src/embed/sage.d.ts.map +1 -1
  98. package/dist/src/embed/search.d.ts +0 -1
  99. package/dist/src/embed/search.d.ts.map +1 -1
  100. package/dist/src/embed/ts-embed.d.ts +0 -1
  101. package/dist/src/embed/ts-embed.d.ts.map +1 -1
  102. package/dist/src/index.d.ts +2 -1
  103. package/dist/src/index.d.ts.map +1 -1
  104. package/dist/src/tokenizedFetch.d.ts +2 -0
  105. package/dist/src/tokenizedFetch.d.ts.map +1 -0
  106. package/dist/src/types.d.ts +12 -0
  107. package/dist/src/types.d.ts.map +1 -1
  108. package/{lib/src/utils → dist/src/utils/authService}/authService.d.ts +44 -43
  109. package/dist/src/utils/authService/authService.d.ts.map +1 -0
  110. package/dist/src/utils/authService/index.d.ts +3 -0
  111. package/dist/src/utils/authService/index.d.ts.map +1 -0
  112. package/dist/src/utils/authService/tokenizedAuthService.d.ts +11 -0
  113. package/dist/src/utils/authService/tokenizedAuthService.d.ts.map +1 -0
  114. package/dist/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  115. package/dist/src/utils/processData.d.ts.map +1 -1
  116. package/dist/tsembed-react.es.js +207 -149
  117. package/dist/tsembed-react.js +207 -149
  118. package/dist/tsembed.es.js +236 -180
  119. package/dist/tsembed.js +236 -180
  120. package/dist/visual-embed-sdk-react-full.d.ts +29 -26
  121. package/dist/visual-embed-sdk-react.d.ts +29 -26
  122. package/dist/visual-embed-sdk.d.ts +29 -26
  123. package/lib/package.json +2 -2
  124. package/lib/src/auth.d.ts +0 -12
  125. package/lib/src/auth.d.ts.map +1 -1
  126. package/lib/src/auth.js +11 -48
  127. package/lib/src/auth.js.map +1 -1
  128. package/lib/src/auth.spec.d.ts.map +1 -1
  129. package/lib/src/auth.spec.js +42 -32
  130. package/lib/src/auth.spec.js.map +1 -1
  131. package/lib/src/authToken.d.ts +4 -0
  132. package/lib/src/authToken.d.ts.map +1 -0
  133. package/lib/src/authToken.js +56 -0
  134. package/lib/src/authToken.js.map +1 -0
  135. package/lib/src/embed/app.d.ts +0 -1
  136. package/lib/src/embed/app.d.ts.map +1 -1
  137. package/lib/src/embed/app.js +1 -1
  138. package/lib/src/embed/app.js.map +1 -1
  139. package/lib/src/embed/base.d.ts +0 -9
  140. package/lib/src/embed/base.d.ts.map +1 -1
  141. package/lib/src/embed/base.js +21 -43
  142. package/lib/src/embed/base.js.map +1 -1
  143. package/lib/src/embed/base.spec.js +15 -14
  144. package/lib/src/embed/base.spec.js.map +1 -1
  145. package/lib/src/embed/embedConfig.d.ts +18 -0
  146. package/lib/src/embed/embedConfig.d.ts.map +1 -0
  147. package/lib/src/embed/embedConfig.js +20 -0
  148. package/lib/src/embed/embedConfig.js.map +1 -0
  149. package/lib/src/embed/liveboard.d.ts +0 -1
  150. package/lib/src/embed/liveboard.d.ts.map +1 -1
  151. package/lib/src/embed/liveboard.js +1 -1
  152. package/lib/src/embed/liveboard.js.map +1 -1
  153. package/lib/src/embed/sage.d.ts +0 -1
  154. package/lib/src/embed/sage.d.ts.map +1 -1
  155. package/lib/src/embed/sage.js +1 -1
  156. package/lib/src/embed/sage.js.map +1 -1
  157. package/lib/src/embed/search.d.ts +0 -1
  158. package/lib/src/embed/search.d.ts.map +1 -1
  159. package/lib/src/embed/search.js +6 -5
  160. package/lib/src/embed/search.js.map +1 -1
  161. package/lib/src/embed/searchEmbed-basic-auth.spec.js +3 -2
  162. package/lib/src/embed/searchEmbed-basic-auth.spec.js.map +1 -1
  163. package/lib/src/embed/ts-embed.d.ts +0 -1
  164. package/lib/src/embed/ts-embed.d.ts.map +1 -1
  165. package/lib/src/embed/ts-embed.js +5 -5
  166. package/lib/src/embed/ts-embed.js.map +1 -1
  167. package/lib/src/embed/ts-embed.spec.js +58 -49
  168. package/lib/src/embed/ts-embed.spec.js.map +1 -1
  169. package/lib/src/index.d.ts +2 -1
  170. package/lib/src/index.d.ts.map +1 -1
  171. package/lib/src/index.js +2 -1
  172. package/lib/src/index.js.map +1 -1
  173. package/lib/src/tokenizedFetch.d.ts +2 -0
  174. package/lib/src/tokenizedFetch.d.ts.map +1 -0
  175. package/lib/src/tokenizedFetch.js +16 -0
  176. package/lib/src/tokenizedFetch.js.map +1 -0
  177. package/lib/src/types.d.ts +12 -0
  178. package/lib/src/types.d.ts.map +1 -1
  179. package/lib/src/types.js.map +1 -1
  180. package/{dist/src/utils → lib/src/utils/authService}/authService.d.ts +44 -43
  181. package/lib/src/utils/authService/authService.d.ts.map +1 -0
  182. package/lib/src/utils/{authService.js → authService/authService.js} +26 -32
  183. package/lib/src/utils/authService/authService.js.map +1 -0
  184. package/lib/src/utils/authService/authService.spec.d.ts.map +1 -0
  185. package/lib/src/utils/{authService.spec.js → authService/authService.spec.js} +1 -2
  186. package/lib/src/utils/authService/authService.spec.js.map +1 -0
  187. package/lib/src/utils/authService/index.d.ts +3 -0
  188. package/lib/src/utils/authService/index.d.ts.map +1 -0
  189. package/lib/src/utils/authService/index.js +3 -0
  190. package/lib/src/utils/authService/index.js.map +1 -0
  191. package/lib/src/utils/authService/tokenizedAuthService.d.ts +11 -0
  192. package/lib/src/utils/authService/tokenizedAuthService.d.ts.map +1 -0
  193. package/lib/src/utils/authService/tokenizedAuthService.js +39 -0
  194. package/lib/src/utils/authService/tokenizedAuthService.js.map +1 -0
  195. package/lib/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
  196. package/lib/src/utils/graphql/answerService/answerService.js +2 -1
  197. package/lib/src/utils/graphql/answerService/answerService.js.map +1 -1
  198. package/lib/src/utils/graphql/answerService/answerService.spec.js +14 -3
  199. package/lib/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
  200. package/lib/src/utils/processData.d.ts.map +1 -1
  201. package/lib/src/utils/processData.js +4 -3
  202. package/lib/src/utils/processData.js.map +1 -1
  203. package/lib/src/utils/processData.spec.js +8 -7
  204. package/lib/src/utils/processData.spec.js.map +1 -1
  205. package/lib/src/visual-embed-sdk.d.ts +34 -27
  206. package/package.json +2 -2
  207. package/src/auth.spec.ts +77 -63
  208. package/src/auth.ts +12 -55
  209. package/src/authToken.ts +66 -0
  210. package/src/embed/app.ts +1 -2
  211. package/src/embed/base.spec.ts +18 -17
  212. package/src/embed/base.ts +26 -51
  213. package/src/embed/embedConfig.ts +23 -0
  214. package/src/embed/liveboard.ts +1 -2
  215. package/src/embed/sage.ts +1 -2
  216. package/src/embed/search.ts +12 -14
  217. package/src/embed/searchEmbed-basic-auth.spec.ts +3 -2
  218. package/src/embed/ts-embed.spec.ts +87 -75
  219. package/src/embed/ts-embed.ts +7 -19
  220. package/src/index.ts +8 -2
  221. package/src/tokenizedFetch.ts +18 -0
  222. package/src/types.ts +36 -19
  223. package/src/utils/{authService.spec.ts → authService/authService.spec.ts} +2 -3
  224. package/src/utils/{authService.ts → authService/authService.ts} +29 -34
  225. package/src/utils/authService/index.ts +9 -0
  226. package/src/utils/authService/tokenizedAuthService.ts +40 -0
  227. package/src/utils/graphql/answerService/answerService.spec.ts +16 -4
  228. package/src/utils/graphql/answerService/answerService.ts +2 -1
  229. package/src/utils/processData.spec.ts +19 -16
  230. package/src/utils/processData.ts +3 -2
  231. package/cjs/src/utils/authService.d.ts.map +0 -1
  232. package/cjs/src/utils/authService.js.map +0 -1
  233. package/cjs/src/utils/authService.spec.d.ts.map +0 -1
  234. package/cjs/src/utils/authService.spec.js.map +0 -1
  235. package/dist/src/utils/authService.d.ts.map +0 -1
  236. package/lib/src/utils/authService.d.ts.map +0 -1
  237. package/lib/src/utils/authService.js.map +0 -1
  238. package/lib/src/utils/authService.spec.d.ts.map +0 -1
  239. package/lib/src/utils/authService.spec.js.map +0 -1
  240. /package/cjs/src/utils/{authService.spec.d.ts → authService/authService.spec.d.ts} +0 -0
  241. /package/dist/src/utils/{authService.spec.d.ts → authService/authService.spec.d.ts} +0 -0
  242. /package/dist/src/utils/{authService.spec.d.ts.map → authService/authService.spec.d.ts.map} +0 -0
  243. /package/lib/src/utils/{authService.spec.d.ts → authService/authService.spec.d.ts} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thoughtspot/visual-embed-sdk",
3
- "version": "1.26.1",
3
+ "version": "1.26.3",
4
4
  "description": "ThoughtSpot Embed SDK",
5
5
  "module": "lib/src/index.js",
6
6
  "main": "dist/tsembed.js",
@@ -38,7 +38,7 @@
38
38
  "size-limit": [
39
39
  {
40
40
  "path": "dist/tsembed.js",
41
- "limit": "43 kB"
41
+ "limit": "44 kB"
42
42
  }
43
43
  ],
44
44
  "scripts": {
package/src/auth.spec.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  import * as authInstance from './auth';
2
- import * as authService from './utils/authService';
2
+ import * as authService from './utils/authService/authService';
3
+ import * as tokenAuthService from './utils/authService/tokenizedAuthService';
3
4
  import * as checkReleaseVersionInBetaInstance from './utils';
4
5
  import * as mixPanelService from './mixpanel-service';
5
6
  import { AuthType, EmbedEvent } from './types';
6
7
  import { executeAfterWait } from './test/test-utils';
8
+ import { resetCachedAuthToken } from './authToken';
7
9
 
8
10
  const thoughtSpotHost = 'http://localhost:3000';
9
11
  const username = 'tsuser';
@@ -94,7 +96,6 @@ export const embedConfig: any = {
94
96
  authType: AuthType.TrustedAuthTokenCookieless,
95
97
  getAuthToken: jest.fn(() => Promise.resolve(token)),
96
98
  }),
97
-
98
99
  };
99
100
 
100
101
  const originalWindow = window;
@@ -114,9 +115,11 @@ describe('Unit test for auth', () => {
114
115
  beforeEach(() => {
115
116
  global.fetch = window.fetch;
116
117
  });
117
-
118
+ afterEach(() => {
119
+ resetCachedAuthToken();
120
+ });
118
121
  test('endpoints, SAML_LOGIN_TEMPLATE', () => {
119
- const ssoTemplateUrl = authInstance.EndPoints.SAML_LOGIN_TEMPLATE(thoughtSpotHost);
122
+ const ssoTemplateUrl = authService.EndPoints.SAML_LOGIN_TEMPLATE(thoughtSpotHost);
120
123
  expect(ssoTemplateUrl).toBe(`/callosum/v1/saml/login?targetURLPath=${thoughtSpotHost}`);
121
124
  });
122
125
 
@@ -150,31 +153,28 @@ describe('Unit test for auth', () => {
150
153
  });
151
154
 
152
155
  test('doTokenAuth: when user is loggedIn', async () => {
153
- jest.spyOn(authService, 'fetchSessionInfoService').mockImplementation(
154
- async () => ({
155
- json: () => mockSessionInfo,
156
- status: 200,
157
- }),
158
- );
156
+ jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockImplementation(async () => ({
157
+ json: () => mockSessionInfo,
158
+ status: 200,
159
+ }));
159
160
  jest.spyOn(authInstance, 'getSessionDetails').mockReturnValue(mockSessionInfo);
160
161
  jest.spyOn(authInstance, 'initSession').mockReturnValue(null);
161
- await authInstance.doTokenAuth(
162
- embedConfig.doTokenAuthSuccess('authToken'),
163
- );
164
- expect(authService.fetchSessionInfoService).toBeCalled();
162
+ await authInstance.doTokenAuth(embedConfig.doTokenAuthSuccess('authToken'));
163
+ expect(tokenAuthService.fetchSessionInfoService).toBeCalled();
165
164
  expect(authInstance.loggedInStatus).toBe(true);
166
165
  });
167
166
 
168
167
  test('doTokenAuth: when user is not loggedIn & getAuthToken have response', async () => {
169
- jest.spyOn(authService, 'fetchSessionInfoService').mockImplementation(() => false);
168
+ jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockImplementation(() => false);
170
169
  jest.spyOn(authService, 'fetchAuthTokenService').mockImplementation(() => ({
171
170
  text: () => Promise.resolve('abc'),
172
171
  }));
173
172
  jest.spyOn(authService, 'fetchAuthService').mockImplementation(() => Promise.resolve({
174
173
  status: 200,
175
174
  }));
175
+ jest.spyOn(authService, 'verifyTokenService').mockResolvedValueOnce(true);
176
176
  await authInstance.doTokenAuth(embedConfig.doTokenAuthSuccess('authToken2'));
177
- expect(authService.fetchSessionInfoService).toBeCalled();
177
+ expect(tokenAuthService.fetchSessionInfoService).toBeCalled();
178
178
  expect(authService.fetchAuthService).toBeCalledWith(
179
179
  thoughtSpotHost,
180
180
  username,
@@ -183,22 +183,27 @@ describe('Unit test for auth', () => {
183
183
  });
184
184
 
185
185
  test('doTokenAuth: when user is not loggedIn & getAuthToken not present, isLoggedIn should called', async () => {
186
- jest.spyOn(authService, 'fetchSessionInfoService').mockImplementation(() => false);
186
+ jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockImplementation(() => false);
187
187
  jest.spyOn(authService, 'fetchAuthTokenService').mockImplementation(() => Promise.resolve({ text: () => Promise.resolve('abc') }));
188
188
  jest.spyOn(authService, 'fetchAuthService').mockImplementation(() => Promise.resolve({
189
189
  status: 200,
190
190
  ok: true,
191
191
  }));
192
+ jest.spyOn(authService, 'verifyTokenService').mockResolvedValueOnce(true);
192
193
  await authInstance.doTokenAuth(embedConfig.doTokenAuthFailureWithoutGetAuthToken);
193
194
  await executeAfterWait(() => {
194
195
  expect(authInstance.loggedInStatus).toBe(true);
195
- expect(authService.fetchSessionInfoService).toBeCalled();
196
- expect(authService.fetchAuthService).toBeCalledWith(thoughtSpotHost, username, 'abc');
196
+ expect(tokenAuthService.fetchSessionInfoService).toBeCalled();
197
+ expect(authService.fetchAuthService).toBeCalledWith(
198
+ thoughtSpotHost,
199
+ username,
200
+ 'authToken2',
201
+ );
197
202
  });
198
203
  });
199
204
 
200
205
  test('doTokenAuth: Should raise error when duplicate token is used', async () => {
201
- jest.spyOn(authService, 'fetchSessionInfoService').mockResolvedValue({
206
+ jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockResolvedValue({
202
207
  status: 401,
203
208
  });
204
209
  jest.spyOn(window, 'alert').mockClear();
@@ -208,9 +213,11 @@ describe('Unit test for auth', () => {
208
213
  status: 200,
209
214
  ok: true,
210
215
  }));
216
+ jest.spyOn(authService, 'verifyTokenService').mockResolvedValueOnce(true);
211
217
  await authInstance.doTokenAuth(embedConfig.doTokenAuthSuccess('authToken3'));
212
218
 
213
219
  try {
220
+ jest.spyOn(authService, 'verifyTokenService').mockResolvedValueOnce(false);
214
221
  await authInstance.doTokenAuth(embedConfig.doTokenAuthSuccess('authToken3'));
215
222
  expect(false).toBe(true);
216
223
  } catch (e) {
@@ -224,7 +231,7 @@ describe('Unit test for auth', () => {
224
231
  });
225
232
 
226
233
  test('doTokenAuth: Should set loggedInStatus if detectThirdPartyCookieAccess is true and the second info call fails', async () => {
227
- jest.spyOn(authService, 'fetchSessionInfoService')
234
+ jest.spyOn(tokenAuthService, 'fetchSessionInfoService')
228
235
  .mockResolvedValue({
229
236
  status: 401,
230
237
  })
@@ -236,14 +243,15 @@ describe('Unit test for auth', () => {
236
243
  status: 200,
237
244
  ok: true,
238
245
  }));
246
+ jest.spyOn(authService, 'verifyTokenService').mockResolvedValueOnce(true);
239
247
  const isLoggedIn = await authInstance.doTokenAuth(embedConfig.doTokenAuthWithCookieDetect);
240
- expect(authService.fetchSessionInfoService).toHaveBeenCalledTimes(2);
248
+ expect(tokenAuthService.fetchSessionInfoService).toHaveBeenCalledTimes(2);
241
249
  expect(isLoggedIn).toBe(false);
242
250
  });
243
251
 
244
252
  test('doTokenAuth: when user is not loggedIn & fetchAuthPostService failed than fetchAuthService should call', async () => {
245
253
  jest.spyOn(window, 'alert').mockImplementation(() => undefined);
246
- jest.spyOn(authService, 'fetchSessionInfoService').mockImplementation(() => false);
254
+ jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockImplementation(() => false);
247
255
  jest.spyOn(authService, 'fetchAuthTokenService').mockImplementation(() => ({
248
256
  text: () => Promise.resolve('abc'),
249
257
  }));
@@ -256,10 +264,11 @@ describe('Unit test for auth', () => {
256
264
  status: 200,
257
265
  type: 'opaqueredirect',
258
266
  }));
267
+ jest.spyOn(authService, 'verifyTokenService').mockResolvedValueOnce(true);
259
268
  expect(await authInstance.doTokenAuth(embedConfig.doTokenAuthSuccess('authToken2'))).toBe(
260
269
  true,
261
270
  );
262
- expect(authService.fetchSessionInfoService).toBeCalled();
271
+ expect(tokenAuthService.fetchSessionInfoService).toBeCalled();
263
272
  expect(authService.fetchAuthPostService).toBeCalledWith(
264
273
  thoughtSpotHost,
265
274
  username,
@@ -278,35 +287,31 @@ describe('Unit test for auth', () => {
278
287
  });
279
288
 
280
289
  it('when user is loggedIn', async () => {
281
- spyOn(
282
- checkReleaseVersionInBetaInstance,
283
- 'checkReleaseVersionInBeta',
284
- );
290
+ spyOn(checkReleaseVersionInBetaInstance, 'checkReleaseVersionInBeta');
285
291
  jest.spyOn(authInstance, 'getSessionDetails').mockReturnValue(mockSessionInfo);
286
292
  jest.spyOn(authInstance, 'initSession').mockReturnValue(null);
287
- jest.spyOn(
288
- authService,
289
- 'fetchSessionInfoService',
290
- ).mockImplementation(async () => ({
291
- json: () => mockSessionInfo,
292
- status: 200,
293
- }));
293
+ jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockImplementation(
294
+ async () => ({
295
+ json: () => mockSessionInfo,
296
+ status: 200,
297
+ }),
298
+ );
294
299
  await authInstance.doBasicAuth(embedConfig.doBasicAuth);
295
- expect(authService.fetchSessionInfoService).toBeCalled();
300
+ expect(tokenAuthService.fetchSessionInfoService).toBeCalled();
296
301
  expect(authInstance.loggedInStatus).toBe(true);
297
302
  expect(authInstance.getSessionDetails).toBeCalled();
298
303
  expect(authInstance.initSession).toBeCalled();
299
304
  });
300
305
 
301
306
  it('when user is not loggedIn', async () => {
302
- jest.spyOn(authService, 'fetchSessionInfoService').mockImplementation(() => Promise.reject());
307
+ jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockImplementation(() => Promise.reject());
303
308
  jest.spyOn(authService, 'fetchBasicAuthService').mockImplementation(() => ({
304
309
  status: 200,
305
310
  ok: true,
306
311
  }));
307
312
 
308
313
  await authInstance.doBasicAuth(embedConfig.doBasicAuth);
309
- expect(authService.fetchSessionInfoService).toBeCalled();
314
+ expect(tokenAuthService.fetchSessionInfoService).toBeCalled();
310
315
  expect(authService.fetchBasicAuthService).toBeCalled();
311
316
  expect(authInstance.loggedInStatus).toBe(true);
312
317
  });
@@ -328,22 +333,24 @@ describe('Unit test for auth', () => {
328
333
  hash: '',
329
334
  },
330
335
  });
331
- jest.spyOn(authService, 'fetchSessionInfoService').mockImplementation(async () => ({
332
- json: () => mockSessionInfo,
333
- status: 200,
334
- }));
336
+ jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockImplementation(
337
+ async () => ({
338
+ json: () => mockSessionInfo,
339
+ status: 200,
340
+ }),
341
+ );
335
342
  jest.spyOn(authInstance, 'getSessionDetails').mockReturnValue(mockSessionInfo);
336
343
  jest.spyOn(authInstance, 'initSession').mockReturnValue(null);
337
344
  await authInstance.doSamlAuth(embedConfig.doSamlAuth);
338
- expect(authService.fetchSessionInfoService).toBeCalled();
345
+ expect(tokenAuthService.fetchSessionInfoService).toBeCalled();
339
346
  expect(window.location.hash).toBe('');
340
347
  expect(authInstance.loggedInStatus).toBe(true);
341
348
  });
342
349
 
343
350
  it('when user is not loggedIn & isAtSSORedirectUrl is true', async () => {
344
- jest.spyOn(authService, 'fetchSessionInfoService').mockImplementation(() => Promise.reject());
351
+ jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockImplementation(() => Promise.reject());
345
352
  await authInstance.doSamlAuth(embedConfig.doSamlAuth);
346
- expect(authService.fetchSessionInfoService).toBeCalled();
353
+ expect(tokenAuthService.fetchSessionInfoService).toBeCalled();
347
354
  expect(window.location.hash).toBe('');
348
355
  expect(authInstance.loggedInStatus).toBe(false);
349
356
  });
@@ -355,9 +362,9 @@ describe('Unit test for auth', () => {
355
362
  hash: '',
356
363
  },
357
364
  });
358
- jest.spyOn(authService, 'fetchSessionInfoService').mockImplementation(() => Promise.reject());
365
+ jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockImplementation(() => Promise.reject());
359
366
  await authInstance.doSamlAuth(embedConfig.doSamlAuth);
360
- expect(authService.fetchSessionInfoService).toBeCalled();
367
+ expect(tokenAuthService.fetchSessionInfoService).toBeCalled();
361
368
  expect(global.window.location.href).toBe(samalLoginUrl);
362
369
  });
363
370
 
@@ -370,7 +377,7 @@ describe('Unit test for auth', () => {
370
377
  });
371
378
  spyOn(authInstance, 'samlCompletionPromise');
372
379
  global.window.open = jest.fn();
373
- jest.spyOn(authService, 'fetchSessionInfoService')
380
+ jest.spyOn(tokenAuthService, 'fetchSessionInfoService')
374
381
  .mockImplementationOnce(() => Promise.reject())
375
382
  .mockImplementationOnce(async () => ({
376
383
  json: () => mockSessionInfo,
@@ -387,7 +394,7 @@ describe('Unit test for auth', () => {
387
394
  document.getElementById('ts-auth-btn').click();
388
395
  window.postMessage({ type: EmbedEvent.SAMLComplete }, '*');
389
396
  await authInstance.samlCompletionPromise;
390
- expect(authService.fetchSessionInfoService).toBeCalled();
397
+ expect(tokenAuthService.fetchSessionInfoService).toBeCalled();
391
398
  expect(authInstance.getSessionDetails).toBeCalled();
392
399
  expect(authInstance.initSession).toBeCalled();
393
400
  });
@@ -395,6 +402,7 @@ describe('Unit test for auth', () => {
395
402
 
396
403
  describe('doOIDCAuth', () => {
397
404
  afterEach(() => {
405
+ resetCachedAuthToken();
398
406
  delete global.window;
399
407
  global.window = Object.create(originalWindow);
400
408
  global.window.open = jest.fn();
@@ -402,9 +410,9 @@ describe('Unit test for auth', () => {
402
410
  });
403
411
 
404
412
  it('when user is not loggedIn & isAtSSORedirectUrl is true', async () => {
405
- jest.spyOn(authService, 'fetchSessionInfoService').mockImplementation(() => Promise.reject());
413
+ jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockImplementation(() => Promise.reject());
406
414
  await authInstance.doOIDCAuth(embedConfig.doOidcAuth);
407
- expect(authService.fetchSessionInfoService).toBeCalled();
415
+ expect(tokenAuthService.fetchSessionInfoService).toBeCalled();
408
416
  expect(window.location.hash).toBe('');
409
417
  expect(authInstance.loggedInStatus).toBe(false);
410
418
  });
@@ -463,16 +471,18 @@ describe('Unit test for auth', () => {
463
471
  });
464
472
 
465
473
  it('doCookielessTokenAuth should resolve to true if valid token is passed', async () => {
466
- jest.spyOn(authService, 'fetchAuthTokenService').mockResolvedValueOnce(new Response(JSON.stringify({ token: 'testToken' }), { status: 200 }));
467
- jest.spyOn(authService, 'verifyTokenService').mockResolvedValueOnce(new Response('', { status: 200 }));
468
- const isLoggedIn = await authInstance.doCookielessTokenAuth(embedConfig.doCookielessAuth('testToken'));
474
+ jest.spyOn(authService, 'verifyTokenService').mockResolvedValueOnce(true);
475
+ const isLoggedIn = await authInstance.doCookielessTokenAuth(
476
+ embedConfig.doCookielessAuth('testToken'),
477
+ );
469
478
  expect(isLoggedIn).toBe(true);
470
479
  });
471
480
 
472
481
  it('doCookielessTokenAuth should resolve to false if valid token is not passed', async () => {
473
- jest.spyOn(authService, 'fetchAuthTokenService').mockResolvedValueOnce(new Response(JSON.stringify({ token: 'testToken' }), { status: 200 }));
474
- jest.spyOn(authService, 'verifyTokenService').mockResolvedValueOnce(new Response('', { status: 400 }));
475
- const isLoggedIn = await authInstance.doCookielessTokenAuth(embedConfig.doCookielessAuth('testToken'));
482
+ jest.spyOn(authService, 'verifyTokenService').mockResolvedValueOnce(false);
483
+ const isLoggedIn = await authInstance.doCookielessTokenAuth(
484
+ embedConfig.doCookielessAuth('testToken'),
485
+ );
476
486
  expect(isLoggedIn).toBe(false);
477
487
  });
478
488
  it('get AuthEE should return proper value', () => {
@@ -495,9 +505,11 @@ describe('Unit test for auth', () => {
495
505
  },
496
506
  },
497
507
  });
498
- expect(details).toEqual(expect.objectContaining({
499
- mixpanelToken: 'devKey',
500
- }));
508
+ expect(details).toEqual(
509
+ expect.objectContaining({
510
+ mixpanelToken: 'devKey',
511
+ }),
512
+ );
501
513
 
502
514
  const details2 = authInstance.getSessionDetails({
503
515
  configInfo: {
@@ -508,8 +520,10 @@ describe('Unit test for auth', () => {
508
520
  },
509
521
  },
510
522
  });
511
- expect(details2).toEqual(expect.objectContaining({
512
- mixpanelToken: 'prodKey',
513
- }));
523
+ expect(details2).toEqual(
524
+ expect.objectContaining({
525
+ mixpanelToken: 'prodKey',
526
+ }),
527
+ );
514
528
  });
515
529
  });
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
+ };
package/src/embed/app.ts CHANGED
@@ -202,10 +202,9 @@ export class AppEmbed extends V1Embed {
202
202
 
203
203
  private defaultHeight = '100%';
204
204
 
205
- protected embedComponentType = 'AppEmbed';
206
-
207
205
  // eslint-disable-next-line no-useless-constructor
208
206
  constructor(domSelector: DOMSelector, viewConfig: AppViewConfig) {
207
+ viewConfig.embedComponentType = 'AppEmbed';
209
208
  super(domSelector, viewConfig);
210
209
  if (this.viewConfig.fullHeight === true) {
211
210
  this.on(EmbedEvent.RouteChange, this.setIframeHeightForNonEmbedLiveboard);