183 lines
4.3 KiB
TypeScript
183 lines
4.3 KiB
TypeScript
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 };
|
||
},
|
||
};
|