0.5.8-panel-upgrade-community-crud-fix
All checks were successful
Deploy on push / deploy (push) Successful in 6s
All checks were successful
Deploy on push / deploy (push) Successful in 6s
This commit is contained in:
99
panel/utils/auth.ts
Normal file
99
panel/utils/auth.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* Утилиты для работы с токенами авторизации
|
||||
* @module auth-utils
|
||||
*/
|
||||
|
||||
// Экспортируем константы для использования в других модулях
|
||||
export const AUTH_TOKEN_KEY = 'auth_token'
|
||||
export const CSRF_TOKEN_KEY = 'csrf_token'
|
||||
|
||||
/**
|
||||
* Получает токен авторизации из cookie
|
||||
* @returns Токен или пустую строку, если токен не найден
|
||||
*/
|
||||
export function getAuthTokenFromCookie(): string {
|
||||
console.log('[Auth] Checking auth token in cookies...')
|
||||
const cookieItems = document.cookie.split(';')
|
||||
for (const item of cookieItems) {
|
||||
const [name, value] = item.trim().split('=')
|
||||
if (name === AUTH_TOKEN_KEY) {
|
||||
console.log('[Auth] Found auth token in cookies')
|
||||
return value
|
||||
}
|
||||
}
|
||||
console.log('[Auth] No auth token found in cookies')
|
||||
return ''
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает CSRF-токен из cookie
|
||||
* @returns CSRF-токен или пустую строку, если токен не найден
|
||||
*/
|
||||
export function getCsrfTokenFromCookie(): string {
|
||||
console.log('[Auth] Checking CSRF token in cookies...')
|
||||
const cookieItems = document.cookie.split(';')
|
||||
for (const item of cookieItems) {
|
||||
const [name, value] = item.trim().split('=')
|
||||
if (name === CSRF_TOKEN_KEY) {
|
||||
console.log('[Auth] Found CSRF token in cookies')
|
||||
return value
|
||||
}
|
||||
}
|
||||
console.log('[Auth] No CSRF token found in cookies')
|
||||
return ''
|
||||
}
|
||||
|
||||
/**
|
||||
* Очищает все токены авторизации
|
||||
*/
|
||||
export function clearAuthTokens(): void {
|
||||
console.log('[Auth] Clearing all auth tokens...')
|
||||
// Очищаем токен из localStorage
|
||||
localStorage.removeItem(AUTH_TOKEN_KEY)
|
||||
|
||||
// Для удаления cookie устанавливаем ей истекшее время жизни
|
||||
// biome-ignore lint/suspicious/noDocumentCookie: Требуется для кроссбраузерной совместимости
|
||||
document.cookie = `${AUTH_TOKEN_KEY}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`
|
||||
// biome-ignore lint/suspicious/noDocumentCookie: Требуется для кроссбраузерной совместимости
|
||||
document.cookie = `${CSRF_TOKEN_KEY}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`
|
||||
console.log('[Auth] Auth tokens cleared')
|
||||
}
|
||||
|
||||
/**
|
||||
* Сохраняет токен авторизации
|
||||
* @param token - Токен для сохранения
|
||||
*/
|
||||
export function saveAuthToken(token: string): void {
|
||||
console.log('[Auth] Attempting to save auth token...')
|
||||
if (!token) {
|
||||
console.log('[Auth] No token provided, skipping save')
|
||||
return
|
||||
}
|
||||
|
||||
// Всегда сохраняем токен в localStorage для надежности
|
||||
localStorage.setItem(AUTH_TOKEN_KEY, token)
|
||||
console.log('[Auth] Token saved to localStorage')
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет, авторизован ли пользователь
|
||||
* @returns Статус авторизации
|
||||
*/
|
||||
export function checkAuthStatus(): boolean {
|
||||
console.log('[Auth] Checking authentication status...')
|
||||
|
||||
// Проверяем наличие cookie auth_token
|
||||
const cookieToken = getAuthTokenFromCookie()
|
||||
const hasCookie = !!cookieToken && cookieToken.length > 10
|
||||
|
||||
// Проверяем наличие токена в localStorage
|
||||
const localToken = localStorage.getItem(AUTH_TOKEN_KEY)
|
||||
const hasLocalToken = !!localToken && localToken.length > 10
|
||||
|
||||
const isAuth = hasCookie || hasLocalToken
|
||||
console.log(`[Auth] Cookie token: ${hasCookie ? 'present' : 'missing'}`)
|
||||
console.log(`[Auth] Local token: ${hasLocalToken ? 'present' : 'missing'}`)
|
||||
console.log(`[Auth] Authentication status: ${isAuth ? 'authenticated' : 'not authenticated'}`)
|
||||
|
||||
return isAuth
|
||||
}
|
104
panel/utils/date.ts
Normal file
104
panel/utils/date.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* Форматирование даты в формате "X дней назад"
|
||||
* @param timestamp - Временная метка
|
||||
* @returns Форматированная строка с относительной датой
|
||||
*/
|
||||
export function formatDateRelative(timestamp?: number): string {
|
||||
if (!timestamp) return 'Н/Д'
|
||||
|
||||
const now = Math.floor(Date.now() / 1000)
|
||||
const diff = now - timestamp
|
||||
|
||||
// Меньше минуты
|
||||
if (diff < 60) {
|
||||
return 'только что'
|
||||
}
|
||||
|
||||
// Меньше часа
|
||||
if (diff < 3600) {
|
||||
const minutes = Math.floor(diff / 60)
|
||||
return `${minutes} ${getMinutesForm(minutes)} назад`
|
||||
}
|
||||
|
||||
// Меньше суток
|
||||
if (diff < 86400) {
|
||||
const hours = Math.floor(diff / 3600)
|
||||
return `${hours} ${getHoursForm(hours)} назад`
|
||||
}
|
||||
|
||||
// Меньше 30 дней
|
||||
if (diff < 2592000) {
|
||||
const days = Math.floor(diff / 86400)
|
||||
return `${days} ${getDaysForm(days)} назад`
|
||||
}
|
||||
|
||||
// Меньше года
|
||||
if (diff < 31536000) {
|
||||
const months = Math.floor(diff / 2592000)
|
||||
return `${months} ${getMonthsForm(months)} назад`
|
||||
}
|
||||
|
||||
// Больше года
|
||||
const years = Math.floor(diff / 31536000)
|
||||
return `${years} ${getYearsForm(years)} назад`
|
||||
}
|
||||
|
||||
/**
|
||||
* Получение правильной формы слова "минута" в зависимости от числа
|
||||
*/
|
||||
function getMinutesForm(minutes: number): string {
|
||||
if (minutes % 10 === 1 && minutes % 100 !== 11) {
|
||||
return 'минуту'
|
||||
} else if ([2, 3, 4].includes(minutes % 10) && ![12, 13, 14].includes(minutes % 100)) {
|
||||
return 'минуты'
|
||||
}
|
||||
return 'минут'
|
||||
}
|
||||
|
||||
/**
|
||||
* Получение правильной формы слова "час" в зависимости от числа
|
||||
*/
|
||||
function getHoursForm(hours: number): string {
|
||||
if (hours % 10 === 1 && hours % 100 !== 11) {
|
||||
return 'час'
|
||||
} else if ([2, 3, 4].includes(hours % 10) && ![12, 13, 14].includes(hours % 100)) {
|
||||
return 'часа'
|
||||
}
|
||||
return 'часов'
|
||||
}
|
||||
|
||||
/**
|
||||
* Получение правильной формы слова "день" в зависимости от числа
|
||||
*/
|
||||
function getDaysForm(days: number): string {
|
||||
if (days % 10 === 1 && days % 100 !== 11) {
|
||||
return 'день'
|
||||
} else if ([2, 3, 4].includes(days % 10) && ![12, 13, 14].includes(days % 100)) {
|
||||
return 'дня'
|
||||
}
|
||||
return 'дней'
|
||||
}
|
||||
|
||||
/**
|
||||
* Получение правильной формы слова "месяц" в зависимости от числа
|
||||
*/
|
||||
function getMonthsForm(months: number): string {
|
||||
if (months % 10 === 1 && months % 100 !== 11) {
|
||||
return 'месяц'
|
||||
} else if ([2, 3, 4].includes(months % 10) && ![12, 13, 14].includes(months % 100)) {
|
||||
return 'месяца'
|
||||
}
|
||||
return 'месяцев'
|
||||
}
|
||||
|
||||
/**
|
||||
* Получение правильной формы слова "год" в зависимости от числа
|
||||
*/
|
||||
function getYearsForm(years: number): string {
|
||||
if (years % 10 === 1 && years % 100 !== 11) {
|
||||
return 'год'
|
||||
} else if ([2, 3, 4].includes(years % 10) && ![12, 13, 14].includes(years % 100)) {
|
||||
return 'года'
|
||||
}
|
||||
return 'лет'
|
||||
}
|
Reference in New Issue
Block a user