Added forced version resolution | Ishan (#460)

* TP-1 | added forced redirect logic

* TP-1 | added web ui lib update

* TP-1 | added fixes for 3 secs

* TP-1|Kunal| gitmodules url update

* TP-1|Kunal| gitmodules url update

* TP-1|submodule update

---------

Co-authored-by: Ishan Srivastava <ishan.srivastava@navi.com>
Co-authored-by: kunalsharma <kunal.sharma@navi.com>
This commit is contained in:
GitHubArchive\Ishan Srivastava
2023-07-17 18:30:09 +05:30
committed by GitHub
parent 0f7798d3c4
commit efedd4c2b3
3 changed files with 120 additions and 13 deletions

View File

@@ -12,3 +12,5 @@ export const fullMonthNames = [
'November',
'December'
];
export const REDIRECT_TIMESTAMP_RECORD = 'redirectRecordTimestamp';

View File

@@ -13,10 +13,16 @@ import { GLOBAL } from '../constants/Global';
import APP_ROUTES, { LOGIN_PATH } from '../layout/Routes';
import { setAuthData, setShowStickyNote } from '../reducers/commonSlice';
import { checkBuildTime, handleBuildNudgeInNewPortal } from './checkBuildTime';
import { isJson, isRedirectionPermitted } from './commonUtils';
import {
isJson,
isRedirectionPermitted,
recordRedirectTime,
zeroImmediateThenDebounce
} from './commonUtils';
import { setLocalServerTimeDiff } from './DateHelper';
import { checkHooman } from './detectBots';
import { getDeviceId } from './FingerPrintJS';
import { REDIRECT_TIMESTAMP_RECORD } from '../constants/Common.constants';
export const logError = (error?: Error | unknown, message?: string) =>
Sentry.captureException({ error, message });
@@ -26,7 +32,10 @@ const MOCK_DIR = '../../__mocks__';
// set this to `true` to use mock data for local development
// to connect with real apis this should be set to `false`
const USE_MOCK = !import.meta.env.PROD && false;
const REDIRECT_URL_VERSIONED = '_V_';
const NEW_LH_ROUTE_CONSTANT = '/new';
const REDIRECT_SAFE_TIMEOUT = 3000;
const NEW_LH_VERSIONED_ROUTE_CONSTANT = '/versions';
export enum ApiKeys {
PEOPLE,
SEND_OTP,
@@ -284,6 +293,25 @@ const errorsToRetry = [500, 503];
const axiosInstance = axios.create();
const getURLForOldPortal = () => window?.location?.href?.split('/new')[0];
const getURLForNewPortal = () => {
const currentUrl = window.location.href;
let urlToAppend = '';
if (currentUrl.includes(NEW_LH_VERSIONED_ROUTE_CONSTANT)) {
urlToAppend = currentUrl.split('/versions')[1].split('/').splice(2).join('/');
}
return `${window?.location?.origin}/new/${urlToAppend}`;
};
const getUrlForForcedVersion = (versionString: string) => {
const currentUrl = window.location.href;
let urlToAppend = '';
if (currentUrl.includes(NEW_LH_VERSIONED_ROUTE_CONSTANT)) {
urlToAppend = currentUrl.split('/versions')[1].split('/').splice(2).join('/');
} else {
urlToAppend = window.location.href.split('new/')[1] || '';
}
const [major, minor, patch] = versionString.split('_').slice(-3);
return `${window?.location?.origin}/new/versions/${major}.${minor}.${patch}/${urlToAppend}`;
};
axiosInstance.interceptors.request.use(
request => {
@@ -320,12 +348,71 @@ const excludedRedirectionEndPointsList = [
];
const checkIsValidRedirection = () => {
const isValidForRedirection =
const isWhitelistedEndpoint =
excludedRedirectionEndPointsList.filter(endPoint => window.location?.href?.includes(endPoint))
.length === 0;
return isValidForRedirection;
return isWhitelistedEndpoint;
};
/**
* checks the given endpoint against the redirect version (something_V_X_Y_Z), and returns that is the "endpoint"
* is actually of the x.y.z version
*/
/**
* Note : returns true if the redirectVersion does not belong to new lh portal some version
*/
function isURLValidForGivenLHVersion(endpoint: string, redirectVersion: string): boolean {
// first see that does the redirectVersion string, really have the version info, if not return true
if (!redirectVersion.includes(REDIRECT_URL_VERSIONED)) {
return true;
}
const [major, minor, patch] = redirectVersion.split('_').slice(-3);
return endpoint.includes(`versions/${major}.${minor}.${patch}`);
}
function isSafeFromInfiniteRedirection() {
const currentRecord: number[] = JSON.parse(
localStorage.getItem(REDIRECT_TIMESTAMP_RECORD) || '[]'
);
return currentRecord.length < 2 || Date.now() - (currentRecord?.[1] || 0) > REDIRECT_SAFE_TIMEOUT;
}
/**
* Note : returns true if the redirectVersion does not belong to old lh portal
*/
function isURLValidForOldLhVersion(endpoint: string, redirectVersion: string): boolean {
return (
redirectVersion !== XREDIRECTTO.OLD_LONGHORN_PORTAL ||
!window?.location?.pathname.startsWith(NEW_LH_ROUTE_CONSTANT)
);
}
/**
* Note : returns true if the redirectVersion does not belong to new lh portal
*/
function isURLValidForLatestLHNew(endpoint: string, redirectVersion: string): boolean {
const path = window?.location?.pathname;
return (
redirectVersion !== XREDIRECTTO.NEW_LONGHORN_PORTAL ||
(path?.startsWith(NEW_LH_ROUTE_CONSTANT) && !path?.includes(NEW_LH_VERSIONED_ROUTE_CONSTANT))
);
}
const debouncedRouteChecker = zeroImmediateThenDebounce(redirectHeader => {
if (!isSafeFromInfiniteRedirection()) {
return;
}
if (!isURLValidForGivenLHVersion(window?.location?.href, redirectHeader)) {
recordRedirectTime();
window.location.replace(getUrlForForcedVersion(redirectHeader));
} else if (!isURLValidForOldLhVersion(window?.location?.href, redirectHeader)) {
recordRedirectTime();
window.location.replace(getURLForOldPortal());
} else if (!isURLValidForLatestLHNew(window?.location?.href, redirectHeader)) {
recordRedirectTime();
window.location.replace(getURLForNewPortal());
}
}, 800);
axiosInstance.interceptors.response.use(
response => {
if (!checkHooman()) return { ...response, data: null, error: commonErrorObject };
@@ -345,15 +432,8 @@ axiosInstance.interceptors.response.use(
const payload = { buildTime: Number(response.headers['build_time']) };
checkBuildTime(payload, handleBuildNudgeInNewPortal(dispatch, setShowStickyNote));
const redirectHeader = response.headers?.[REDIRECT_HEADER_NAME];
if (
redirectHeader &&
checkIsValidRedirection() &&
getURLForOldPortal() &&
import.meta.env.PROD
) {
if (redirectHeader === XREDIRECTTO.OLD_LONGHORN_PORTAL) {
window.location.replace(getURLForOldPortal());
}
if (redirectHeader && checkIsValidRedirection() && import.meta.env.PROD) {
debouncedRouteChecker(redirectHeader);
}
return response;
},

View File

@@ -8,6 +8,7 @@ import {
} from 'src/pages/Cases/constants/CasesConstants';
import { interpolatePathParams } from './interpolate';
import { logError } from './ApiHelper';
import { REDIRECT_TIMESTAMP_RECORD } from '../constants/Common.constants';
export const isObjectEmpty = (object: any) => {
for (const prop in object) {
@@ -224,3 +225,27 @@ export const formatNumber = (value: number) => {
maximumSignificantDigits: 10
}).format(value);
};
export const zeroImmediateThenDebounce = (callback: (...params: any[]) => any, ms = 300) => {
let timeoutId: ReturnType<typeof setTimeout>;
let executedTimes = 0;
return function (this: any, ...args: any[]) {
if (executedTimes === 0) {
callback.apply(this, args);
} else {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => callback.apply(this, args), ms);
}
++executedTimes;
};
};
export function recordRedirectTime() {
const currentRecord: number[] = JSON.parse(
localStorage.getItem(REDIRECT_TIMESTAMP_RECORD) || '[]'
);
if (currentRecord.length === 2) {
currentRecord.shift();
}
currentRecord.push(Date.now());
localStorage.setItem(REDIRECT_TIMESTAMP_RECORD, JSON.stringify(currentRecord));
}