// @ts-ignore // eslint-disable-next-line import { openTokenAuthUrl } from '../authentication/actions'; // @ts-ignore import { getTokenAuthUrl, isTokenAuthEnabled } from '../authentication/functions'; import { getJwtExpirationDate } from '../base/jwt/functions'; import { MEDIA_TYPE } from '../base/media/constants'; import { isLocalTrackMuted } from '../base/tracks/functions.any'; import { getLocationContextRoot, parseURIString } from '../base/util/uri'; import { addTrackStateToURL } from './functions.any'; import logger from './logger'; import { IStore } from './types'; /** * Redirects to another page generated by replacing the path in the original URL * with the given path. * * @param {(string)} pathname - The path to navigate to. * @returns {Function} */ export function redirectWithStoredParams(pathname: string) { return (dispatch: IStore['dispatch'], getState: IStore['getState']) => { const { locationURL } = getState()['features/base/connection']; const newLocationURL = new URL(locationURL?.href ?? ''); (newLocationURL as Mutable).pathname = pathname; window.location.assign(newLocationURL.toString()); }; } /** * Assigns a specific pathname to window.location.pathname taking into account * the context root of the Web app. * * @param {string} pathname - The pathname to assign to * window.location.pathname. If the specified pathname is relative, the context * root of the Web app will be prepended to the specified pathname before * assigning it to window.location.pathname. * @param {string} hashParam - Optional hash param to assign to * window.location.hash. * @returns {Function} */ export function redirectToStaticPage(pathname: string, hashParam?: string) { return () => { const windowLocation = window.location; let newPathname = pathname; if (!newPathname.startsWith('/')) { // A pathname equal to ./ specifies the current directory. It will be // fine but pointless to include it because contextRoot is the current // directory. newPathname.startsWith('./') && (newPathname = newPathname.substring(2)); newPathname = getLocationContextRoot(windowLocation) + newPathname; } if (hashParam) { (windowLocation as Mutable).hash = hashParam; } (windowLocation as Mutable).pathname = newPathname; }; } /** * Reloads the page by restoring the original URL. * * @returns {Function} */ export function reloadWithStoredParams() { return (dispatch: IStore['dispatch'], getState: IStore['getState']) => { const state = getState(); const { locationURL } = state['features/base/connection']; // Preserve the local tracks muted states. // @ts-ignore const newURL = addTrackStateToURL(locationURL, state); const windowLocation = window.location; const oldSearchString = windowLocation.search; windowLocation.replace(newURL.toString()); if (newURL.search === oldSearchString) { // NOTE: Assuming that only the hash or search part of the URL will // be changed! // location.replace will not trigger redirect/reload when // only the hash params are changed. That's why we need to call // reload in addition to replace. windowLocation.reload(); } }; } /** * Checks whether tokenAuthUrl is set, we have a jwt token that will expire soon * and redirect to the auth url to obtain new token if this is the case. * * @param {Dispatch} dispatch - The Redux dispatch function. * @param {Function} getState - The Redux state. * @param {Function} failureCallback - The callback on failure to obtain auth url. * @returns {boolean} Whether we will redirect or not. */ export function maybeRedirectToTokenAuthUrl( dispatch: IStore['dispatch'], getState: IStore['getState'], failureCallback: Function) { const state = getState(); const config = state['features/base/config']; const { enabled: lowBandwidthModeEnabled } = state['features/base/low-bandwidth-mode']; const { startLowBandwidthMode } = config; const { locationURL = { href: '' } as URL } = state['features/base/connection']; const audioMuted = isLocalTrackMuted(state['features/base/tracks'], MEDIA_TYPE.AUDIO); const videoMuted = isLocalTrackMuted(state['features/base/tracks'], MEDIA_TYPE.VIDEO); if (!isTokenAuthEnabled(state)) { return false; } // if tokenAuthUrl check jwt if is about to expire go through the url to get new token const jwt = state['features/base/jwt'].jwt; const refreshToken = state['features/base/jwt'].refreshToken; const expirationDate = getJwtExpirationDate(jwt); // if there is jwt token, and it is expired let's obtain a new one if (expirationDate && expirationDate.getTime() <= Date.now()) { const room = state['features/base/conference'].room; const { tenant } = parseURIString(locationURL.href) || {}; getTokenAuthUrl( config, locationURL, { audioMuted, lowBandwidthModeEnabled: lowBandwidthModeEnabled || startLowBandwidthMode, skipPrejoin: true, videoMuted }, room, tenant, refreshToken ) .then((tokenAuthServiceUrl: string | undefined) => { if (!tokenAuthServiceUrl) { logger.warn('Cannot handle login, token service URL is not set'); return Promise.reject(); } return dispatch(openTokenAuthUrl(tokenAuthServiceUrl)); }) .catch(e => { failureCallback(e); }); return true; } return false; }