import type { AuthProvider } from "@refinedev/core"; import axios, { AxiosError } from "axios"; 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( `${import.meta.env.VITE_KRBL_API}/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)?.response?.data?.message || "Неверный email или пароль"; return { success: false, error: new AuthError(errorMessage), }; } }, logout: async () => { try { await axios.post( `${import.meta.env.VITE_KRBL_API}/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( `${import.meta.env.VITE_KRBL_API}/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(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(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 }; }, };