2023-03-31 14:59:54 +00:00
|
|
|
|
import axios, { AxiosResponse } from "axios";
|
2023-03-19 15:26:39 +00:00
|
|
|
|
import { create } from "zustand";
|
|
|
|
|
import { persist } from "zustand/middleware";
|
|
|
|
|
|
2023-03-31 14:59:54 +00:00
|
|
|
|
|
2023-03-20 11:40:19 +00:00
|
|
|
|
type Token = string;
|
2023-03-31 14:59:54 +00:00
|
|
|
|
|
2023-03-19 15:26:39 +00:00
|
|
|
|
interface AuthStore {
|
2023-03-20 11:40:19 +00:00
|
|
|
|
token: Token;
|
2023-03-31 14:59:54 +00:00
|
|
|
|
makeRequest: <TRequest = unknown, TResponse = unknown>(props: FirstRequest<TRequest>) => Promise<TResponse>;
|
|
|
|
|
clearToken: () => void;
|
2023-03-19 15:26:39 +00:00
|
|
|
|
}
|
2023-03-31 14:59:54 +00:00
|
|
|
|
|
|
|
|
|
interface FirstRequest<T> {
|
2023-03-20 11:40:19 +00:00
|
|
|
|
method?: string;
|
|
|
|
|
url: string;
|
2023-03-31 14:59:54 +00:00
|
|
|
|
body?: T;
|
2023-03-20 11:40:19 +00:00
|
|
|
|
useToken?: boolean;
|
|
|
|
|
contentType?: boolean;
|
2023-03-31 14:59:54 +00:00
|
|
|
|
signal?: AbortSignal;
|
2023-04-13 16:48:17 +00:00
|
|
|
|
withCredentials?: boolean;
|
2023-03-19 15:26:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-03-31 14:59:54 +00:00
|
|
|
|
export const authStore = create<AuthStore>()(
|
2023-03-20 11:40:19 +00:00
|
|
|
|
persist(
|
|
|
|
|
(set, get) => ({
|
|
|
|
|
token: "",
|
2023-03-31 14:59:54 +00:00
|
|
|
|
makeRequest: <TRequest, TResponse>(props: FirstRequest<TRequest>): Promise<TResponse> => {
|
2023-03-20 11:40:19 +00:00
|
|
|
|
const newProps = { ...props, HC: (newToken: Token) => set({ token: newToken }), token: get().token };
|
2023-03-31 14:59:54 +00:00
|
|
|
|
|
|
|
|
|
return makeRequest<TRequest, TResponse>(newProps);
|
2023-03-20 11:40:19 +00:00
|
|
|
|
},
|
|
|
|
|
clearToken: () => set({ token: "" }),
|
|
|
|
|
}),
|
|
|
|
|
{
|
|
|
|
|
name: "token",
|
|
|
|
|
}
|
|
|
|
|
)
|
2023-03-19 15:26:39 +00:00
|
|
|
|
);
|
2023-03-31 14:59:54 +00:00
|
|
|
|
|
|
|
|
|
interface MakeRequest<T> extends FirstRequest<T> {
|
2023-03-20 11:40:19 +00:00
|
|
|
|
HC: (newToken: Token) => void;
|
|
|
|
|
token: Token;
|
2023-03-19 15:26:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-03-31 14:59:54 +00:00
|
|
|
|
async function makeRequest<TRequest, TResponse>({
|
|
|
|
|
method = "post",
|
|
|
|
|
url,
|
|
|
|
|
body,
|
|
|
|
|
useToken = true,
|
|
|
|
|
contentType = false,
|
|
|
|
|
HC,
|
|
|
|
|
token,
|
|
|
|
|
signal,
|
2023-04-13 16:48:17 +00:00
|
|
|
|
withCredentials,
|
2023-03-31 14:59:54 +00:00
|
|
|
|
}: MakeRequest<TRequest>) {
|
2023-03-20 11:40:19 +00:00
|
|
|
|
//В случае 401 рефреш должен попробовать вызваться 1 раз
|
|
|
|
|
let headers: any = {};
|
|
|
|
|
if (useToken) headers["Authorization"] = token;
|
2023-04-13 16:48:17 +00:00
|
|
|
|
if (contentType) headers["Content-Type"] = "*/*";
|
2023-03-31 14:59:54 +00:00
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const response = await axios<TRequest, AxiosResponse<TResponse & { accessToken?: string; }>>(
|
2023-04-13 16:48:17 +00:00
|
|
|
|
{ url, method, headers, data: body, signal, withCredentials }
|
2023-03-31 14:59:54 +00:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (response.data?.accessToken) {
|
|
|
|
|
HC(response.data.accessToken);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return response.data;
|
|
|
|
|
} catch (error: any) {
|
2023-04-13 16:48:17 +00:00
|
|
|
|
if (error?.response?.status === 401 && !withCredentials) {
|
2023-05-12 14:33:44 +00:00
|
|
|
|
const refreshResponse = await refresh(token);
|
2023-03-31 14:59:54 +00:00
|
|
|
|
if (refreshResponse.data?.accessToken) HC(refreshResponse.data.accessToken);
|
|
|
|
|
|
|
|
|
|
headers["Authorization"] = refreshResponse.data.accessToken;
|
|
|
|
|
const response = await axios<TRequest, AxiosResponse<TResponse>>(
|
|
|
|
|
{ url, method, headers, data: body, signal }
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return response.data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
2023-03-19 15:26:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-05-12 14:33:44 +00:00
|
|
|
|
function refresh(token:Token) {
|
2023-03-31 14:59:54 +00:00
|
|
|
|
return axios<never, AxiosResponse<{ accessToken: string; }>>("https://admin.pena.digital/auth/refresh", {
|
2023-03-20 11:40:19 +00:00
|
|
|
|
headers: {
|
2023-05-12 14:33:44 +00:00
|
|
|
|
Authorization: token,
|
2023-03-20 11:40:19 +00:00
|
|
|
|
"Content-Type": "application/json",
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|