WhiteNightsAdminPanel/src/authProvider.ts
2025-03-28 03:54:15 +03:00

175 lines
4.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import type {AuthProvider} from '@refinedev/core'
import axios, {AxiosError} from 'axios'
import {BACKEND_URL} from './lib/constants'
import {jwtDecode} from 'jwt-decode'
export const TOKEN_KEY = 'refine-auth'
interface AuthResponse {
token: string
user: {
id: number
name: string
email: string
is_admin: boolean
}
}
interface ErrorResponse {
message: string
}
class AuthError extends Error {
constructor(message: string) {
super(message)
this.name = 'AuthError'
}
}
interface JWTPayload {
user_id: number
email: string
is_admin: boolean
exp: number
}
export const authProvider: AuthProvider = {
login: async ({email, password}) => {
try {
const response = await axios.post<AuthResponse>(`${BACKEND_URL}/auth/login`, {
email,
password,
})
const {token, user} = response.data
if (token) {
localStorage.setItem(TOKEN_KEY, token)
localStorage.setItem('user', JSON.stringify(user))
return {
success: true,
redirectTo: '/',
}
}
throw new AuthError('Неверный email или пароль')
} catch (error) {
const errorMessage = (error as AxiosError<ErrorResponse>)?.response?.data?.message || 'Неверный email или пароль'
return {
success: false,
error: new AuthError(errorMessage),
}
}
},
logout: async () => {
try {
await axios.post(
`${BACKEND_URL}/auth/logout`,
{},
{
headers: {
Authorization: `Bearer ${localStorage.getItem(TOKEN_KEY)}`,
},
},
)
} catch (error) {
console.error('Ошибка при выходе:', error)
}
localStorage.removeItem(TOKEN_KEY)
localStorage.removeItem('user')
return {
success: true,
redirectTo: '/login',
}
},
check: async () => {
const token = localStorage.getItem(TOKEN_KEY)
if (!token) {
return {
authenticated: false,
redirectTo: '/login',
}
}
try {
const response = await axios.get(`${BACKEND_URL}/auth/me`, {
headers: {
Authorization: `Bearer ${token}`,
},
})
if (response.status === 200) {
// Обновляем информацию о пользователе
localStorage.setItem('user', JSON.stringify(response.data))
return {
authenticated: true,
}
}
} catch (error) {
localStorage.removeItem(TOKEN_KEY)
localStorage.removeItem('user')
return {
authenticated: false,
redirectTo: '/login',
error: new AuthError('Сессия истекла, пожалуйста, войдите снова'),
}
}
return {
authenticated: false,
redirectTo: '/login',
}
},
getPermissions: async () => {
const token = localStorage.getItem(TOKEN_KEY)
if (!token) return null
try {
const decoded = jwtDecode<JWTPayload>(token)
if (decoded.is_admin) {
document.body.classList.add('is-admin')
} else {
document.body.classList.remove('is-admin')
}
return decoded.is_admin ? ['admin'] : ['user']
} catch {
document.body.classList.remove('is-admin')
return ['user']
}
},
getIdentity: async () => {
const token = localStorage.getItem(TOKEN_KEY)
const user = localStorage.getItem('user')
if (!token || !user) return null
try {
const decoded = jwtDecode<JWTPayload>(token)
const userData = JSON.parse(user)
return {
...userData,
is_admin: decoded.is_admin, // всегда используем значение из токена
}
} catch {
return null
}
},
onError: async (error) => {
const status = (error as AxiosError)?.response?.status
if (status === 401 || status === 403) {
localStorage.removeItem(TOKEN_KEY)
localStorage.removeItem('user')
return {
logout: true,
redirectTo: '/login',
error: new AuthError('Сессия истекла, пожалуйста, войдите снова'),
}
}
return {error}
},
}