WhiteNightsAdminPanel/src/providers/authProvider.ts
2025-05-14 14:42:45 +03:00

183 lines
4.3 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 { 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>(
`${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<ErrorResponse>)?.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<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 };
},
};