This commit is contained in:
2025-05-19 11:25:41 +03:00
parent 11e46f7352
commit dc5ad46df9
20 changed files with 952 additions and 509 deletions

View File

@@ -3,29 +3,9 @@
* @module auth
*/
import { query } from './graphql'
// Константа для имени ключа токена в localStorage
const AUTH_COOKIE_NAME = 'auth_token'
// Константа для имени ключа токена в cookie
// Экспортируем константы для использования в других модулях
export const AUTH_TOKEN_KEY = 'auth_token'
/**
* Получает токен авторизации из cookie
* @returns Токен или пустую строку, если токен не найден
*/
export const getAuthTokenFromCookie = (): string => {
const cookieItems = document.cookie.split(';')
for (const item of cookieItems) {
const [name, value] = item.trim().split('=')
if (name === 'auth_token') {
return value
}
}
return ''
}
export const CSRF_TOKEN_KEY = 'csrf_token'
/**
* Интерфейс для учетных данных
@@ -51,6 +31,36 @@ interface LoginResponse {
login: LoginResult
}
/**
* Получает токен авторизации из 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 ''
}
/**
* Проверяет, авторизован ли пользователь
* @returns Статус авторизации
@@ -77,13 +87,17 @@ export function logout(callback?: () => void): void {
localStorage.removeItem(AUTH_TOKEN_KEY)
// Для удаления cookie устанавливаем ей истекшее время жизни
document.cookie = `${AUTH_COOKIE_NAME}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`
document.cookie = `${AUTH_TOKEN_KEY}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`
// Дополнительно пытаемся сделать запрос на сервер для удаления серверных сессий
try {
fetch('/logout', {
method: 'GET',
credentials: 'include'
fetch('/auth/logout', {
method: 'POST', // Используем POST вместо GET для операций изменения состояния
credentials: 'include',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': getCsrfTokenFromCookie() // Добавляем CSRF токен если он есть
}
}).catch((e) => {
console.error('Ошибка при запросе на выход:', e)
})
@@ -96,47 +110,68 @@ export function logout(callback?: () => void): void {
}
/**
* Выполняет вход в систему
* Выполняет вход в систему используя GraphQL-запрос
* @param credentials - Учетные данные
* @returns Результат авторизации
*/
export async function login(credentials: Credentials): Promise<boolean> {
try {
// Используем query из graphql.ts для выполнения запроса
const data = await query<LoginResponse>(
`${location.origin}/graphql`,
`
mutation Login($email: String!, $password: String!) {
login(email: $email, password: $password) {
success
token
error
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
}
}
`,
{
email: credentials.email,
password: credentials.password
}
)
})
})
if (data?.login?.success) {
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) {
// Проверяем, установил ли сервер cookie
const cookieToken = getAuthTokenFromCookie()
const hasCookie = !!cookieToken && cookieToken.length > 10
// Если cookie не установлена, но есть токен в ответе, сохраняем его в localStorage
if (!hasCookie && data.login.token) {
localStorage.setItem(AUTH_TOKEN_KEY, data.login.token)
if (!hasCookie && result.data.login.token) {
localStorage.setItem(AUTH_TOKEN_KEY, result.data.login.token)
}
return true
}
throw new Error(data?.login?.error || 'Ошибка авторизации')
if (result.errors && result.errors.length > 0) {
throw new Error(result.errors[0].message || 'Ошибка авторизации')
}
throw new Error(result?.data?.login?.error || 'Неизвестная ошибка авторизации')
} catch (error) {
console.error('Ошибка при входе:', error)
throw error
}
}