Files
core/panel/context/auth.tsx

181 lines
5.6 KiB
TypeScript
Raw Normal View History

2025-07-25 09:42:43 +03:00
import { Component, createContext, createSignal, JSX, onMount, useContext } from 'solid-js'
2025-07-25 09:58:34 +03:00
import { AuthSuccess } from '~/graphql/generated/graphql'
2025-06-30 21:25:26 +03:00
import { query } from '../graphql'
import { ADMIN_LOGIN_MUTATION, ADMIN_LOGOUT_MUTATION } from '../graphql/mutations'
import {
AUTH_TOKEN_KEY,
CSRF_TOKEN_KEY,
checkAuthStatus,
clearAuthTokens,
getAuthTokenFromCookie,
getCsrfTokenFromCookie,
saveAuthToken
} from '../utils/auth'
/**
* Модуль авторизации
* @module auth
*/
/**
* Интерфейс для учетных данных
*/
export interface Credentials {
email: string
password: string
}
/**
* Интерфейс для результата авторизации
*/
export interface LoginResult {
success: boolean
token?: string
error?: string
}
// Экспортируем утилитарные функции для обратной совместимости
export {
AUTH_TOKEN_KEY,
CSRF_TOKEN_KEY,
getAuthTokenFromCookie,
getCsrfTokenFromCookie,
checkAuthStatus,
clearAuthTokens,
saveAuthToken
}
interface AuthContextType {
isAuthenticated: () => boolean
2025-07-25 09:42:43 +03:00
isReady: () => boolean
2025-06-30 21:25:26 +03:00
login: (username: string, password: string) => Promise<void>
logout: () => Promise<void>
}
const AuthContext = createContext<AuthContextType>({
isAuthenticated: () => false,
2025-07-25 09:42:43 +03:00
isReady: () => false,
2025-06-30 21:25:26 +03:00
login: async () => {},
logout: async () => {}
})
export const useAuth = () => useContext(AuthContext)
interface AuthProviderProps {
children: JSX.Element
}
export const AuthProvider: Component<AuthProviderProps> = (props) => {
console.log('[AuthProvider] Initializing...')
const [isAuthenticated, setIsAuthenticated] = createSignal(checkAuthStatus())
2025-07-25 09:42:43 +03:00
const [isReady, setIsReady] = createSignal(false)
2025-06-30 21:25:26 +03:00
console.log(
`[AuthProvider] Initial auth state: ${isAuthenticated() ? 'authenticated' : 'not authenticated'}`
)
2025-07-25 09:42:43 +03:00
// Инициализация авторизации при монтировании
onMount(async () => {
console.log('[AuthProvider] Performing auth initialization...')
2025-07-25 09:53:18 +03:00
console.log('[AuthProvider] Checking localStorage token:', !!localStorage.getItem(AUTH_TOKEN_KEY))
console.log('[AuthProvider] Checking cookie token:', !!getAuthTokenFromCookie())
console.log('[AuthProvider] Checking CSRF token:', !!getCsrfTokenFromCookie())
2025-07-25 09:42:43 +03:00
// Небольшая задержка для завершения других инициализаций
await new Promise((resolve) => setTimeout(resolve, 100))
// Проверяем текущее состояние авторизации
const authStatus = checkAuthStatus()
2025-07-25 09:53:18 +03:00
console.log('[AuthProvider] Final auth status after check:', authStatus)
2025-07-25 09:42:43 +03:00
setIsAuthenticated(authStatus)
console.log('[AuthProvider] Auth initialization complete, ready for requests')
setIsReady(true)
})
2025-06-30 21:25:26 +03:00
const login = async (username: string, password: string) => {
console.log('[AuthProvider] Attempting login...')
try {
2025-07-02 22:30:21 +03:00
const result = await query<{
login: { success: boolean; token?: string }
}>(`${location.origin}/graphql`, ADMIN_LOGIN_MUTATION, {
email: username,
password
})
2025-06-30 21:25:26 +03:00
if (result?.login?.success) {
console.log('[AuthProvider] Login successful')
if (result.login.token) {
saveAuthToken(result.login.token)
}
setIsAuthenticated(true)
// Убираем window.location.href - пусть роутер сам обрабатывает навигацию
} else {
console.error('[AuthProvider] Login failed')
throw new Error('Неверные учетные данные')
}
} catch (error) {
console.error('[AuthProvider] Login error:', error)
throw error
}
}
const logout = async () => {
console.log('[AuthProvider] Attempting logout...')
try {
2025-07-02 22:30:21 +03:00
// Сначала очищаем токены на клиенте
clearAuthTokens()
setIsAuthenticated(false)
// Затем делаем запрос на сервер
const result = await query<{ logout: { success: boolean; message?: string } }>(
2025-06-30 21:25:26 +03:00
`${location.origin}/graphql`,
ADMIN_LOGOUT_MUTATION
)
2025-07-02 22:30:21 +03:00
console.log('[AuthProvider] Logout response:', result)
2025-06-30 21:25:26 +03:00
if (result?.logout?.success) {
2025-07-02 22:30:21 +03:00
console.log('[AuthProvider] Logout successful:', result.logout.message)
window.location.href = '/login'
} else {
console.warn('[AuthProvider] Logout was not successful:', result?.logout?.message)
// Все равно редиректим на страницу входа
2025-06-30 21:25:26 +03:00
window.location.href = '/login'
}
} catch (error) {
console.error('[AuthProvider] Logout error:', error)
2025-07-02 22:30:21 +03:00
// При любой ошибке редиректим на страницу входа
2025-06-30 21:25:26 +03:00
window.location.href = '/login'
}
}
const value: AuthContextType = {
isAuthenticated,
2025-07-25 09:42:43 +03:00
isReady,
2025-06-30 21:25:26 +03:00
login,
logout
}
console.log('[AuthProvider] Rendering provider with context')
return <AuthContext.Provider value={value}>{props.children}</AuthContext.Provider>
}
// Export the logout function for direct use
export const logout = async () => {
console.log('[Auth] Executing standalone logout...')
try {
2025-07-25 09:58:34 +03:00
const result = await query<{ logout: AuthSuccess }>(`${location.origin}/graphql`, ADMIN_LOGOUT_MUTATION)
2025-06-30 21:25:26 +03:00
console.log('[Auth] Standalone logout result:', result)
if (result?.logout?.success) {
clearAuthTokens()
return true
}
return false
} catch (error) {
console.error('[Auth] Standalone logout error:', error)
// Даже при ошибке очищаем токены
clearAuthTokens()
throw error
}
}