mirror of
https://github.com/Buriburizaem0n/admin-frontend-domain.git
synced 2026-02-05 13:10:08 +00:00
feat: refresh token
This commit is contained in:
@@ -5,6 +5,10 @@ export const getProfile = async (): Promise<User> => {
|
|||||||
return fetcher<User>(FetcherMethod.GET, '/api/v1/profile', null)
|
return fetcher<User>(FetcherMethod.GET, '/api/v1/profile', null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const refreshToken = async (): Promise<any> => {
|
||||||
|
return fetcher<any>(FetcherMethod.GET, '/api/v1/refresh_token', null)
|
||||||
|
}
|
||||||
|
|
||||||
export const login = async (username: string, password: string): Promise<any> => {
|
export const login = async (username: string, password: string): Promise<any> => {
|
||||||
return fetcher<any>(FetcherMethod.POST, '/api/v1/login', { username, password })
|
return fetcher<any>(FetcherMethod.POST, '/api/v1/login', { username, password })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { createContext, useContext, useEffect, useMemo, useState } from "react";
|
import { createContext, useContext, useEffect, useMemo, useRef } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { useMainStore } from "./useMainStore";
|
import { useMainStore } from "./useMainStore";
|
||||||
import { AuthContextProps } from "@/types";
|
import { AuthContextProps } from "@/types";
|
||||||
import { getProfile, login as loginRequest } from "@/api/user";
|
import { getProfile, login as loginRequest, refreshToken } from "@/api/user";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
|
||||||
const AuthContext = createContext<AuthContextProps>({
|
const AuthContext = createContext<AuthContextProps>({
|
||||||
@@ -16,23 +16,34 @@ export const AuthProvider = ({ children }: {
|
|||||||
}) => {
|
}) => {
|
||||||
const profile = useMainStore(store => store.profile)
|
const profile = useMainStore(store => store.profile)
|
||||||
const setProfile = useMainStore(store => store.setProfile)
|
const setProfile = useMainStore(store => store.setProfile)
|
||||||
const [lastUpdatedAt, setLastUpdatedAt] = useState<number>(0);
|
const initialized = useRef(false)
|
||||||
|
const lastRefreshedAt = useRef(0)
|
||||||
|
|
||||||
// FIXME @naiba 触发了两次
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (profile && Date.now() - lastUpdatedAt > 1000 * 60 * 5) {
|
if (initialized.current) {
|
||||||
console.log(profile, Date.now(), lastUpdatedAt)
|
return
|
||||||
getProfile().then((data) => {
|
|
||||||
setLastUpdatedAt(Date.now())
|
|
||||||
if (data && data.username !== profile.username) {
|
|
||||||
console.log('bingo', data.username);
|
|
||||||
setProfile(data)
|
|
||||||
}
|
|
||||||
}).catch(() => {
|
|
||||||
setLastUpdatedAt(Date.now())
|
|
||||||
setProfile(undefined)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
initialized.current = true;
|
||||||
|
(async () => {
|
||||||
|
while (true) {
|
||||||
|
if (!profile) {
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 1000))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (lastRefreshedAt.current + 1000 * 60 * 10 > Date.now()) {
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 1000))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await refreshToken();
|
||||||
|
const user = await getProfile();
|
||||||
|
setProfile(user);
|
||||||
|
lastRefreshedAt.current = Date.now();
|
||||||
|
} catch (error) {
|
||||||
|
setProfile(undefined);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
}, [profile])
|
}, [profile])
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import { AuthProvider } from './hooks/useAuth';
|
|||||||
|
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
{
|
{
|
||||||
path: "/dashboard/",
|
path: "/dashboard",
|
||||||
element: <AuthProvider><ProtectedRoute><Root /></ProtectedRoute></AuthProvider>,
|
element: <AuthProvider><ProtectedRoute><Root /></ProtectedRoute></AuthProvider>,
|
||||||
errorElement: <ErrorPage />,
|
errorElement: <ErrorPage />,
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ export default () => {
|
|||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Password</FormLabel>
|
<FormLabel>Password</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="shadcn" {...field} />
|
<Input type="password" placeholder="shadcn" {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormDescription>
|
<FormDescription>
|
||||||
This is your public display name.
|
This is your public display name.
|
||||||
@@ -75,7 +75,7 @@ export default () => {
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<Button type="submit">Submit</Button>
|
<Button type="submit">Login</Button>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export const ProtectedRoute = ({ children }: {
|
|||||||
const { profile } = useAuth();
|
const { profile } = useAuth();
|
||||||
|
|
||||||
if (!profile && window.location.pathname !== "/dashboard/login") {
|
if (!profile && window.location.pathname !== "/dashboard/login") {
|
||||||
return <Navigate to="/dashboard/login" />;
|
return <><Navigate to="/dashboard/login" />{children}</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return children;
|
return children;
|
||||||
|
|||||||
Reference in New Issue
Block a user