Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions src/auth.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import * as SessionService from './utils/sessionInfoService';
const thoughtSpotHost = 'http://localhost:3000';
const username = 'tsuser';
const password = '12345678';
const samalLoginUrl = `${thoughtSpotHost}/callosum/v1/saml/login?targetURLPath=%235e16222e-ef02-43e9-9fbd-24226bf3ce5b`;
const samalLoginUrl = `${thoughtSpotHost}/callosum/v1/saml/login?targetURLPath=%23%3FtsSSOMarker%3D5e16222e-ef02-43e9-9fbd-24226bf3ce5b`;

export const embedConfig: any = {
doTokenAuthSuccess: (token: string) => ({
Expand Down Expand Up @@ -331,8 +331,8 @@ describe('Unit test for auth', () => {
spyOn(checkReleaseVersionInBetaInstance, 'checkReleaseVersionInBeta');
Object.defineProperty(window, 'location', {
value: {
href: authInstance.SSO_REDIRECTION_MARKER_GUID,
hash: '',
href: `asd.com#?tsSSOMarker=${authInstance.SSO_REDIRECTION_MARKER_GUID}`,
hash: `?tsSSOMarker=${authInstance.SSO_REDIRECTION_MARKER_GUID}`,
},
});
jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockImplementation(
Expand All @@ -348,6 +348,12 @@ describe('Unit test for auth', () => {
});

it('when user is not loggedIn & isAtSSORedirectUrl is true', async () => {
Object.defineProperty(window, 'location', {
value: {
href: `asd.com#?tsSSOMarker=${authInstance.SSO_REDIRECTION_MARKER_GUID}`,
hash: `?tsSSOMarker=${authInstance.SSO_REDIRECTION_MARKER_GUID}`,
},
});
jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockImplementation(() => Promise.reject());
await authInstance.doSamlAuth(embedConfig.doSamlAuth);
expect(window.location.hash).toBe('');
Expand Down Expand Up @@ -401,6 +407,12 @@ describe('Unit test for auth', () => {
});

it('when user is not loggedIn & isAtSSORedirectUrl is true', async () => {
Object.defineProperty(window, 'location', {
value: {
href: `asd.com#?tsSSOMarker=${authInstance.SSO_REDIRECTION_MARKER_GUID}`,
hash: `?tsSSOMarker=${authInstance.SSO_REDIRECTION_MARKER_GUID}`,
},
});
jest.spyOn(tokenAuthService, 'fetchSessionInfoService').mockImplementation(() => Promise.reject());
await authInstance.doOIDCAuth(embedConfig.doOidcAuth);
expect(window.location.hash).toBe('');
Expand Down
10 changes: 7 additions & 3 deletions src/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import {
AuthType, DOMSelector, EmbedConfig, EmbedEvent,
} from './types';
import { getDOMNode, getRedirectUrl } from './utils';
import { getDOMNode, getRedirectUrl, getSSOMarker } from './utils';
import {
EndPoints,
fetchAuthPostService,
Expand Down Expand Up @@ -42,7 +42,7 @@
}

/**
* Enum for auth status emitted by the emitter returned from {@link init}.

Check warning on line 45 in src/auth.ts

View workflow job for this annotation

GitHub Actions / build

The type 'init' is undefined
* @group Authentication / Init
*/
export enum AuthStatus {
Expand All @@ -66,13 +66,13 @@
* Emitted when inPopup is true in the SAMLRedirect flow and the
* popup is waiting to be triggered either programmatically
* or by the trigger button.
* @version SDK: 1.19.0

Check warning on line 69 in src/auth.ts

View workflow job for this annotation

GitHub Actions / build

Invalid JSDoc @Version: "SDK: 1.19.0"
*/
WAITING_FOR_POPUP = 'WAITING_FOR_POPUP',
}

/**
* Event emitter returned from {@link init}.

Check warning on line 75 in src/auth.ts

View workflow job for this annotation

GitHub Actions / build

The type 'init' is undefined
* @group Authentication / Init
*/
export interface AuthEventEmitter {
Expand Down Expand Up @@ -100,7 +100,7 @@
once(event: AuthStatus.SUCCESS, listener: (sessionInfo: any) => void): this;
/**
* Trigger an event on the emitter returned from init.
* @param {@link AuthEvent}

Check warning on line 103 in src/auth.ts

View workflow job for this annotation

GitHub Actions / build

Syntax error in type: @link AuthEvent
*/
emit(event: AuthEvent, ...args: any[]): boolean;
/**
Expand All @@ -119,7 +119,7 @@
}

/**
* Events which can be triggered on the emitter returned from {@link init}.

Check warning on line 122 in src/auth.ts

View workflow job for this annotation

GitHub Actions / build

The type 'init' is undefined
* @group Authentication / Init
*/
export enum AuthEvent {
Expand All @@ -132,7 +132,7 @@

let authEE: EventEmitter<AuthStatus | AuthEvent>;

/**

Check warning on line 135 in src/auth.ts

View workflow job for this annotation

GitHub Actions / build

Missing JSDoc @returns declaration
*
*/
export function getAuthEE(): EventEmitter<AuthStatus | AuthEvent> {
Expand All @@ -141,7 +141,7 @@

/**
*
* @param eventEmitter

Check warning on line 144 in src/auth.ts

View workflow job for this annotation

GitHub Actions / build

Missing JSDoc @param "eventEmitter" description

Check warning on line 144 in src/auth.ts

View workflow job for this annotation

GitHub Actions / build

Missing JSDoc @param "eventEmitter" type
*/
export function setAuthEE(eventEmitter: EventEmitter<AuthStatus | AuthEvent>): void {
authEE = eventEmitter;
Expand Down Expand Up @@ -176,7 +176,7 @@

/**
*
* @param failureType

Check warning on line 179 in src/auth.ts

View workflow job for this annotation

GitHub Actions / build

Missing JSDoc @param "failureType" description

Check warning on line 179 in src/auth.ts

View workflow job for this annotation

GitHub Actions / build

Missing JSDoc @param "failureType" type
*/
export function notifyAuthFailure(failureType: AuthFailureType): void {
if (!authEE) {
Expand Down Expand Up @@ -245,7 +245,7 @@
* Check if we are stuck at the SSO redirect URL
*/
function isAtSSORedirectUrl(): boolean {
return window.location.href.indexOf(SSO_REDIRECTION_MARKER_GUID) >= 0;
return window.location.href.indexOf(getSSOMarker(SSO_REDIRECTION_MARKER_GUID)) >= 0;
}

/**
Expand All @@ -257,7 +257,11 @@
// reload the page which we don't want. We'll live with adding an
// unnecessary hash to the parent page URL until we find any use case where
// that creates an issue.
window.location.hash = window.location.hash.replace(SSO_REDIRECTION_MARKER_GUID, '');

// Replace any occurences of ?ssoMarker=guid or &ssoMarker=guid.
let updatedHash = window.location.hash.replace(`?${getSSOMarker(SSO_REDIRECTION_MARKER_GUID)}`, '');
updatedHash = updatedHash.replace(`&${getSSOMarker(SSO_REDIRECTION_MARKER_GUID)}`, '');
window.location.hash = updatedHash;
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/css-variables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ export interface CustomCssVariables {
/**
* Font color of the text on toggle buttons such as
* **All**, **Answers**, and **Liveboards** on the Home page (Classic experience),
* the text color of the chart and table tiles on Home page (New modular Homepage experience),
* and title text on the AI-generated charts and tables.
* the text color of the chart and table tiles on Home page (New modular Homepage
* experience), and title text on the AI-generated charts and tables.
* The default color code is #2770EF.
*
*/
Expand Down
3 changes: 0 additions & 3 deletions src/embed/liveboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,6 @@ export interface LiveboardViewConfig
*
* Since, this will show preview images, be careful that it may show
* undesired data to the user when using row level security.
*
* @example
* ```js
* const embed = new LiveboardEmbed('#embed-container', {
Expand All @@ -280,7 +279,6 @@ export interface LiveboardViewConfig
* });
* embed.render();
* ```
*
* @version SDK: 1.32.0 | ThoughtSpot: 10.0.0.cl
*/
showPreviewLoader?: boolean;
Expand Down Expand Up @@ -613,7 +611,6 @@ export class LiveboardEmbed extends V1Embed {
/**
* Returns the full url of the liveboard/viz which can be used to open
* this liveboard inside the full Thoughtspot application in a new tab.
*
* @returns url string
*/
public getLiveboardUrl(): string {
Expand Down
1 change: 0 additions & 1 deletion src/tokenizedFetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { AuthType } from './types';
* Fetch wrapper that adds the authentication token to the request.
* Use this to call the ThoughtSpot APIs when using the visual embed sdk.
* The interface for this method is the same as Web `Fetch`.
*
* @param input
* @param init
* @example
Expand Down
12 changes: 6 additions & 6 deletions src/utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@ describe('unit test for utils', () => {

test('appendToUrlHash', () => {
expect(appendToUrlHash('http://myhost:3000', 'hashFrag')).toBe(
'http://myhost:3000#hashFrag',
'http://myhost:3000#?tsSSOMarker=hashFrag',
);
expect(appendToUrlHash('http://xyz.com/#foo', 'bar')).toBe('http://xyz.com/#foobar');
expect(appendToUrlHash('http://xyz.com/#foo', 'bar')).toBe('http://xyz.com/#foo?tsSSOMarker=bar');
});

describe('getRedirectURL', () => {
Expand All @@ -135,9 +135,9 @@ describe('unit test for utils', () => {

test('Should return correct value when path is undefined', () => {
expect(getRedirectUrl('http://myhost:3000', 'hashFrag')).toBe(
'http://myhost:3000#hashFrag',
'http://myhost:3000#?tsSSOMarker=hashFrag',
);
expect(getRedirectUrl('http://xyz.com/#foo', 'bar')).toBe('http://xyz.com/#foobar');
expect(getRedirectUrl('http://xyz.com/#foo', 'bar')).toBe('http://xyz.com/#foo?tsSSOMarker=bar');
});

test('Should return correct value when path is set', () => {
Expand All @@ -148,11 +148,11 @@ describe('unit test for utils', () => {
}));

expect(getRedirectUrl('http://myhost:3000/', 'hashFrag', '/bar')).toBe(
'http://myhost:3000/bar#hashFrag',
'http://myhost:3000/bar#?tsSSOMarker=hashFrag',
);

expect(getRedirectUrl('http://myhost:3000/#/foo', 'hashFrag', '#/bar')).toBe(
'http://myhost:3000/#/barhashFrag',
'http://myhost:3000/#/bar?tsSSOMarker=hashFrag',
);
});
});
Expand Down
16 changes: 14 additions & 2 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ export const getCssDimension = (value: number | string): string => {
return value;
};

export const getSSOMarker = (markerId: string) => {
const encStringToAppend = encodeURIComponent(markerId);
return `tsSSOMarker=${encStringToAppend}`;
};

/**
* Append a string to a URL's hash fragment
* @param url A URL
Expand All @@ -140,11 +145,18 @@ export const appendToUrlHash = (url: string, stringToAppend: string) => {
let outputUrl = url;
const encStringToAppend = encodeURIComponent(stringToAppend);

const marker = `tsSSOMarker=${encStringToAppend}`;

let splitAdder = '';

if (url.indexOf('#') >= 0) {
outputUrl = `${outputUrl}${encStringToAppend}`;
// If second half of hash contains a '?' already add a '&' instead of
// '?' which appends to query params.
splitAdder = url.split('#')[1].indexOf('?') >= 0 ? '&' : '?';
} else {
outputUrl = `${outputUrl}#${encStringToAppend}`;
splitAdder = '#?';
}
outputUrl = `${outputUrl}${splitAdder}${marker}`;

return outputUrl;
};
Expand Down
1 change: 0 additions & 1 deletion src/utils/processData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ export function processCustomAction(e: any, thoughtSpotHost: string) {

/**
* Responds to AuthInit sent from host signifying successful authentication in host.
*
* @param e
* @returns {any}
*/
Expand Down
4 changes: 0 additions & 4 deletions src/utils/sessionInfoService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ let sessionInfo: null | SessionInfo = null;
* Returns the session info object and caches it for future use.
* Once fetched the session info object is cached and returned from the cache on
* subsequent calls.
*
* @example ```js
* const sessionInfo = await getSessionInfo();
* console.log(sessionInfo);
Expand All @@ -40,7 +39,6 @@ export async function getSessionInfo(): Promise<SessionInfo> {
/**
* Returns the cached session info object. If the client is not authenticated the
* function will return null.
*
* @example ```js
* const sessionInfo = getCachedSessionInfo();
* if (sessionInfo) {
Expand All @@ -58,7 +56,6 @@ export function getCachedSessionInfo(): SessionInfo | null {

/**
* Processes the session info response and returns the session info object.
*
* @param sessionInfoResp {any} Response from the session info API.
* @returns {SessionInfo} The session info object.
* @example ```js
Expand Down Expand Up @@ -87,7 +84,6 @@ export const getSessionDetails = (sessionInfoResp: any): SessionInfo => {

/**
* Resets the cached session info object and forces a new fetch on the next call.
*
* @example ```js
* resetCachedSessionInfo();
* const sessionInfo = await getSessionInfo();
Expand Down
Loading