From 4d7437f0696ded41b1986ccadfd60d3e6c04031c Mon Sep 17 00:00:00 2001 From: Egor Date: Sun, 18 Jan 2026 05:26:47 +0300 Subject: [PATCH] Add files via upload --- src/utils/logger.ts | 57 +++++++++++++++++++++++++++++++++++++++++++++ src/utils/token.ts | 37 +++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 src/utils/logger.ts diff --git a/src/utils/logger.ts b/src/utils/logger.ts new file mode 100644 index 0000000..95eee2b --- /dev/null +++ b/src/utils/logger.ts @@ -0,0 +1,57 @@ +/** + * Утилита для логирования только в development режиме + * В production логи не выводятся + */ + +const isDev = import.meta.env.DEV + +export const logger = { + log: (...args: unknown[]): void => { + if (isDev) { + console.log(...args) + } + }, + + warn: (...args: unknown[]): void => { + if (isDev) { + console.warn(...args) + } + }, + + error: (...args: unknown[]): void => { + // Ошибки логируем всегда (важно для отладки в production) + console.error(...args) + }, + + debug: (...args: unknown[]): void => { + if (isDev) { + console.debug(...args) + } + }, + + /** + * Создаёт логгер с префиксом для конкретного модуля + */ + createLogger: (prefix: string) => ({ + log: (...args: unknown[]): void => { + if (isDev) { + console.log(`[${prefix}]`, ...args) + } + }, + warn: (...args: unknown[]): void => { + if (isDev) { + console.warn(`[${prefix}]`, ...args) + } + }, + error: (...args: unknown[]): void => { + console.error(`[${prefix}]`, ...args) + }, + debug: (...args: unknown[]): void => { + if (isDev) { + console.debug(`[${prefix}]`, ...args) + } + }, + }), +} + +export default logger diff --git a/src/utils/token.ts b/src/utils/token.ts index 7018db9..736400f 100644 --- a/src/utils/token.ts +++ b/src/utils/token.ts @@ -253,3 +253,40 @@ class TokenRefreshManager { } export const tokenRefreshManager = new TokenRefreshManager() + +/** + * Безопасный редирект на страницу логина + * Валидирует URL чтобы предотвратить open redirect уязвимость + */ +export function safeRedirectToLogin(): void { + // Разрешённые пути для редиректа (относительные пути нашего приложения) + const loginPath = '/login' + + // Проверяем, что мы на том же origin + if (typeof window !== 'undefined') { + // Используем только относительный путь для безопасности + window.location.href = loginPath + } +} + +/** + * Валидирует URL для редиректа + * Возвращает true только для безопасных URL (относительные пути или тот же origin) + */ +export function isValidRedirectUrl(url: string): boolean { + // Пустой URL - небезопасен + if (!url) return false + + // Относительные пути всегда безопасны + if (url.startsWith('/') && !url.startsWith('//')) { + return true + } + + try { + const parsed = new URL(url, window.location.origin) + // Разрешаем только тот же origin + return parsed.origin === window.location.origin + } catch { + return false + } +}