core/panel/context/auth.tsx

159 lines
4.5 KiB
TypeScript
Raw Normal View History

2025-06-30 18:25:26 +00:00
import { Component, createContext, createSignal, JSX, useContext } from 'solid-js'
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
login: (username: string, password: string) => Promise<void>
logout: () => Promise<void>
}
const AuthContext = createContext<AuthContextType>({
isAuthenticated: () => false,
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())
console.log(
`[AuthProvider] Initial auth state: ${isAuthenticated() ? 'authenticated' : 'not authenticated'}`
)
const login = async (username: string, password: string) => {
console.log('[AuthProvider] Attempting login...')
try {
2025-07-02 19:30:21 +00:00
const result = await query<{
login: { success: boolean; token?: string }
}>(`${location.origin}/graphql`, ADMIN_LOGIN_MUTATION, {
email: username,
password
})
2025-06-30 18:25:26 +00: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 19:30:21 +00:00
// Сначала очищаем токены на клиенте
clearAuthTokens()
setIsAuthenticated(false)
// Затем делаем запрос на сервер
const result = await query<{ logout: { success: boolean; message?: string } }>(
2025-06-30 18:25:26 +00:00
`${location.origin}/graphql`,
ADMIN_LOGOUT_MUTATION
)
2025-07-02 19:30:21 +00:00
console.log('[AuthProvider] Logout response:', result)
2025-06-30 18:25:26 +00:00
if (result?.logout?.success) {
2025-07-02 19:30:21 +00: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 18:25:26 +00:00
window.location.href = '/login'
}
} catch (error) {
console.error('[AuthProvider] Logout error:', error)
2025-07-02 19:30:21 +00:00
// При любой ошибке редиректим на страницу входа
2025-06-30 18:25:26 +00:00
window.location.href = '/login'
}
}
const value: AuthContextType = {
isAuthenticated,
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 {
const result = await query<{ logout: { success: boolean } }>(
`${location.origin}/graphql`,
ADMIN_LOGOUT_MUTATION
)
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
}
}