mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-22 15:39:11 +00:00
fix: maintain locked and token params
This commit is contained in:
committed by
Carlos Valente
parent
d08787a6ba
commit
c3d66f5bd1
@@ -1,6 +1,6 @@
|
|||||||
import { resolvePath } from 'react-router-dom';
|
import { resolvePath } from 'react-router-dom';
|
||||||
|
|
||||||
import { generatePathFromPreset, getRouteFromPreset, validateUrlPresetPath } from '../urlPresets';
|
import { arePathsEquivalent, generatePathFromPreset, getRouteFromPreset, validateUrlPresetPath } from '../urlPresets';
|
||||||
|
|
||||||
describe('validateUrlPresetPaths()', () => {
|
describe('validateUrlPresetPaths()', () => {
|
||||||
test.each([
|
test.each([
|
||||||
@@ -60,6 +60,18 @@ describe('getRouteFromPreset()', () => {
|
|||||||
const location = resolvePath('/unknown');
|
const location = resolvePath('/unknown');
|
||||||
expect(getRouteFromPreset(location, presets)).toEqual(null);
|
expect(getRouteFromPreset(location, presets)).toEqual(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('handle url sharing edge cases', () => {
|
||||||
|
it('finds the correct preset when the url contains extra arguments', () => {
|
||||||
|
const location = resolvePath('/demopage?locked=true&token=123');
|
||||||
|
expect(getRouteFromPreset(location, presets)?.startsWith('timer?user=guest&alias=demopage')).toBeTruthy()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('appends the feature params to the alias', () => {
|
||||||
|
const location = resolvePath('/demopage?locked=true&token=123');
|
||||||
|
expect(getRouteFromPreset(location, presets)).toBe('timer?user=guest&alias=demopage&locked=true&token=123')
|
||||||
|
})
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('generatePathFromPreset()', () => {
|
describe('generatePathFromPreset()', () => {
|
||||||
@@ -67,6 +79,29 @@ describe('generatePathFromPreset()', () => {
|
|||||||
['timer?user=guest', 'demopage', 'timer?user=guest&alias=demopage'],
|
['timer?user=guest', 'demopage', 'timer?user=guest&alias=demopage'],
|
||||||
['timer?user=admin', 'demopage', 'timer?user=admin&alias=demopage'],
|
['timer?user=admin', 'demopage', 'timer?user=admin&alias=demopage'],
|
||||||
])('generates a path from a preset: %s', (path, alias, expected) => {
|
])('generates a path from a preset: %s', (path, alias, expected) => {
|
||||||
expect(generatePathFromPreset(path, alias)).toEqual(expected);
|
expect(generatePathFromPreset(path, alias, null, null)).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('appends the feature params to the alias', () => {
|
||||||
|
expect(generatePathFromPreset('timer?user=guest', 'demopage', 'true', '123')).toBe('timer?user=guest&alias=demopage&locked=true&token=123');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('arePathsEquivalent()', () => {
|
||||||
|
it("checks whether the paths match", () => {
|
||||||
|
expect(arePathsEquivalent('demopage', 'timer')).toBeFalsy();
|
||||||
|
expect(arePathsEquivalent('timer', 'timer')).toBeTruthy();
|
||||||
|
expect(arePathsEquivalent('timer?user=guest', 'timer?user=guest')).toBeTruthy();
|
||||||
|
})
|
||||||
|
|
||||||
|
it("checks whether the params match", () => {
|
||||||
|
expect(arePathsEquivalent('timer?test=a', 'timer?test=b')).toBeFalsy();
|
||||||
|
expect(arePathsEquivalent('timer?test=a', 'timer?test=a')).toBeTruthy();
|
||||||
|
})
|
||||||
|
|
||||||
|
it("considers edge cases for the url sharing feature", () => {
|
||||||
|
expect(arePathsEquivalent('timer?test=a&locked=true=token=123', 'timer?test=b')).toBeFalsy();
|
||||||
|
expect(arePathsEquivalent('timer?test=a&locked=true=token=123', 'timer?test=a')).toBeTruthy();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -36,31 +36,35 @@ function removeTrailingSlash(text: string): string {
|
|||||||
/**
|
/**
|
||||||
* Checks whether the current location corresponds to a preset and returns the new path if necessary
|
* Checks whether the current location corresponds to a preset and returns the new path if necessary
|
||||||
*/
|
*/
|
||||||
export function getRouteFromPreset(location: Path, urlPresets: URLPreset[]) {
|
export function getRouteFromPreset(location: Path, urlPresets: URLPreset[]): string | null {
|
||||||
// current url is the pathname without the leading slash
|
// current url is the pathname without the leading slash
|
||||||
const currentURL = location.pathname.substring(1);
|
const currentURL = location.pathname.substring(1);
|
||||||
|
const searchParams = new URLSearchParams(location.search);
|
||||||
|
|
||||||
|
// check if we have token or locked in the search params
|
||||||
|
const locked = searchParams.get('locked');
|
||||||
|
const token = searchParams.get('token');
|
||||||
|
|
||||||
// we need to check if the whole url is an alias
|
// we need to check if the whole url is an alias
|
||||||
const foundPreset = urlPresets.find((preset) => preset.alias === removeTrailingSlash(currentURL) && preset.enabled);
|
const foundPreset = urlPresets.find((preset) => preset.alias === removeTrailingSlash(currentURL) && preset.enabled);
|
||||||
if (foundPreset) {
|
if (foundPreset) {
|
||||||
// if so, we can redirect to the preset path
|
// if so, we can redirect to the preset path
|
||||||
return generatePathFromPreset(foundPreset.pathAndParams, foundPreset.alias);
|
return generatePathFromPreset(foundPreset.pathAndParams, foundPreset.alias, locked, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the current url is not an alias, we check if the alias is in the search parameters
|
// if the current url is not an alias, we check if the alias is in the search parameters
|
||||||
const searchParams = new URLSearchParams(location.search);
|
|
||||||
|
|
||||||
const presetOnPage = searchParams.get('alias');
|
const presetOnPage = searchParams.get('alias');
|
||||||
if (!presetOnPage) {
|
if (!presetOnPage) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const currentPath = `${location.pathname}${location.search}`.substring(1);
|
||||||
|
|
||||||
for (const preset of urlPresets) {
|
for (const preset of urlPresets) {
|
||||||
// if the page has a known enabled alias, we check if we need to redirect
|
// if the page has a known enabled alias, we check if we need to redirect
|
||||||
if (preset.alias === presetOnPage && preset.enabled) {
|
if (preset.alias === presetOnPage && preset.enabled) {
|
||||||
const newPath = generatePathFromPreset(preset.pathAndParams, preset.alias);
|
const newPath = generatePathFromPreset(preset.pathAndParams, preset.alias, locked, token);
|
||||||
const currentPath = `${location.pathname}${location.search}`.substring(1);
|
if (!arePathsEquivalent(currentPath, newPath)) {
|
||||||
if (currentPath !== newPath) {
|
|
||||||
// if current path is out of date
|
// if current path is out of date
|
||||||
// return new path so we can redirect
|
// return new path so we can redirect
|
||||||
return newPath;
|
return newPath;
|
||||||
@@ -73,13 +77,50 @@ export function getRouteFromPreset(location: Path, urlPresets: URLPreset[]) {
|
|||||||
/**
|
/**
|
||||||
* Handles generating a path and search parameters from a preset
|
* Handles generating a path and search parameters from a preset
|
||||||
*/
|
*/
|
||||||
export function generatePathFromPreset(pathAndParams: string, alias: string): string {
|
export function generatePathFromPreset(pathAndParams: string, alias: string, locked: string | null, token: string | null ): string {
|
||||||
const path = resolvePath(pathAndParams);
|
const path = resolvePath(pathAndParams);
|
||||||
const searchParams = new URLSearchParams(path.search);
|
const searchParams = new URLSearchParams(path.search);
|
||||||
|
|
||||||
// save the alias so we have a reference to it being a preset and can update if necessary
|
// save the alias so we have a reference to it being a preset and can update if necessary
|
||||||
searchParams.set('alias', alias);
|
searchParams.set('alias', alias);
|
||||||
|
|
||||||
|
// maintain params from the URL search feature
|
||||||
|
if (locked) {
|
||||||
|
searchParams.set('locked', locked);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token) {
|
||||||
|
searchParams.set('token', token);
|
||||||
|
}
|
||||||
|
|
||||||
// return path concatenated without the leading slash
|
// return path concatenated without the leading slash
|
||||||
return `${path.pathname}?${searchParams}`.substring(1);
|
return `${path.pathname}?${searchParams}`.substring(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility checks if two paths are equivalent
|
||||||
|
* Considers the edge cases for url sharing where a path may contain extra arguments from the alias
|
||||||
|
* - token
|
||||||
|
* - locked
|
||||||
|
*/
|
||||||
|
export function arePathsEquivalent(currentPath: string, newPath: string): boolean {
|
||||||
|
const currentUrl = new URL(currentPath, document.location.origin);
|
||||||
|
const newUrl = new URL(newPath, document.location.origin);
|
||||||
|
|
||||||
|
// check path
|
||||||
|
if (currentUrl.pathname !== newUrl.pathname) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// check search params
|
||||||
|
// if the params match, we dont need further checks
|
||||||
|
if (currentUrl.searchParams.toString() === newUrl.searchParams.toString()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there is no match, we check the edge cases for the url sharing feature
|
||||||
|
currentUrl.searchParams.delete('token');
|
||||||
|
currentUrl.searchParams.delete('locked');
|
||||||
|
|
||||||
|
return currentUrl.searchParams.toString() === newUrl.searchParams.toString();
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user