mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-18 21:54:09 +00:00
refactor: obfuscated pincode in transit
This commit is contained in:
committed by
Carlos Valente
parent
3fdb1bd1c8
commit
4e6b833e10
@@ -26,7 +26,6 @@ export const AppContextProvider = ({ children }: PropsWithChildren) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (status === 'pending') return;
|
if (status === 'pending') return;
|
||||||
if (!data) return;
|
|
||||||
const previousEditor = sessionStorage.getItem(storageKeys.editor);
|
const previousEditor = sessionStorage.getItem(storageKeys.editor);
|
||||||
|
|
||||||
if (previousEditor && previousEditor === data.editorKey) {
|
if (previousEditor && previousEditor === data.editorKey) {
|
||||||
@@ -53,10 +52,6 @@ export const AppContextProvider = ({ children }: PropsWithChildren) => {
|
|||||||
return savedPin == null || savedPin === '' || pin === savedPin;
|
return savedPin == null || savedPin === '' || pin === savedPin;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (permission === 'editor') {
|
if (permission === 'editor') {
|
||||||
const correct = isValid(pin, data.editorKey);
|
const correct = isValid(pin, data.editorKey);
|
||||||
if (correct) {
|
if (correct) {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
import { unobfuscate } from 'ontime-utils';
|
||||||
|
|
||||||
import { queryRefetchIntervalSlow } from '../../ontimeConfig';
|
import { queryRefetchIntervalSlow } from '../../ontimeConfig';
|
||||||
import { APP_SETTINGS } from '../api/constants';
|
import { APP_SETTINGS } from '../api/constants';
|
||||||
@@ -14,7 +15,17 @@ export default function useSettings() {
|
|||||||
retryDelay: (attempt) => attempt * 2500,
|
retryDelay: (attempt) => attempt * 2500,
|
||||||
refetchInterval: queryRefetchIntervalSlow,
|
refetchInterval: queryRefetchIntervalSlow,
|
||||||
networkMode: 'always',
|
networkMode: 'always',
|
||||||
|
select: (data) => {
|
||||||
|
const unobfuscated = { ...data };
|
||||||
|
if (data.editorKey) {
|
||||||
|
unobfuscated.editorKey = unobfuscate(data.editorKey);
|
||||||
|
}
|
||||||
|
if (data.operatorKey) {
|
||||||
|
unobfuscated.operatorKey = unobfuscate(data.operatorKey);
|
||||||
|
}
|
||||||
|
return unobfuscated;
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return { data, status, isFetching, isError, refetch };
|
return { data: data ?? ontimePlaceholderSettings, status, isFetching, isError, refetch };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,10 +6,20 @@ import { DataProvider } from '../../classes/data-provider/DataProvider.js';
|
|||||||
import { failEmptyObjects } from '../../utils/routerUtils.js';
|
import { failEmptyObjects } from '../../utils/routerUtils.js';
|
||||||
import { extractPin } from '../../services/project-service/ProjectService.js';
|
import { extractPin } from '../../services/project-service/ProjectService.js';
|
||||||
import { isDocker } from '../../setup/index.js';
|
import { isDocker } from '../../setup/index.js';
|
||||||
|
import { obfuscate } from 'ontime-utils';
|
||||||
|
|
||||||
export async function getSettings(_req: Request, res: Response<Settings>) {
|
export async function getSettings(_req: Request, res: Response<Settings>) {
|
||||||
const settings = DataProvider.getSettings();
|
const settings = DataProvider.getSettings();
|
||||||
res.status(200).send(settings);
|
const obfuscatedSettings = { ...settings };
|
||||||
|
if (settings.editorKey) {
|
||||||
|
obfuscatedSettings.editorKey = obfuscate(settings.editorKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.operatorKey) {
|
||||||
|
obfuscatedSettings.editorKey = obfuscate(settings.editorKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).send(obfuscatedSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function postSettings(req: Request, res: Response<Settings | ErrorResponse>) {
|
export async function postSettings(req: Request, res: Response<Settings | ErrorResponse>) {
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export class DataProvider {
|
|||||||
await this.persist();
|
await this.persist();
|
||||||
}
|
}
|
||||||
|
|
||||||
static getSettings(): Settings {
|
static getSettings(): Readonly<Settings> {
|
||||||
return data.settings;
|
return data.settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ export { deleteAtIndex, insertAtIndex, reorderArray, sortArrayByProperty } from
|
|||||||
|
|
||||||
// generic utilities
|
// generic utilities
|
||||||
export { unpackError } from './src/generic/generic.js';
|
export { unpackError } from './src/generic/generic.js';
|
||||||
|
export { obfuscate, unobfuscate } from './src/generic/generic.js';
|
||||||
export { isNumeric } from './src/types/types.js';
|
export { isNumeric } from './src/types/types.js';
|
||||||
|
|
||||||
// model validation
|
// model validation
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { obfuscate, unobfuscate } from '../generic.js';
|
||||||
|
|
||||||
|
describe('obfuscate and unobfuscate', () => {
|
||||||
|
it('should return the obfuscated string', () => {
|
||||||
|
const str = 'abc123';
|
||||||
|
const obfuscated = obfuscate(str);
|
||||||
|
expect(obfuscated).not.toBe(str);
|
||||||
|
expect(obfuscated.startsWith('_')).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the original string after obfuscating and unobfuscating', () => {
|
||||||
|
const str = 'abc123';
|
||||||
|
const obfuscated = obfuscate(str);
|
||||||
|
const unobfuscated = unobfuscate(obfuscated);
|
||||||
|
expect(unobfuscated).toBe(str);
|
||||||
|
expect(unobfuscated.startsWith('_')).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -4,3 +4,39 @@ export function unpackError(error: unknown): string {
|
|||||||
}
|
}
|
||||||
return String(error);
|
return String(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obfuscate a string
|
||||||
|
* Uses a variation of ROT13 that handles numeric values
|
||||||
|
* @param str
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function obfuscate(str: string): string {
|
||||||
|
const obfuscated = str.replace(/[a-zA-Z0-9]/g, (c) => {
|
||||||
|
if (/[a-zA-Z]/.test(c)) {
|
||||||
|
// @ts-expect-error -- we use some javascript magic here
|
||||||
|
return String.fromCharCode((c <= 'Z' ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26);
|
||||||
|
} else {
|
||||||
|
// @ts-expect-error -- we use some javascript magic here
|
||||||
|
|
||||||
|
return String.fromCharCode((c <= '4' ? 57 : 48) >= (c = c.charCodeAt(0) + 5) ? c : c - 10);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (str.startsWith('_')) {
|
||||||
|
return obfuscated.replace('_', '');
|
||||||
|
}
|
||||||
|
return `_${obfuscated}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unobfoscate a string
|
||||||
|
* Uses a variation of ROT13 that handles numeric values
|
||||||
|
* @param str
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function unobfuscate(str: string): string {
|
||||||
|
if (str.startsWith('_')) {
|
||||||
|
return obfuscate(str);
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user