@thoughtspot/visual-embed-sdk 1.29.0-alpha.7 → 1.29.0-alpha.SCAL-205893-1
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 +1 -1
- package/cjs/src/auth.d.ts +14 -17
- package/cjs/src/auth.d.ts.map +1 -1
- package/cjs/src/auth.js +45 -59
- package/cjs/src/auth.js.map +1 -1
- package/cjs/src/auth.spec.d.ts +12 -0
- package/cjs/src/auth.spec.d.ts.map +1 -1
- package/cjs/src/auth.spec.js +89 -67
- package/cjs/src/auth.spec.js.map +1 -1
- package/cjs/src/authToken.d.ts +1 -1
- package/cjs/src/authToken.d.ts.map +1 -1
- package/cjs/src/authToken.js +18 -5
- package/cjs/src/authToken.js.map +1 -1
- package/cjs/src/authToken.spec.d.ts +2 -0
- package/cjs/src/authToken.spec.d.ts.map +1 -0
- package/cjs/src/authToken.spec.js +29 -0
- package/cjs/src/authToken.spec.js.map +1 -0
- package/cjs/src/embed/app.spec.js +4 -2
- package/cjs/src/embed/app.spec.js.map +1 -1
- package/cjs/src/embed/base.d.ts.map +1 -1
- package/cjs/src/embed/base.js +2 -0
- package/cjs/src/embed/base.js.map +1 -1
- package/cjs/src/embed/base.spec.js +1 -0
- package/cjs/src/embed/base.spec.js.map +1 -1
- package/cjs/src/embed/embed.spec.js +3 -0
- package/cjs/src/embed/embed.spec.js.map +1 -1
- package/cjs/src/embed/events.spec.js +3 -0
- package/cjs/src/embed/events.spec.js.map +1 -1
- package/cjs/src/embed/liveboard.spec.js +2 -0
- package/cjs/src/embed/liveboard.spec.js.map +1 -1
- package/cjs/src/embed/pinboard.spec.js +3 -0
- package/cjs/src/embed/pinboard.spec.js.map +1 -1
- package/cjs/src/embed/sage.spec.js +3 -0
- package/cjs/src/embed/sage.spec.js.map +1 -1
- package/cjs/src/embed/search.spec.js +1 -0
- package/cjs/src/embed/search.spec.js.map +1 -1
- package/cjs/src/embed/ts-embed-trigger.spec.js +3 -0
- package/cjs/src/embed/ts-embed-trigger.spec.js.map +1 -1
- package/cjs/src/embed/ts-embed.d.ts.map +1 -1
- package/cjs/src/embed/ts-embed.js +7 -0
- package/cjs/src/embed/ts-embed.js.map +1 -1
- package/cjs/src/embed/ts-embed.spec.js +7 -0
- 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/mixpanel-service.d.ts +2 -1
- package/cjs/src/mixpanel-service.d.ts.map +1 -1
- package/cjs/src/mixpanel-service.js +1 -0
- package/cjs/src/mixpanel-service.js.map +1 -1
- package/cjs/src/mixpanel-service.spec.js +7 -0
- package/cjs/src/mixpanel-service.spec.js.map +1 -1
- package/cjs/src/react/index.d.ts +1 -1
- package/cjs/src/react/index.d.ts.map +1 -1
- package/cjs/src/react/index.js +2 -1
- package/cjs/src/react/index.js.map +1 -1
- package/cjs/src/react/index.spec.js +6 -0
- package/cjs/src/react/index.spec.js.map +1 -1
- package/cjs/src/types.d.ts +79 -47
- package/cjs/src/types.d.ts.map +1 -1
- package/cjs/src/types.js +61 -46
- package/cjs/src/types.js.map +1 -1
- package/cjs/src/utils/authService/authService.d.ts +1 -0
- package/cjs/src/utils/authService/authService.d.ts.map +1 -1
- package/cjs/src/utils/authService/authService.js +1 -0
- package/cjs/src/utils/authService/authService.js.map +1 -1
- package/cjs/src/utils/authService/authService.spec.js +18 -5
- package/cjs/src/utils/authService/authService.spec.js.map +1 -1
- package/cjs/src/utils/authService/tokenizedAuthService.d.ts +15 -2
- package/cjs/src/utils/authService/tokenizedAuthService.d.ts.map +1 -1
- package/cjs/src/utils/authService/tokenizedAuthService.js +39 -9
- package/cjs/src/utils/authService/tokenizedAuthService.js.map +1 -1
- package/cjs/src/utils/authService/tokenizedAuthService.spec.d.ts +2 -0
- package/cjs/src/utils/authService/tokenizedAuthService.spec.d.ts.map +1 -0
- package/cjs/src/utils/authService/tokenizedAuthService.spec.js +32 -0
- package/cjs/src/utils/authService/tokenizedAuthService.spec.js.map +1 -0
- package/cjs/src/utils/graphql/answerService/answerService.d.ts +10 -0
- package/cjs/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
- package/cjs/src/utils/graphql/answerService/answerService.js +10 -0
- package/cjs/src/utils/graphql/answerService/answerService.js.map +1 -1
- package/cjs/src/utils/processData.js +2 -2
- package/cjs/src/utils/processData.js.map +1 -1
- package/cjs/src/utils/processData.spec.js +3 -2
- package/cjs/src/utils/processData.spec.js.map +1 -1
- package/cjs/src/utils/sessionInfoService.d.ts +66 -0
- package/cjs/src/utils/sessionInfoService.d.ts.map +1 -0
- package/cjs/src/utils/sessionInfoService.js +92 -0
- package/cjs/src/utils/sessionInfoService.js.map +1 -0
- package/cjs/src/utils.d.ts +1 -1
- package/cjs/src/utils.d.ts.map +1 -1
- package/cjs/src/utils.js +4 -1
- package/cjs/src/utils.js.map +1 -1
- package/dist/src/auth.d.ts +14 -17
- package/dist/src/auth.d.ts.map +1 -1
- package/dist/src/auth.spec.d.ts +12 -0
- package/dist/src/auth.spec.d.ts.map +1 -1
- package/dist/src/authToken.d.ts +1 -1
- package/dist/src/authToken.d.ts.map +1 -1
- package/dist/src/authToken.spec.d.ts +2 -0
- package/dist/src/authToken.spec.d.ts.map +1 -0
- package/dist/src/embed/base.d.ts.map +1 -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/mixpanel-service.d.ts +2 -1
- package/dist/src/mixpanel-service.d.ts.map +1 -1
- package/dist/src/react/index.d.ts +1 -1
- package/dist/src/react/index.d.ts.map +1 -1
- package/dist/src/types.d.ts +79 -47
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/authService/authService.d.ts +1 -0
- package/dist/src/utils/authService/authService.d.ts.map +1 -1
- package/dist/src/utils/authService/tokenizedAuthService.d.ts +15 -2
- package/dist/src/utils/authService/tokenizedAuthService.d.ts.map +1 -1
- package/dist/src/utils/authService/tokenizedAuthService.spec.d.ts +2 -0
- package/dist/src/utils/authService/tokenizedAuthService.spec.d.ts.map +1 -0
- package/dist/src/utils/graphql/answerService/answerService.d.ts +10 -0
- package/dist/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
- package/dist/src/utils/sessionInfoService.d.ts +66 -0
- package/dist/src/utils/sessionInfoService.d.ts.map +1 -0
- package/dist/src/utils.d.ts +1 -1
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/tsembed-react.es.js +225 -105
- package/dist/tsembed-react.js +225 -104
- package/dist/tsembed.es.js +233 -116
- package/dist/tsembed.js +233 -116
- package/dist/visual-embed-sdk-react-full.d.ts +171 -66
- package/dist/visual-embed-sdk-react.d.ts +171 -66
- package/dist/visual-embed-sdk.d.ts +171 -66
- package/lib/package.json +1 -1
- package/lib/src/auth.d.ts +14 -17
- package/lib/src/auth.d.ts.map +1 -1
- package/lib/src/auth.js +44 -56
- package/lib/src/auth.js.map +1 -1
- package/lib/src/auth.spec.d.ts +12 -0
- package/lib/src/auth.spec.d.ts.map +1 -1
- package/lib/src/auth.spec.js +88 -66
- package/lib/src/auth.spec.js.map +1 -1
- package/lib/src/authToken.d.ts +1 -1
- package/lib/src/authToken.d.ts.map +1 -1
- package/lib/src/authToken.js +18 -5
- package/lib/src/authToken.js.map +1 -1
- package/lib/src/authToken.spec.d.ts +2 -0
- package/lib/src/authToken.spec.d.ts.map +1 -0
- package/lib/src/authToken.spec.js +26 -0
- package/lib/src/authToken.spec.js.map +1 -0
- package/lib/src/embed/app.spec.js +4 -2
- package/lib/src/embed/app.spec.js.map +1 -1
- package/lib/src/embed/base.d.ts.map +1 -1
- package/lib/src/embed/base.js +3 -1
- package/lib/src/embed/base.js.map +1 -1
- package/lib/src/embed/base.spec.js +1 -0
- package/lib/src/embed/base.spec.js.map +1 -1
- package/lib/src/embed/embed.spec.js +2 -0
- package/lib/src/embed/embed.spec.js.map +1 -1
- package/lib/src/embed/events.spec.js +2 -0
- package/lib/src/embed/events.spec.js.map +1 -1
- package/lib/src/embed/liveboard.spec.js +2 -0
- package/lib/src/embed/liveboard.spec.js.map +1 -1
- package/lib/src/embed/pinboard.spec.js +2 -0
- package/lib/src/embed/pinboard.spec.js.map +1 -1
- package/lib/src/embed/sage.spec.js +2 -0
- package/lib/src/embed/sage.spec.js.map +1 -1
- package/lib/src/embed/search.spec.js +1 -0
- package/lib/src/embed/search.spec.js.map +1 -1
- package/lib/src/embed/ts-embed-trigger.spec.js +2 -0
- package/lib/src/embed/ts-embed-trigger.spec.js.map +1 -1
- package/lib/src/embed/ts-embed.d.ts.map +1 -1
- package/lib/src/embed/ts-embed.js +7 -0
- package/lib/src/embed/ts-embed.js.map +1 -1
- package/lib/src/embed/ts-embed.spec.js +7 -0
- 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/mixpanel-service.d.ts +2 -1
- package/lib/src/mixpanel-service.d.ts.map +1 -1
- package/lib/src/mixpanel-service.js +1 -0
- package/lib/src/mixpanel-service.js.map +1 -1
- package/lib/src/mixpanel-service.spec.js +7 -0
- package/lib/src/mixpanel-service.spec.js.map +1 -1
- package/lib/src/react/index.d.ts +1 -1
- package/lib/src/react/index.d.ts.map +1 -1
- package/lib/src/react/index.js +1 -1
- package/lib/src/react/index.js.map +1 -1
- package/lib/src/react/index.spec.js +6 -0
- package/lib/src/react/index.spec.js.map +1 -1
- package/lib/src/types.d.ts +79 -47
- package/lib/src/types.d.ts.map +1 -1
- package/lib/src/types.js +61 -46
- package/lib/src/types.js.map +1 -1
- package/lib/src/utils/authService/authService.d.ts +1 -0
- package/lib/src/utils/authService/authService.d.ts.map +1 -1
- package/lib/src/utils/authService/authService.js +1 -0
- package/lib/src/utils/authService/authService.js.map +1 -1
- package/lib/src/utils/authService/authService.spec.js +18 -5
- package/lib/src/utils/authService/authService.spec.js.map +1 -1
- package/lib/src/utils/authService/tokenizedAuthService.d.ts +15 -2
- package/lib/src/utils/authService/tokenizedAuthService.d.ts.map +1 -1
- package/lib/src/utils/authService/tokenizedAuthService.js +37 -8
- package/lib/src/utils/authService/tokenizedAuthService.js.map +1 -1
- package/lib/src/utils/authService/tokenizedAuthService.spec.d.ts +2 -0
- package/lib/src/utils/authService/tokenizedAuthService.spec.d.ts.map +1 -0
- package/lib/src/utils/authService/tokenizedAuthService.spec.js +29 -0
- package/lib/src/utils/authService/tokenizedAuthService.spec.js.map +1 -0
- package/lib/src/utils/graphql/answerService/answerService.d.ts +10 -0
- package/lib/src/utils/graphql/answerService/answerService.d.ts.map +1 -1
- package/lib/src/utils/graphql/answerService/answerService.js +10 -0
- package/lib/src/utils/graphql/answerService/answerService.js.map +1 -1
- package/lib/src/utils/processData.js +3 -3
- package/lib/src/utils/processData.js.map +1 -1
- package/lib/src/utils/processData.spec.js +3 -2
- package/lib/src/utils/processData.spec.js.map +1 -1
- package/lib/src/utils/sessionInfoService.d.ts +66 -0
- package/lib/src/utils/sessionInfoService.d.ts.map +1 -0
- package/lib/src/utils/sessionInfoService.js +85 -0
- package/lib/src/utils/sessionInfoService.js.map +1 -0
- package/lib/src/utils.d.ts +1 -1
- package/lib/src/utils.d.ts.map +1 -1
- package/lib/src/utils.js +4 -1
- package/lib/src/utils.js.map +1 -1
- package/lib/src/visual-embed-sdk.d.ts +176 -67
- package/package.json +1 -1
- package/src/auth.spec.ts +92 -72
- package/src/auth.ts +46 -68
- package/src/authToken.spec.ts +31 -0
- package/src/authToken.ts +17 -5
- package/src/embed/app.spec.ts +4 -2
- package/src/embed/base.spec.ts +1 -0
- package/src/embed/base.ts +3 -0
- package/src/embed/embed.spec.ts +2 -0
- package/src/embed/events.spec.ts +2 -0
- package/src/embed/liveboard.spec.ts +2 -0
- package/src/embed/pinboard.spec.ts +2 -0
- package/src/embed/sage.spec.ts +3 -0
- package/src/embed/search.spec.ts +1 -0
- package/src/embed/ts-embed-trigger.spec.ts +3 -0
- package/src/embed/ts-embed.spec.ts +8 -0
- package/src/embed/ts-embed.ts +7 -0
- package/src/index.ts +2 -1
- package/src/mixpanel-service.spec.ts +12 -3
- package/src/mixpanel-service.ts +3 -1
- package/src/react/index.spec.tsx +7 -0
- package/src/react/index.tsx +1 -0
- package/src/types.ts +80 -47
- package/src/utils/authService/authService.spec.ts +18 -5
- package/src/utils/authService/authService.ts +1 -0
- package/src/utils/authService/tokenizedAuthService.spec.ts +36 -0
- package/src/utils/authService/tokenizedAuthService.ts +38 -8
- package/src/utils/graphql/answerService/answerService.ts +10 -0
- package/src/utils/processData.spec.ts +3 -2
- package/src/utils/processData.ts +3 -3
- package/src/utils/sessionInfoService.ts +101 -0
- package/src/utils.ts +7 -2
package/src/auth.spec.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import * as authInstance from './auth';
|
|
2
|
-
import * as
|
|
3
|
-
import * as tokenAuthService from './utils/authService/tokenizedAuthService';
|
|
4
|
-
import * as checkReleaseVersionInBetaInstance from './utils';
|
|
5
|
-
import * as mixPanelService from './mixpanel-service';
|
|
2
|
+
import * as authTokenService from './authToken';
|
|
6
3
|
import * as EmbedConfig from './embed/embedConfig';
|
|
7
|
-
import
|
|
4
|
+
import * as mixPanelService from './mixpanel-service';
|
|
8
5
|
import { executeAfterWait } from './test/test-utils';
|
|
9
|
-
import {
|
|
6
|
+
import { AuthType, EmbedEvent } from './types';
|
|
7
|
+
import * as checkReleaseVersionInBetaInstance from './utils';
|
|
8
|
+
import * as authService from './utils/authService/authService';
|
|
9
|
+
import * as tokenAuthService from './utils/authService/tokenizedAuthService';
|
|
10
|
+
import { logger } from './utils/logger';
|
|
11
|
+
import * as SessionService from './utils/sessionInfoService';
|
|
10
12
|
|
|
11
13
|
const thoughtSpotHost = 'http://localhost:3000';
|
|
12
14
|
const username = 'tsuser';
|
|
@@ -18,7 +20,7 @@ export const embedConfig: any = {
|
|
|
18
20
|
thoughtSpotHost,
|
|
19
21
|
username,
|
|
20
22
|
authEndpoint: 'auth',
|
|
21
|
-
authType: AuthType.
|
|
23
|
+
authType: AuthType.TrustedAuthToken,
|
|
22
24
|
getAuthToken: jest.fn(() => Promise.resolve(token)),
|
|
23
25
|
}),
|
|
24
26
|
doTokenAuthWithCookieDetect: {
|
|
@@ -112,31 +114,47 @@ export const mockSessionInfo = {
|
|
|
112
114
|
},
|
|
113
115
|
};
|
|
114
116
|
|
|
117
|
+
export const mockSessionInfoApiResponse = {
|
|
118
|
+
userGUID: '1234',
|
|
119
|
+
releaseVersion: 'test',
|
|
120
|
+
configInfo: {
|
|
121
|
+
isPublicUser: false,
|
|
122
|
+
mixpanelConfig: {
|
|
123
|
+
production: true,
|
|
124
|
+
devSdkKey: 'devKey',
|
|
125
|
+
prodSdkKey: 'prodKey',
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
|
|
115
130
|
describe('Unit test for auth', () => {
|
|
116
131
|
beforeEach(() => {
|
|
132
|
+
jest.resetAllMocks();
|
|
117
133
|
global.fetch = window.fetch;
|
|
118
134
|
});
|
|
119
135
|
afterEach(() => {
|
|
120
|
-
resetCachedAuthToken();
|
|
136
|
+
authTokenService.resetCachedAuthToken();
|
|
137
|
+
SessionService.resetCachedSessionInfo();
|
|
121
138
|
});
|
|
122
139
|
test('endpoints, SAML_LOGIN_TEMPLATE', () => {
|
|
123
140
|
const ssoTemplateUrl = authService.EndPoints.SAML_LOGIN_TEMPLATE(thoughtSpotHost);
|
|
124
141
|
expect(ssoTemplateUrl).toBe(`/callosum/v1/saml/login?targetURLPath=${thoughtSpotHost}`);
|
|
125
142
|
});
|
|
126
143
|
|
|
127
|
-
test('when session info giving response', async () => {
|
|
128
|
-
jest.spyOn(
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
expect(sessionInfo).
|
|
144
|
+
test('when session info giving response, it is cached', async () => {
|
|
145
|
+
jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockResolvedValueOnce(mockSessionInfoApiResponse);
|
|
146
|
+
const sessionInfo = await SessionService.getSessionInfo();
|
|
147
|
+
expect(sessionInfo.mixpanelToken).toEqual('prodKey');
|
|
148
|
+
expect(sessionInfo.isPublicUser).toEqual(false);
|
|
149
|
+
await SessionService.getSessionInfo();
|
|
150
|
+
expect(tokenAuthService.fetchSessionInfoService).toHaveBeenCalledTimes(1);
|
|
132
151
|
});
|
|
133
152
|
|
|
134
153
|
test('Disable mixpanel when disableSDKTracking flag is set', () => {
|
|
135
|
-
jest.clearAllMocks();
|
|
136
|
-
jest.resetAllMocks();
|
|
137
154
|
jest.spyOn(mixPanelService, 'initMixpanel');
|
|
155
|
+
jest.spyOn(SessionService, 'getSessionInfo').mockReturnValue(mockSessionInfo);
|
|
138
156
|
jest.spyOn(EmbedConfig, 'getEmbedConfig').mockReturnValue({ disableSDKTracking: true });
|
|
139
|
-
authInstance.
|
|
157
|
+
authInstance.postLoginService();
|
|
140
158
|
expect(mixPanelService.initMixpanel).not.toBeCalled();
|
|
141
159
|
});
|
|
142
160
|
|
|
@@ -163,28 +181,22 @@ describe('Unit test for auth', () => {
|
|
|
163
181
|
});
|
|
164
182
|
|
|
165
183
|
test('doTokenAuth: when user is loggedIn', async () => {
|
|
166
|
-
jest.spyOn(
|
|
167
|
-
|
|
168
|
-
status: 200,
|
|
169
|
-
}));
|
|
170
|
-
jest.spyOn(authInstance, 'getSessionDetails').mockReturnValue(mockSessionInfo);
|
|
171
|
-
jest.spyOn(authInstance, 'initSession').mockReturnValue(null);
|
|
184
|
+
const getAuthenticationTokenMock = jest.spyOn(authTokenService, 'getAuthenticationToken');
|
|
185
|
+
jest.spyOn(tokenAuthService, 'isActiveService').mockImplementation(async () => true);
|
|
172
186
|
await authInstance.doTokenAuth(embedConfig.doTokenAuthSuccess('authToken'));
|
|
173
|
-
expect(
|
|
187
|
+
expect(authTokenService.getAuthenticationToken).not.toBeCalled();
|
|
174
188
|
expect(authInstance.loggedInStatus).toBe(true);
|
|
189
|
+
getAuthenticationTokenMock.mockRestore();
|
|
175
190
|
});
|
|
176
191
|
|
|
177
192
|
test('doTokenAuth: when user is not loggedIn & getAuthToken have response', async () => {
|
|
178
|
-
jest.spyOn(tokenAuthService, '
|
|
179
|
-
jest.spyOn(authService, 'fetchAuthTokenService').mockImplementation(() => ({
|
|
180
|
-
text: () => Promise.resolve('abc'),
|
|
181
|
-
}));
|
|
193
|
+
jest.spyOn(tokenAuthService, 'isActiveService').mockImplementation(async () => false);
|
|
182
194
|
jest.spyOn(authService, 'fetchAuthService').mockImplementation(() => Promise.resolve({
|
|
183
195
|
status: 200,
|
|
196
|
+
ok: true,
|
|
184
197
|
}));
|
|
185
198
|
jest.spyOn(authService, 'verifyTokenService').mockResolvedValueOnce(true);
|
|
186
199
|
await authInstance.doTokenAuth(embedConfig.doTokenAuthSuccess('authToken2'));
|
|
187
|
-
expect(tokenAuthService.fetchSessionInfoService).toBeCalled();
|
|
188
200
|
expect(authService.fetchAuthService).toBeCalledWith(
|
|
189
201
|
thoughtSpotHost,
|
|
190
202
|
username,
|
|
@@ -193,26 +205,25 @@ describe('Unit test for auth', () => {
|
|
|
193
205
|
});
|
|
194
206
|
|
|
195
207
|
test('doTokenAuth: when user is not loggedIn & getAuthToken not present, isLoggedIn should called', async () => {
|
|
196
|
-
jest.spyOn(tokenAuthService, '
|
|
197
|
-
jest.spyOn(authService, 'fetchAuthTokenService').mockImplementation(() =>
|
|
208
|
+
jest.spyOn(tokenAuthService, 'isActiveService').mockImplementation(async () => false);
|
|
209
|
+
jest.spyOn(authService, 'fetchAuthTokenService').mockImplementation(() => ({
|
|
210
|
+
text: () => Promise.resolve('abc'),
|
|
211
|
+
}));
|
|
198
212
|
jest.spyOn(authService, 'fetchAuthService').mockImplementation(() => Promise.resolve({
|
|
199
213
|
status: 200,
|
|
200
214
|
ok: true,
|
|
201
215
|
}));
|
|
202
216
|
jest.spyOn(authService, 'verifyTokenService').mockResolvedValueOnce(true);
|
|
203
217
|
await authInstance.doTokenAuth(embedConfig.doTokenAuthFailureWithoutGetAuthToken);
|
|
218
|
+
expect(authService.fetchAuthTokenService).toBeCalledWith('auth');
|
|
204
219
|
await executeAfterWait(() => {
|
|
205
220
|
expect(authInstance.loggedInStatus).toBe(true);
|
|
206
|
-
expect(
|
|
207
|
-
expect(authService.fetchAuthService).toBeCalledWith(
|
|
208
|
-
thoughtSpotHost,
|
|
209
|
-
username,
|
|
210
|
-
'authToken2',
|
|
211
|
-
);
|
|
221
|
+
expect(authService.fetchAuthService).toBeCalledWith(thoughtSpotHost, username, 'abc');
|
|
212
222
|
});
|
|
213
223
|
});
|
|
214
224
|
|
|
215
225
|
test('doTokenAuth: Should raise error when duplicate token is used', async () => {
|
|
226
|
+
jest.spyOn(tokenAuthService, 'isActiveService').mockImplementation(async () => false);
|
|
216
227
|
jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockResolvedValue({
|
|
217
228
|
status: 401,
|
|
218
229
|
});
|
|
@@ -254,8 +265,10 @@ describe('Unit test for auth', () => {
|
|
|
254
265
|
ok: true,
|
|
255
266
|
}));
|
|
256
267
|
jest.spyOn(authService, 'verifyTokenService').mockResolvedValueOnce(true);
|
|
268
|
+
jest.spyOn(tokenAuthService, 'isActiveService').mockResolvedValueOnce(false);
|
|
269
|
+
jest.spyOn(tokenAuthService, 'isActiveService').mockResolvedValueOnce(false);
|
|
257
270
|
const isLoggedIn = await authInstance.doTokenAuth(embedConfig.doTokenAuthWithCookieDetect);
|
|
258
|
-
expect(tokenAuthService.
|
|
271
|
+
expect(tokenAuthService.isActiveService).toHaveBeenCalledTimes(2);
|
|
259
272
|
expect(isLoggedIn).toBe(false);
|
|
260
273
|
});
|
|
261
274
|
|
|
@@ -278,7 +291,6 @@ describe('Unit test for auth', () => {
|
|
|
278
291
|
expect(await authInstance.doTokenAuth(embedConfig.doTokenAuthSuccess('authToken2'))).toBe(
|
|
279
292
|
true,
|
|
280
293
|
);
|
|
281
|
-
expect(tokenAuthService.fetchSessionInfoService).toBeCalled();
|
|
282
294
|
expect(authService.fetchAuthPostService).toBeCalledWith(
|
|
283
295
|
thoughtSpotHost,
|
|
284
296
|
username,
|
|
@@ -297,20 +309,9 @@ describe('Unit test for auth', () => {
|
|
|
297
309
|
});
|
|
298
310
|
|
|
299
311
|
it('when user is loggedIn', async () => {
|
|
300
|
-
spyOn(
|
|
301
|
-
jest.spyOn(authInstance, 'getSessionDetails').mockReturnValue(mockSessionInfo);
|
|
302
|
-
jest.spyOn(authInstance, 'initSession').mockReturnValue(null);
|
|
303
|
-
jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockImplementation(
|
|
304
|
-
async () => ({
|
|
305
|
-
json: () => mockSessionInfo,
|
|
306
|
-
status: 200,
|
|
307
|
-
}),
|
|
308
|
-
);
|
|
312
|
+
jest.spyOn(tokenAuthService, 'isActiveService').mockResolvedValueOnce(true);
|
|
309
313
|
await authInstance.doBasicAuth(embedConfig.doBasicAuth);
|
|
310
|
-
expect(tokenAuthService.fetchSessionInfoService).toBeCalled();
|
|
311
314
|
expect(authInstance.loggedInStatus).toBe(true);
|
|
312
|
-
expect(authInstance.getSessionDetails).toBeCalled();
|
|
313
|
-
expect(authInstance.initSession).toBeCalled();
|
|
314
315
|
});
|
|
315
316
|
|
|
316
317
|
it('when user is not loggedIn', async () => {
|
|
@@ -321,7 +322,7 @@ describe('Unit test for auth', () => {
|
|
|
321
322
|
}));
|
|
322
323
|
|
|
323
324
|
await authInstance.doBasicAuth(embedConfig.doBasicAuth);
|
|
324
|
-
expect(tokenAuthService.fetchSessionInfoService).toBeCalled();
|
|
325
|
+
// expect(tokenAuthService.fetchSessionInfoService).toBeCalled();
|
|
325
326
|
expect(authService.fetchBasicAuthService).toBeCalled();
|
|
326
327
|
expect(authInstance.loggedInStatus).toBe(true);
|
|
327
328
|
});
|
|
@@ -349,10 +350,8 @@ describe('Unit test for auth', () => {
|
|
|
349
350
|
status: 200,
|
|
350
351
|
}),
|
|
351
352
|
);
|
|
352
|
-
jest.spyOn(
|
|
353
|
-
jest.spyOn(authInstance, 'initSession').mockReturnValue(null);
|
|
353
|
+
jest.spyOn(tokenAuthService, 'isActiveService').mockReturnValue(true);
|
|
354
354
|
await authInstance.doSamlAuth(embedConfig.doSamlAuth);
|
|
355
|
-
expect(tokenAuthService.fetchSessionInfoService).toBeCalled();
|
|
356
355
|
expect(window.location.hash).toBe('');
|
|
357
356
|
expect(authInstance.loggedInStatus).toBe(true);
|
|
358
357
|
});
|
|
@@ -360,7 +359,6 @@ describe('Unit test for auth', () => {
|
|
|
360
359
|
it('when user is not loggedIn & isAtSSORedirectUrl is true', async () => {
|
|
361
360
|
jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockImplementation(() => Promise.reject());
|
|
362
361
|
await authInstance.doSamlAuth(embedConfig.doSamlAuth);
|
|
363
|
-
expect(tokenAuthService.fetchSessionInfoService).toBeCalled();
|
|
364
362
|
expect(window.location.hash).toBe('');
|
|
365
363
|
expect(authInstance.loggedInStatus).toBe(false);
|
|
366
364
|
});
|
|
@@ -374,7 +372,6 @@ describe('Unit test for auth', () => {
|
|
|
374
372
|
});
|
|
375
373
|
jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockImplementation(() => Promise.reject());
|
|
376
374
|
await authInstance.doSamlAuth(embedConfig.doSamlAuth);
|
|
377
|
-
expect(tokenAuthService.fetchSessionInfoService).toBeCalled();
|
|
378
375
|
expect(global.window.location.href).toBe(samalLoginUrl);
|
|
379
376
|
});
|
|
380
377
|
|
|
@@ -387,14 +384,9 @@ describe('Unit test for auth', () => {
|
|
|
387
384
|
});
|
|
388
385
|
spyOn(authInstance, 'samlCompletionPromise');
|
|
389
386
|
global.window.open = jest.fn();
|
|
390
|
-
jest.spyOn(tokenAuthService, '
|
|
391
|
-
.
|
|
392
|
-
.
|
|
393
|
-
json: () => mockSessionInfo,
|
|
394
|
-
status: 200,
|
|
395
|
-
}));
|
|
396
|
-
jest.spyOn(authInstance, 'getSessionDetails').mockReturnValue(mockSessionInfo);
|
|
397
|
-
jest.spyOn(authInstance, 'initSession').mockReturnValue(null);
|
|
387
|
+
jest.spyOn(tokenAuthService, 'isActiveService')
|
|
388
|
+
.mockReturnValueOnce(false)
|
|
389
|
+
.mockReturnValueOnce(true);
|
|
398
390
|
expect(await authInstance.samlCompletionPromise).not.toBe(null);
|
|
399
391
|
expect(
|
|
400
392
|
await authInstance.doSamlAuth({
|
|
@@ -404,15 +396,13 @@ describe('Unit test for auth', () => {
|
|
|
404
396
|
document.getElementById('ts-auth-btn').click();
|
|
405
397
|
window.postMessage({ type: EmbedEvent.SAMLComplete }, '*');
|
|
406
398
|
await authInstance.samlCompletionPromise;
|
|
407
|
-
expect(
|
|
408
|
-
expect(authInstance.getSessionDetails).toBeCalled();
|
|
409
|
-
expect(authInstance.initSession).toBeCalled();
|
|
399
|
+
expect(authInstance.loggedInStatus).toBe(true);
|
|
410
400
|
});
|
|
411
401
|
});
|
|
412
402
|
|
|
413
403
|
describe('doOIDCAuth', () => {
|
|
414
404
|
afterEach(() => {
|
|
415
|
-
resetCachedAuthToken();
|
|
405
|
+
authTokenService.resetCachedAuthToken();
|
|
416
406
|
delete global.window;
|
|
417
407
|
global.window = Object.create(originalWindow);
|
|
418
408
|
global.window.open = jest.fn();
|
|
@@ -422,7 +412,6 @@ describe('Unit test for auth', () => {
|
|
|
422
412
|
it('when user is not loggedIn & isAtSSORedirectUrl is true', async () => {
|
|
423
413
|
jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockImplementation(() => Promise.reject());
|
|
424
414
|
await authInstance.doOIDCAuth(embedConfig.doOidcAuth);
|
|
425
|
-
expect(tokenAuthService.fetchSessionInfoService).toBeCalled();
|
|
426
415
|
expect(window.location.hash).toBe('');
|
|
427
416
|
expect(authInstance.loggedInStatus).toBe(false);
|
|
428
417
|
});
|
|
@@ -465,6 +454,7 @@ describe('Unit test for auth', () => {
|
|
|
465
454
|
|
|
466
455
|
it('authenticate: when authType is Basic', async () => {
|
|
467
456
|
jest.spyOn(authInstance, 'doBasicAuth');
|
|
457
|
+
jest.spyOn(authService, 'fetchBasicAuthService').mockImplementation(() => Promise.resolve({ status: 200, ok: true }));
|
|
468
458
|
await authInstance.authenticate(embedConfig.basicAuthSuccess);
|
|
469
459
|
expect(authInstance.doBasicAuth).toBeCalled();
|
|
470
460
|
expect(authInstance.loggedInStatus).toBe(true);
|
|
@@ -481,6 +471,7 @@ describe('Unit test for auth', () => {
|
|
|
481
471
|
});
|
|
482
472
|
|
|
483
473
|
it('doCookielessTokenAuth should resolve to true if valid token is passed', async () => {
|
|
474
|
+
jest.clearAllMocks();
|
|
484
475
|
jest.spyOn(authService, 'verifyTokenService').mockResolvedValueOnce(true);
|
|
485
476
|
const isLoggedIn = await authInstance.doCookielessTokenAuth(
|
|
486
477
|
embedConfig.doCookielessAuth('testToken'),
|
|
@@ -500,11 +491,11 @@ describe('Unit test for auth', () => {
|
|
|
500
491
|
authInstance.setAuthEE(testObject as any);
|
|
501
492
|
expect(authInstance.getAuthEE()).toBe(testObject);
|
|
502
493
|
});
|
|
503
|
-
it('getSessionDetails returns the correct details given sessionInfo', () => {
|
|
494
|
+
it('getSessionDetails returns the correct details given sessionInfo', async () => {
|
|
504
495
|
jest.clearAllMocks();
|
|
505
496
|
jest.restoreAllMocks();
|
|
506
497
|
|
|
507
|
-
|
|
498
|
+
jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockReturnValue({
|
|
508
499
|
userGUID: '1234',
|
|
509
500
|
releaseVersion: '1',
|
|
510
501
|
configInfo: {
|
|
@@ -515,13 +506,14 @@ describe('Unit test for auth', () => {
|
|
|
515
506
|
},
|
|
516
507
|
},
|
|
517
508
|
});
|
|
509
|
+
const details = await SessionService.getSessionInfo();
|
|
518
510
|
expect(details).toEqual(
|
|
519
511
|
expect.objectContaining({
|
|
520
512
|
mixpanelToken: 'devKey',
|
|
521
513
|
}),
|
|
522
514
|
);
|
|
523
515
|
|
|
524
|
-
|
|
516
|
+
jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockReturnValue({
|
|
525
517
|
configInfo: {
|
|
526
518
|
mixpanelConfig: {
|
|
527
519
|
devSdkKey: 'devKey',
|
|
@@ -530,10 +522,38 @@ describe('Unit test for auth', () => {
|
|
|
530
522
|
},
|
|
531
523
|
},
|
|
532
524
|
});
|
|
525
|
+
|
|
526
|
+
SessionService.resetCachedSessionInfo();
|
|
527
|
+
const details2 = await SessionService.getSessionInfo();
|
|
533
528
|
expect(details2).toEqual(
|
|
534
529
|
expect.objectContaining({
|
|
535
530
|
mixpanelToken: 'prodKey',
|
|
536
531
|
}),
|
|
537
532
|
);
|
|
538
533
|
});
|
|
534
|
+
|
|
535
|
+
test('notifyAuthSuccess if getSessionInfo returns data', async () => {
|
|
536
|
+
const dummyInfo = { test: 'dummy' };
|
|
537
|
+
jest.spyOn(SessionService, 'getSessionInfo').mockResolvedValueOnce(dummyInfo);
|
|
538
|
+
jest.spyOn(logger, 'error').mockResolvedValueOnce(true);
|
|
539
|
+
const emitSpy = jest.fn();
|
|
540
|
+
authInstance.setAuthEE({ emit: emitSpy } as any);
|
|
541
|
+
await authInstance.notifyAuthSuccess();
|
|
542
|
+
expect(logger.error).not.toBeCalled();
|
|
543
|
+
expect(emitSpy).toBeCalledWith(authInstance.AuthStatus.SUCCESS, dummyInfo);
|
|
544
|
+
authInstance.setAuthEE(null);
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
test('notifyAuthSuccess if getSessionInfo fails', async () => {
|
|
548
|
+
jest.spyOn(SessionService, 'getSessionInfo').mockImplementation(() => {
|
|
549
|
+
throw new Error('error');
|
|
550
|
+
});
|
|
551
|
+
jest.spyOn(logger, 'error');
|
|
552
|
+
const emitSpy = jest.fn();
|
|
553
|
+
authInstance.setAuthEE({ emit: emitSpy } as any);
|
|
554
|
+
await authInstance.notifyAuthSuccess();
|
|
555
|
+
expect(logger.error).toBeCalled();
|
|
556
|
+
expect(emitSpy).not.toBeCalled();
|
|
557
|
+
authInstance.setAuthEE(null);
|
|
558
|
+
});
|
|
539
559
|
});
|
package/src/auth.ts
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import EventEmitter from 'eventemitter3';
|
|
2
|
+
import { getAuthenticationToken, resetCachedAuthToken } from './authToken';
|
|
3
|
+
import { getEmbedConfig } from './embed/embedConfig';
|
|
2
4
|
import { initMixpanel } from './mixpanel-service';
|
|
3
5
|
import {
|
|
4
|
-
AuthType, DOMSelector, EmbedConfig, EmbedEvent,
|
|
6
|
+
AuthType, DOMSelector, EmbedConfig, EmbedEvent,
|
|
5
7
|
} from './types';
|
|
6
8
|
import { getDOMNode, getRedirectUrl } from './utils';
|
|
7
9
|
import {
|
|
8
|
-
|
|
10
|
+
EndPoints,
|
|
11
|
+
fetchAuthPostService,
|
|
9
12
|
fetchAuthService,
|
|
10
13
|
fetchBasicAuthService,
|
|
11
14
|
fetchLogoutService,
|
|
12
|
-
fetchAuthPostService,
|
|
13
|
-
EndPoints,
|
|
14
15
|
} from './utils/authService';
|
|
15
|
-
import {
|
|
16
|
+
import { isActiveService } from './utils/authService/tokenizedAuthService';
|
|
16
17
|
import { logger } from './utils/logger';
|
|
17
|
-
import {
|
|
18
|
+
import { getSessionInfo } from './utils/sessionInfoService';
|
|
18
19
|
|
|
19
20
|
// eslint-disable-next-line import/no-mutable-exports
|
|
20
21
|
export let loggedInStatus = false;
|
|
@@ -22,22 +23,11 @@ export let loggedInStatus = false;
|
|
|
22
23
|
export let samlAuthWindow: Window = null;
|
|
23
24
|
// eslint-disable-next-line import/no-mutable-exports
|
|
24
25
|
export let samlCompletionPromise: Promise<void> = null;
|
|
25
|
-
|
|
26
|
-
let sessionInfoResolver: (value: sessionInfoInterface) => void = null;
|
|
27
|
-
const sessionInfoPromise = new Promise((resolve: (value: sessionInfoInterface) => void) => {
|
|
28
|
-
sessionInfoResolver = resolve;
|
|
29
|
-
});
|
|
26
|
+
|
|
30
27
|
let releaseVersion = '';
|
|
31
28
|
|
|
32
29
|
export const SSO_REDIRECTION_MARKER_GUID = '5e16222e-ef02-43e9-9fbd-24226bf3ce5b';
|
|
33
30
|
|
|
34
|
-
interface sessionInfoInterface {
|
|
35
|
-
userGUID: any;
|
|
36
|
-
isPublicUser: any;
|
|
37
|
-
mixpanelToken: any;
|
|
38
|
-
[key: string]: any;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
31
|
/**
|
|
42
32
|
* Enum for auth failure types. This is the parameter passed to the listner
|
|
43
33
|
* of {@link AuthStatus.FAILURE}.
|
|
@@ -180,12 +170,17 @@ export function notifyAuthSDKSuccess(): void {
|
|
|
180
170
|
/**
|
|
181
171
|
*
|
|
182
172
|
*/
|
|
183
|
-
export function notifyAuthSuccess(): void {
|
|
173
|
+
export async function notifyAuthSuccess(): Promise<void> {
|
|
184
174
|
if (!authEE) {
|
|
185
175
|
logger.error('SDK not initialized');
|
|
186
176
|
return;
|
|
187
177
|
}
|
|
188
|
-
|
|
178
|
+
try {
|
|
179
|
+
const sessionInfo = await getSessionInfo();
|
|
180
|
+
authEE.emit(AuthStatus.SUCCESS, sessionInfo);
|
|
181
|
+
} catch (e) {
|
|
182
|
+
logger.error('Failed to get session info');
|
|
183
|
+
}
|
|
189
184
|
}
|
|
190
185
|
|
|
191
186
|
/**
|
|
@@ -211,70 +206,46 @@ export function notifyLogout(): void {
|
|
|
211
206
|
authEE.emit(AuthStatus.LOGOUT);
|
|
212
207
|
}
|
|
213
208
|
|
|
214
|
-
export const initSession = (sessionDetails: sessionInfoInterface) => {
|
|
215
|
-
const embedConfig = getEmbedConfig();
|
|
216
|
-
if (sessionInfo == null) {
|
|
217
|
-
sessionInfo = sessionDetails;
|
|
218
|
-
if (!embedConfig.disableSDKTracking) {
|
|
219
|
-
initMixpanel(sessionInfo);
|
|
220
|
-
}
|
|
221
|
-
sessionInfoResolver(sessionInfo);
|
|
222
|
-
}
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
export const getSessionDetails = (sessionInfoResp: any): sessionInfoInterface => {
|
|
226
|
-
const devMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.devSdkKey;
|
|
227
|
-
const prodMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.prodSdkKey;
|
|
228
|
-
const mixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.production
|
|
229
|
-
? prodMixpanelToken
|
|
230
|
-
: devMixpanelToken;
|
|
231
|
-
return {
|
|
232
|
-
userGUID: sessionInfoResp.userGUID,
|
|
233
|
-
mixpanelToken,
|
|
234
|
-
isPublicUser: sessionInfoResp.configInfo.isPublicUser,
|
|
235
|
-
releaseVersion: sessionInfoResp.releaseVersion,
|
|
236
|
-
clusterId: sessionInfoResp.configInfo.selfClusterId,
|
|
237
|
-
clusterName: sessionInfoResp.configInfo.selfClusterName,
|
|
238
|
-
...sessionInfoResp,
|
|
239
|
-
};
|
|
240
|
-
};
|
|
241
|
-
|
|
242
209
|
/**
|
|
243
210
|
* Check if we are logged into the ThoughtSpot cluster
|
|
244
211
|
*
|
|
245
212
|
* @param thoughtSpotHost The ThoughtSpot cluster hostname or IP
|
|
246
213
|
*/
|
|
247
214
|
async function isLoggedIn(thoughtSpotHost: string): Promise<boolean> {
|
|
248
|
-
const authVerificationUrl = `${thoughtSpotHost}${EndPoints.AUTH_VERIFICATION}`;
|
|
249
|
-
let response = null;
|
|
250
215
|
try {
|
|
251
|
-
response = await
|
|
252
|
-
|
|
253
|
-
const sessionDetails = getSessionDetails(sessionInfoResp);
|
|
254
|
-
// Store user session details from session info
|
|
255
|
-
initSession(sessionDetails);
|
|
256
|
-
releaseVersion = sessionInfoResp.releaseVersion;
|
|
216
|
+
const response = await isActiveService(thoughtSpotHost);
|
|
217
|
+
return response;
|
|
257
218
|
} catch (e) {
|
|
258
219
|
return false;
|
|
259
220
|
}
|
|
260
|
-
return response.status === 200;
|
|
261
221
|
}
|
|
262
222
|
|
|
263
223
|
/**
|
|
264
|
-
*
|
|
224
|
+
* Services to be called after the login is successful,
|
|
225
|
+
* This should be called after the cookie is set for cookie auth or
|
|
226
|
+
* after the token is set for cookieless.
|
|
227
|
+
*
|
|
228
|
+
* @return {Promise<void>}
|
|
229
|
+
* @example
|
|
230
|
+
* ```js
|
|
231
|
+
* await postLoginService();
|
|
232
|
+
* ```
|
|
233
|
+
* @version SDK: 1.28.3 | ThoughtSpot: *
|
|
265
234
|
*/
|
|
266
|
-
export function
|
|
267
|
-
|
|
235
|
+
export async function postLoginService(): Promise<void> {
|
|
236
|
+
const sessionInfo = await getSessionInfo();
|
|
237
|
+
releaseVersion = sessionInfo.releaseVersion;
|
|
238
|
+
const embedConfig = getEmbedConfig();
|
|
239
|
+
if (!embedConfig.disableSDKTracking) {
|
|
240
|
+
initMixpanel(sessionInfo);
|
|
241
|
+
}
|
|
268
242
|
}
|
|
269
243
|
|
|
270
244
|
/**
|
|
271
|
-
* Return
|
|
272
|
-
* authentication is successful. And info is available.
|
|
273
|
-
*
|
|
274
|
-
* @group Global methods
|
|
245
|
+
* Return releaseVersion if available
|
|
275
246
|
*/
|
|
276
|
-
export function
|
|
277
|
-
return
|
|
247
|
+
export function getReleaseVersion() {
|
|
248
|
+
return releaseVersion;
|
|
278
249
|
}
|
|
279
250
|
|
|
280
251
|
/**
|
|
@@ -309,8 +280,15 @@ export const doTokenAuth = async (embedConfig: EmbedConfig): Promise<boolean> =>
|
|
|
309
280
|
throw new Error('Either auth endpoint or getAuthToken function must be provided');
|
|
310
281
|
}
|
|
311
282
|
loggedInStatus = await isLoggedIn(thoughtSpotHost);
|
|
283
|
+
|
|
312
284
|
if (!loggedInStatus) {
|
|
313
|
-
|
|
285
|
+
let authToken: string;
|
|
286
|
+
try {
|
|
287
|
+
authToken = await getAuthenticationToken(embedConfig);
|
|
288
|
+
} catch (e) {
|
|
289
|
+
loggedInStatus = false;
|
|
290
|
+
throw e;
|
|
291
|
+
}
|
|
314
292
|
let resp;
|
|
315
293
|
try {
|
|
316
294
|
resp = await fetchAuthPostService(thoughtSpotHost, username, authToken);
|
|
@@ -492,7 +470,7 @@ export const logout = async (embedConfig: EmbedConfig): Promise<boolean> => {
|
|
|
492
470
|
const { thoughtSpotHost } = embedConfig;
|
|
493
471
|
await fetchLogoutService(thoughtSpotHost);
|
|
494
472
|
resetCachedAuthToken();
|
|
495
|
-
const thoughtspotIframes = document.querySelectorAll(
|
|
473
|
+
const thoughtspotIframes = document.querySelectorAll("[data-ts-iframe='true']");
|
|
496
474
|
if (thoughtspotIframes?.length) {
|
|
497
475
|
thoughtspotIframes.forEach((el) => {
|
|
498
476
|
el.parentElement.innerHTML = embedConfig.loginFailedMessage;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { getAuthenticationToken, resetCachedAuthToken } from './authToken';
|
|
2
|
+
import * as authServiceInstance from './utils/authService/authService';
|
|
3
|
+
import { EmbedConfig } from './types';
|
|
4
|
+
|
|
5
|
+
describe('AuthToken Unit tests', () => {
|
|
6
|
+
test('getAuthenticationToken: When verification is disabled', async () => {
|
|
7
|
+
jest.spyOn(authServiceInstance, 'verifyTokenService');
|
|
8
|
+
|
|
9
|
+
const token = await getAuthenticationToken({
|
|
10
|
+
getAuthToken: async () => 'abc3',
|
|
11
|
+
disableTokenVerification: true,
|
|
12
|
+
} as EmbedConfig);
|
|
13
|
+
|
|
14
|
+
expect(token).toBe('abc3');
|
|
15
|
+
expect(authServiceInstance.verifyTokenService).not.toBeCalled();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test.only('getAuthenticationToken: When verification is enabled', async () => {
|
|
19
|
+
resetCachedAuthToken();
|
|
20
|
+
jest.clearAllMocks();
|
|
21
|
+
jest.spyOn(authServiceInstance, 'verifyTokenService').mockImplementation(() => true);
|
|
22
|
+
const token = await getAuthenticationToken({
|
|
23
|
+
thoughtSpotHost: 'test',
|
|
24
|
+
getAuthToken: async () => 'abc2',
|
|
25
|
+
disableTokenVerification: false,
|
|
26
|
+
} as EmbedConfig);
|
|
27
|
+
|
|
28
|
+
expect(token).toBe('abc2');
|
|
29
|
+
expect(authServiceInstance.verifyTokenService).toBeCalledWith('test', 'abc2');
|
|
30
|
+
});
|
|
31
|
+
});
|
package/src/authToken.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { EmbedConfig } from './types';
|
|
2
2
|
import { fetchAuthTokenService, verifyTokenService } from './utils/authService/authService';
|
|
3
|
+
import { logger } from './utils/logger';
|
|
3
4
|
|
|
4
5
|
const DUPLICATE_TOKEN_ERR = 'Duplicate token, please issue a new token every time getAuthToken callback is called.'
|
|
5
6
|
+ 'See https://developers.thoughtspot.com/docs/?pageid=embed-auth#trusted-auth-embed for more details.';
|
|
@@ -9,8 +10,10 @@ const INVALID_TOKEN_ERR = 'Invalid token received form token callback or authTok
|
|
|
9
10
|
let cachedAuthToken: string | null = null;
|
|
10
11
|
|
|
11
12
|
// This method can be used to get the authToken using the embedConfig
|
|
12
|
-
export
|
|
13
|
-
if
|
|
13
|
+
export async function getAuthenticationToken(embedConfig: EmbedConfig): Promise<string> {
|
|
14
|
+
// Since we don't have token validation enabled , we cannot tell if the
|
|
15
|
+
// cached token is valid or not. So we will always fetch a new token.
|
|
16
|
+
if (cachedAuthToken && !embedConfig.disableTokenVerification) {
|
|
14
17
|
let isCachedTokenStillValid;
|
|
15
18
|
try {
|
|
16
19
|
isCachedTokenStillValid = await validateAuthToken(embedConfig, cachedAuthToken, true);
|
|
@@ -31,18 +34,27 @@ export const getAuthenticationToken = async (embedConfig: EmbedConfig): Promise<
|
|
|
31
34
|
authToken = await response.text();
|
|
32
35
|
}
|
|
33
36
|
|
|
34
|
-
|
|
35
|
-
|
|
37
|
+
try {
|
|
38
|
+
// this will throw error if the token is not valid
|
|
39
|
+
await validateAuthToken(embedConfig, authToken);
|
|
40
|
+
} catch (e) {
|
|
41
|
+
logger.error(`Received invalid token from getAuthToken callback or authToken endpoint. Error : ${e.message}`);
|
|
42
|
+
throw e;
|
|
43
|
+
}
|
|
36
44
|
|
|
37
45
|
cachedAuthToken = authToken;
|
|
38
46
|
return authToken;
|
|
39
|
-
}
|
|
47
|
+
}
|
|
40
48
|
|
|
41
49
|
const validateAuthToken = async (
|
|
42
50
|
embedConfig: EmbedConfig,
|
|
43
51
|
authToken: string,
|
|
44
52
|
suppressAlert?: boolean,
|
|
45
53
|
): Promise<boolean> => {
|
|
54
|
+
if (embedConfig.disableTokenVerification) {
|
|
55
|
+
logger.info('Token verification is disabled. Assuming token is valid.');
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
46
58
|
try {
|
|
47
59
|
const isTokenValid = await verifyTokenService(embedConfig.thoughtSpotHost, authToken);
|
|
48
60
|
if (isTokenValid) return true;
|
package/src/embed/app.spec.ts
CHANGED
|
@@ -24,6 +24,7 @@ import { version } from '../../package.json';
|
|
|
24
24
|
import * as config from '../config';
|
|
25
25
|
import { TsEmbed, V1Embed } from './ts-embed';
|
|
26
26
|
import { logger } from '../utils/logger';
|
|
27
|
+
import * as auth from '../auth';
|
|
27
28
|
|
|
28
29
|
const defaultViewConfig = {
|
|
29
30
|
frameParams: {
|
|
@@ -40,6 +41,7 @@ beforeAll(() => {
|
|
|
40
41
|
thoughtSpotHost,
|
|
41
42
|
authType: AuthType.None,
|
|
42
43
|
});
|
|
44
|
+
jest.spyOn(auth, 'postLoginService').mockImplementation(() => Promise.resolve({}));
|
|
43
45
|
(window as any).ResizeObserver = window.ResizeObserver
|
|
44
46
|
|| jest.fn().mockImplementation(() => ({
|
|
45
47
|
disconnect: jest.fn(),
|
|
@@ -72,13 +74,13 @@ describe('App embed tests', () => {
|
|
|
72
74
|
test('should hide the primary nav bar', async () => {
|
|
73
75
|
const appEmbed = new AppEmbed(getRootEl(), {
|
|
74
76
|
...defaultViewConfig,
|
|
75
|
-
showPrimaryNavbar:
|
|
77
|
+
showPrimaryNavbar: false,
|
|
76
78
|
} as AppViewConfig);
|
|
77
79
|
appEmbed.render();
|
|
78
80
|
await executeAfterWait(() => {
|
|
79
81
|
expectUrlMatchesWithParams(
|
|
80
82
|
getIFrameSrc(),
|
|
81
|
-
`http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=
|
|
83
|
+
`http://${thoughtSpotHost}/?embedApp=true&primaryNavHidden=true&profileAndHelpInNavBarHidden=false${defaultParams}${defaultParamsPost}#/home`,
|
|
82
84
|
);
|
|
83
85
|
});
|
|
84
86
|
});
|
package/src/embed/base.spec.ts
CHANGED