core/panel/auth.ts

178 lines
5.8 KiB
TypeScript
Raw Normal View History

2025-05-16 06:23:48 +00:00
/**
* Модуль авторизации
* @module auth
*/
2025-05-19 08:25:41 +00:00
// Экспортируем константы для использования в других модулях
2025-05-16 07:30:02 +00:00
export const AUTH_TOKEN_KEY = 'auth_token'
2025-05-19 08:25:41 +00:00
export const CSRF_TOKEN_KEY = 'csrf_token'
2025-05-16 07:30:02 +00:00
2025-05-16 06:23:48 +00:00
/**
* Интерфейс для учетных данных
*/
export interface Credentials {
email: string
password: string
}
/**
* Интерфейс для результата авторизации
*/
export interface LoginResult {
success: boolean
token?: string
error?: string
}
/**
* Интерфейс для ответа API при логине
*/
interface LoginResponse {
login: LoginResult
}
2025-05-19 08:25:41 +00:00
/**
* Получает токен авторизации из cookie
* @returns Токен или пустую строку, если токен не найден
*/
export function getAuthTokenFromCookie(): string {
const cookieItems = document.cookie.split(';')
for (const item of cookieItems) {
const [name, value] = item.trim().split('=')
if (name === AUTH_TOKEN_KEY) {
return value
}
}
return ''
}
/**
* Получает CSRF-токен из cookie
* @returns CSRF-токен или пустую строку, если токен не найден
*/
export function getCsrfTokenFromCookie(): string {
const cookieItems = document.cookie.split(';')
for (const item of cookieItems) {
const [name, value] = item.trim().split('=')
if (name === CSRF_TOKEN_KEY) {
return value
}
}
return ''
}
2025-05-16 06:23:48 +00:00
/**
* Проверяет, авторизован ли пользователь
* @returns Статус авторизации
*/
export function isAuthenticated(): boolean {
// Проверяем наличие 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
// Пользователь авторизован, если есть cookie или токен в localStorage
return hasCookie || hasLocalToken
}
/**
* Выполняет выход из системы
* @param callback - Функция обратного вызова после выхода
*/
export function logout(callback?: () => void): void {
// Очищаем токен из localStorage
localStorage.removeItem(AUTH_TOKEN_KEY)
// Для удаления cookie устанавливаем ей истекшее время жизни
2025-05-19 08:25:41 +00:00
document.cookie = `${AUTH_TOKEN_KEY}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`
2025-05-16 06:23:48 +00:00
// Дополнительно пытаемся сделать запрос на сервер для удаления серверных сессий
try {
2025-05-19 08:25:41 +00:00
fetch('/auth/logout', {
method: 'POST', // Используем POST вместо GET для операций изменения состояния
credentials: 'include',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': getCsrfTokenFromCookie() // Добавляем CSRF токен если он есть
}
2025-05-16 07:30:02 +00:00
}).catch((e) => {
2025-05-16 06:23:48 +00:00
console.error('Ошибка при запросе на выход:', e)
})
} catch (e) {
console.error('Ошибка при выходе:', e)
}
// Вызываем функцию обратного вызова после очистки токенов
if (callback) callback()
}
/**
2025-05-19 08:25:41 +00:00
* Выполняет вход в систему используя GraphQL-запрос
2025-05-16 06:23:48 +00:00
* @param credentials - Учетные данные
* @returns Результат авторизации
*/
export async function login(credentials: Credentials): Promise<boolean> {
try {
2025-05-19 08:25:41 +00:00
console.log('Отправка запроса авторизации через GraphQL')
const response = await fetch(`${location.origin}/graphql`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'X-CSRF-Token': getCsrfTokenFromCookie() // Добавляем CSRF токен если он есть
},
credentials: 'include', // Важно для обработки cookies
body: JSON.stringify({
query: `
mutation Login($email: String!, $password: String!) {
login(email: $email, password: $password) {
success
token
error
}
}
`,
variables: {
email: credentials.email,
password: credentials.password
2025-05-16 06:23:48 +00:00
}
2025-05-19 08:25:41 +00:00
})
})
2025-05-16 06:23:48 +00:00
2025-05-19 08:25:41 +00:00
if (!response.ok) {
const errorText = await response.text()
console.error('Ошибка HTTP:', response.status, errorText)
throw new Error(`HTTP error: ${response.status} ${response.statusText}`)
}
const result = await response.json()
console.log('Результат авторизации:', result)
if (result?.data?.login?.success) {
2025-05-16 06:23:48 +00:00
// Проверяем, установил ли сервер cookie
const cookieToken = getAuthTokenFromCookie()
const hasCookie = !!cookieToken && cookieToken.length > 10
// Если cookie не установлена, но есть токен в ответе, сохраняем его в localStorage
2025-05-19 08:25:41 +00:00
if (!hasCookie && result.data.login.token) {
localStorage.setItem(AUTH_TOKEN_KEY, result.data.login.token)
2025-05-16 06:23:48 +00:00
}
return true
}
2025-05-19 08:25:41 +00:00
if (result.errors && result.errors.length > 0) {
throw new Error(result.errors[0].message || 'Ошибка авторизации')
}
throw new Error(result?.data?.login?.error || 'Неизвестная ошибка авторизации')
2025-05-16 06:23:48 +00:00
} catch (error) {
console.error('Ошибка при входе:', error)
throw error
}
}