@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.
- package/cjs/package.json +2 -2
- package/cjs/src/auth.d.ts +0 -12
- package/cjs/src/auth.d.ts.map +1 -1
- package/cjs/src/auth.js +16 -54
- package/cjs/src/auth.js.map +1 -1
- package/cjs/src/auth.spec.d.ts.map +1 -1
- package/cjs/src/auth.spec.js +42 -32
- package/cjs/src/auth.spec.js.map +1 -1
- package/cjs/src/authToken.d.ts +4 -0
- package/cjs/src/authToken.d.ts.map +1 -0
- package/cjs/src/authToken.js +61 -0
- package/cjs/src/authToken.js.map +1 -0
- package/cjs/src/embed/app.d.ts +0 -1
- package/cjs/src/embed/app.d.ts.map +1 -1
- package/cjs/src/embed/app.js +1 -1
- package/cjs/src/embed/app.js.map +1 -1
- package/cjs/src/embed/base.d.ts +0 -9
- package/cjs/src/embed/base.d.ts.map +1 -1
- package/cjs/src/embed/base.js +21 -44
- package/cjs/src/embed/base.js.map +1 -1
- package/cjs/src/embed/base.spec.js +15 -14
- package/cjs/src/embed/base.spec.js.map +1 -1
- package/cjs/src/embed/embedConfig.d.ts +18 -0
- package/cjs/src/embed/embedConfig.d.ts.map +1 -0
- package/cjs/src/embed/embedConfig.js +25 -0
- package/cjs/src/embed/embedConfig.js.map +1 -0
- package/cjs/src/embed/liveboard.d.ts +0 -1
- package/cjs/src/embed/liveboard.d.ts.map +1 -1
- package/cjs/src/embed/liveboard.js +1 -1
- package/cjs/src/embed/liveboard.js.map +1 -1
- package/cjs/src/embed/sage.d.ts +0 -1
- package/cjs/src/embed/sage.d.ts.map +1 -1
- package/cjs/src/embed/sage.js +1 -1
- package/cjs/src/embed/sage.js.map +1 -1
- package/cjs/src/embed/search.d.ts +0 -1
- package/cjs/src/embed/search.d.ts.map +1 -1
- package/cjs/src/embed/search.js +5 -4
- package/cjs/src/embed/search.js.map +1 -1
- package/cjs/src/embed/searchEmbed-basic-auth.spec.js +3 -2
- package/cjs/src/embed/searchEmbed-basic-auth.spec.js.map +1 -1
- package/cjs/src/embed/ts-embed.d.ts +0 -1
- package/cjs/src/embed/ts-embed.d.ts.map +1 -1
- package/cjs/src/embed/ts-embed.js +6 -6
- package/cjs/src/embed/ts-embed.js.map +1 -1
- package/cjs/src/embed/ts-embed.spec.js +58 -49
- package/cjs/src/embed/ts-embed.spec.js.map +1 -1
- package/cjs/src/index.d.ts +2 -1
- package/cjs/src/index.d.ts.map +1 -1
- package/cjs/src/index.js +2 -1
- package/cjs/src/index.js.map +1 -1
- package/cjs/src/tokenizedFetch.d.ts +2 -0
- package/cjs/src/tokenizedFetch.d.ts.map +1 -0
- package/cjs/src/tokenizedFetch.js +20 -0
- package/cjs/src/tokenizedFetch.js.map +1 -0
- package/cjs/src/types.d.ts +12 -0
- package/cjs/src/types.d.ts.map +1 -1
- package/cjs/src/types.js.map +1 -1
- package/cjs/src/utils/{authService.d.ts → authService/authService.d.ts} +12 -11
- package/cjs/src/utils/authService/authService.d.ts.map +1 -0
- package/cjs/src/utils/{authService.js → authService/authService.js} +31 -39
- package/cjs/src/utils/authService/authService.js.map +1 -0
- package/cjs/src/utils/authService/authService.spec.d.ts.map +1 -0
- package/cjs/src/utils/{authService.spec.js → authService/authService.spec.js} +11 -12
- package/cjs/src/utils/authService/authService.spec.js.map +1 -0
- package/cjs/src/utils/authService/index.d.ts +3 -0
- package/cjs/src/utils/authService/index.d.ts.map +1 -0
- package/cjs/src/utils/authService/index.js +14 -0
- package/cjs/src/utils/authService/index.js.map +1 -0
- package/cjs/src/utils/authService/tokenizedAuthService.d.ts +11 -0
- package/cjs/src/utils/authService/tokenizedAuthService.d.ts.map +1 -0
- package/cjs/src/utils/authService/tokenizedAuthService.js +44 -0
- package/cjs/src/utils/authService/tokenizedAuthService.js.map +1 -0
- package/cjs/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
- package/cjs/src/utils/graphql/answerService/answerService.js +2 -1
- package/cjs/src/utils/graphql/answerService/answerService.js.map +1 -1
- package/cjs/src/utils/graphql/answerService/answerService.spec.js +15 -3
- package/cjs/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
- package/cjs/src/utils/processData.d.ts.map +1 -1
- package/cjs/src/utils/processData.js +5 -4
- package/cjs/src/utils/processData.js.map +1 -1
- package/cjs/src/utils/processData.spec.js +8 -7
- package/cjs/src/utils/processData.spec.js.map +1 -1
- package/dist/src/auth.d.ts +0 -12
- package/dist/src/auth.d.ts.map +1 -1
- package/dist/src/auth.spec.d.ts.map +1 -1
- package/dist/src/authToken.d.ts +4 -0
- package/dist/src/authToken.d.ts.map +1 -0
- package/dist/src/embed/app.d.ts +0 -1
- package/dist/src/embed/app.d.ts.map +1 -1
- package/dist/src/embed/base.d.ts +0 -9
- package/dist/src/embed/base.d.ts.map +1 -1
- package/dist/src/embed/embedConfig.d.ts +18 -0
- package/dist/src/embed/embedConfig.d.ts.map +1 -0
- package/dist/src/embed/liveboard.d.ts +0 -1
- package/dist/src/embed/liveboard.d.ts.map +1 -1
- package/dist/src/embed/sage.d.ts +0 -1
- package/dist/src/embed/sage.d.ts.map +1 -1
- package/dist/src/embed/search.d.ts +0 -1
- package/dist/src/embed/search.d.ts.map +1 -1
- package/dist/src/embed/ts-embed.d.ts +0 -1
- package/dist/src/embed/ts-embed.d.ts.map +1 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/tokenizedFetch.d.ts +2 -0
- package/dist/src/tokenizedFetch.d.ts.map +1 -0
- package/dist/src/types.d.ts +12 -0
- package/dist/src/types.d.ts.map +1 -1
- package/{lib/src/utils → dist/src/utils/authService}/authService.d.ts +44 -43
- package/dist/src/utils/authService/authService.d.ts.map +1 -0
- package/dist/src/utils/authService/index.d.ts +3 -0
- package/dist/src/utils/authService/index.d.ts.map +1 -0
- package/dist/src/utils/authService/tokenizedAuthService.d.ts +11 -0
- package/dist/src/utils/authService/tokenizedAuthService.d.ts.map +1 -0
- package/dist/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
- package/dist/src/utils/processData.d.ts.map +1 -1
- package/dist/tsembed-react.es.js +207 -149
- package/dist/tsembed-react.js +207 -149
- package/dist/tsembed.es.js +236 -180
- package/dist/tsembed.js +236 -180
- package/dist/visual-embed-sdk-react-full.d.ts +29 -26
- package/dist/visual-embed-sdk-react.d.ts +29 -26
- package/dist/visual-embed-sdk.d.ts +29 -26
- package/lib/package.json +2 -2
- package/lib/src/auth.d.ts +0 -12
- package/lib/src/auth.d.ts.map +1 -1
- package/lib/src/auth.js +11 -48
- package/lib/src/auth.js.map +1 -1
- package/lib/src/auth.spec.d.ts.map +1 -1
- package/lib/src/auth.spec.js +42 -32
- package/lib/src/auth.spec.js.map +1 -1
- package/lib/src/authToken.d.ts +4 -0
- package/lib/src/authToken.d.ts.map +1 -0
- package/lib/src/authToken.js +56 -0
- package/lib/src/authToken.js.map +1 -0
- package/lib/src/embed/app.d.ts +0 -1
- package/lib/src/embed/app.d.ts.map +1 -1
- package/lib/src/embed/app.js +1 -1
- package/lib/src/embed/app.js.map +1 -1
- package/lib/src/embed/base.d.ts +0 -9
- package/lib/src/embed/base.d.ts.map +1 -1
- package/lib/src/embed/base.js +21 -43
- package/lib/src/embed/base.js.map +1 -1
- package/lib/src/embed/base.spec.js +15 -14
- package/lib/src/embed/base.spec.js.map +1 -1
- package/lib/src/embed/embedConfig.d.ts +18 -0
- package/lib/src/embed/embedConfig.d.ts.map +1 -0
- package/lib/src/embed/embedConfig.js +20 -0
- package/lib/src/embed/embedConfig.js.map +1 -0
- package/lib/src/embed/liveboard.d.ts +0 -1
- package/lib/src/embed/liveboard.d.ts.map +1 -1
- package/lib/src/embed/liveboard.js +1 -1
- package/lib/src/embed/liveboard.js.map +1 -1
- package/lib/src/embed/sage.d.ts +0 -1
- package/lib/src/embed/sage.d.ts.map +1 -1
- package/lib/src/embed/sage.js +1 -1
- package/lib/src/embed/sage.js.map +1 -1
- package/lib/src/embed/search.d.ts +0 -1
- package/lib/src/embed/search.d.ts.map +1 -1
- package/lib/src/embed/search.js +6 -5
- package/lib/src/embed/search.js.map +1 -1
- package/lib/src/embed/searchEmbed-basic-auth.spec.js +3 -2
- package/lib/src/embed/searchEmbed-basic-auth.spec.js.map +1 -1
- package/lib/src/embed/ts-embed.d.ts +0 -1
- package/lib/src/embed/ts-embed.d.ts.map +1 -1
- package/lib/src/embed/ts-embed.js +5 -5
- package/lib/src/embed/ts-embed.js.map +1 -1
- package/lib/src/embed/ts-embed.spec.js +58 -49
- package/lib/src/embed/ts-embed.spec.js.map +1 -1
- package/lib/src/index.d.ts +2 -1
- package/lib/src/index.d.ts.map +1 -1
- package/lib/src/index.js +2 -1
- package/lib/src/index.js.map +1 -1
- package/lib/src/tokenizedFetch.d.ts +2 -0
- package/lib/src/tokenizedFetch.d.ts.map +1 -0
- package/lib/src/tokenizedFetch.js +16 -0
- package/lib/src/tokenizedFetch.js.map +1 -0
- package/lib/src/types.d.ts +12 -0
- package/lib/src/types.d.ts.map +1 -1
- package/lib/src/types.js.map +1 -1
- package/{dist/src/utils → lib/src/utils/authService}/authService.d.ts +44 -43
- package/lib/src/utils/authService/authService.d.ts.map +1 -0
- package/lib/src/utils/{authService.js → authService/authService.js} +26 -32
- package/lib/src/utils/authService/authService.js.map +1 -0
- package/lib/src/utils/authService/authService.spec.d.ts.map +1 -0
- package/lib/src/utils/{authService.spec.js → authService/authService.spec.js} +1 -2
- package/lib/src/utils/authService/authService.spec.js.map +1 -0
- package/lib/src/utils/authService/index.d.ts +3 -0
- package/lib/src/utils/authService/index.d.ts.map +1 -0
- package/lib/src/utils/authService/index.js +3 -0
- package/lib/src/utils/authService/index.js.map +1 -0
- package/lib/src/utils/authService/tokenizedAuthService.d.ts +11 -0
- package/lib/src/utils/authService/tokenizedAuthService.d.ts.map +1 -0
- package/lib/src/utils/authService/tokenizedAuthService.js +39 -0
- package/lib/src/utils/authService/tokenizedAuthService.js.map +1 -0
- package/lib/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
- package/lib/src/utils/graphql/answerService/answerService.js +2 -1
- package/lib/src/utils/graphql/answerService/answerService.js.map +1 -1
- package/lib/src/utils/graphql/answerService/answerService.spec.js +14 -3
- package/lib/src/utils/graphql/answerService/answerService.spec.js.map +1 -1
- package/lib/src/utils/processData.d.ts.map +1 -1
- package/lib/src/utils/processData.js +4 -3
- package/lib/src/utils/processData.js.map +1 -1
- package/lib/src/utils/processData.spec.js +8 -7
- package/lib/src/utils/processData.spec.js.map +1 -1
- package/lib/src/visual-embed-sdk.d.ts +34 -27
- package/package.json +2 -2
- package/src/auth.spec.ts +77 -63
- package/src/auth.ts +12 -55
- package/src/authToken.ts +66 -0
- package/src/embed/app.ts +1 -2
- package/src/embed/base.spec.ts +18 -17
- package/src/embed/base.ts +26 -51
- package/src/embed/embedConfig.ts +23 -0
- package/src/embed/liveboard.ts +1 -2
- package/src/embed/sage.ts +1 -2
- package/src/embed/search.ts +12 -14
- package/src/embed/searchEmbed-basic-auth.spec.ts +3 -2
- package/src/embed/ts-embed.spec.ts +87 -75
- package/src/embed/ts-embed.ts +7 -19
- package/src/index.ts +8 -2
- package/src/tokenizedFetch.ts +18 -0
- package/src/types.ts +36 -19
- package/src/utils/{authService.spec.ts → authService/authService.spec.ts} +2 -3
- package/src/utils/{authService.ts → authService/authService.ts} +29 -34
- package/src/utils/authService/index.ts +9 -0
- package/src/utils/authService/tokenizedAuthService.ts +40 -0
- package/src/utils/graphql/answerService/answerService.spec.ts +16 -4
- package/src/utils/graphql/answerService/answerService.ts +2 -1
- package/src/utils/processData.spec.ts +19 -16
- package/src/utils/processData.ts +3 -2
- package/cjs/src/utils/authService.d.ts.map +0 -1
- package/cjs/src/utils/authService.js.map +0 -1
- package/cjs/src/utils/authService.spec.d.ts.map +0 -1
- package/cjs/src/utils/authService.spec.js.map +0 -1
- package/dist/src/utils/authService.d.ts.map +0 -1
- package/lib/src/utils/authService.d.ts.map +0 -1
- package/lib/src/utils/authService.js.map +0 -1
- package/lib/src/utils/authService.spec.d.ts.map +0 -1
- package/lib/src/utils/authService.spec.js.map +0 -1
- /package/cjs/src/utils/{authService.spec.d.ts → authService/authService.spec.d.ts} +0 -0
- /package/dist/src/utils/{authService.spec.d.ts → authService/authService.spec.d.ts} +0 -0
- /package/dist/src/utils/{authService.spec.d.ts.map → authService/authService.spec.d.ts.map} +0 -0
- /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.
|
|
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": "
|
|
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 =
|
|
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(
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
196
|
-
expect(authService.fetchAuthService).toBeCalledWith(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
332
|
-
|
|
333
|
-
|
|
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(
|
|
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(
|
|
351
|
+
jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockImplementation(() => Promise.reject());
|
|
345
352
|
await authInstance.doSamlAuth(embedConfig.doSamlAuth);
|
|
346
|
-
expect(
|
|
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(
|
|
365
|
+
jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockImplementation(() => Promise.reject());
|
|
359
366
|
await authInstance.doSamlAuth(embedConfig.doSamlAuth);
|
|
360
|
-
expect(
|
|
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(
|
|
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(
|
|
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(
|
|
413
|
+
jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockImplementation(() => Promise.reject());
|
|
406
414
|
await authInstance.doOIDCAuth(embedConfig.doOidcAuth);
|
|
407
|
-
expect(
|
|
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, '
|
|
467
|
-
|
|
468
|
-
|
|
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, '
|
|
474
|
-
|
|
475
|
-
|
|
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(
|
|
499
|
-
|
|
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(
|
|
512
|
-
|
|
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
|
-
|
|
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
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
324
|
+
if (authToken) {
|
|
325
|
+
authSuccess = true;
|
|
326
|
+
}
|
|
327
|
+
} catch {
|
|
328
|
+
authSuccess = false;
|
|
369
329
|
}
|
|
370
330
|
|
|
371
|
-
return
|
|
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
|
-
|
|
473
|
+
await fetchLogoutService(thoughtSpotHost);
|
|
474
|
+
resetCachedAuthToken();
|
|
518
475
|
loggedInStatus = false;
|
|
519
476
|
return loggedInStatus;
|
|
520
477
|
};
|
package/src/authToken.ts
ADDED
|
@@ -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);
|