improved AuthProvider
This commit is contained in:
@@ -3,7 +3,7 @@ import {
|
||||
createBrowserRouter,
|
||||
Navigate,
|
||||
} from 'react-router-dom';
|
||||
import { useState } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import Chat from './pages/Chat.tsx';
|
||||
import Login from './pages/Login.tsx';
|
||||
import Signup from './pages/Signup.tsx';
|
||||
@@ -11,7 +11,9 @@ import Settings from './pages/Settings.tsx';
|
||||
import Lost from './pages/404.tsx';
|
||||
import { AuthContext } from './utils/AuthProvider.tsx';
|
||||
import ProtectedRoutes from './utils/ProtectedRoutes.tsx';
|
||||
import PublicRoute from '@/utils/PublicRoute.tsx';
|
||||
import axios from 'axios';
|
||||
import Cookies from 'js-cookie';
|
||||
export const axiosClient = axios.create({
|
||||
baseURL: import.meta.env.VITE_BASE_URL,
|
||||
});
|
||||
@@ -34,12 +36,17 @@ const router = createBrowserRouter([
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
element: <Login />,
|
||||
},
|
||||
{
|
||||
path: '/signup',
|
||||
element: <Signup />,
|
||||
element: <PublicRoute />,
|
||||
children: [
|
||||
{
|
||||
path: '/login',
|
||||
element: <Login />,
|
||||
},
|
||||
{
|
||||
path: '/signup',
|
||||
element: <Signup />,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '*',
|
||||
@@ -48,12 +55,38 @@ const router = createBrowserRouter([
|
||||
]);
|
||||
|
||||
function App() {
|
||||
const [authorized, setAuthorized] = useState<boolean | null>(null);
|
||||
const [authorized, setAuthorized] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
async function validateToken() {
|
||||
const token = Cookies.get('token');
|
||||
if (!token) {
|
||||
setAuthorized(false);
|
||||
setIsLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await axiosClient.get('/api/auth/validate', {
|
||||
withCredentials: true,
|
||||
});
|
||||
setAuthorized(true);
|
||||
} catch (e) {
|
||||
setAuthorized(false);
|
||||
console.log('Failed to validate token: ', e);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
validateToken();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<AuthContext.Provider value={{ authorized, setAuthorized }}>
|
||||
<AuthContext.Provider value={{ authorized, isLoading, setAuthorized }}>
|
||||
<RouterProvider router={router} />
|
||||
</AuthContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import { createContext } from 'react';
|
||||
|
||||
type AuthContextType = {
|
||||
authorized: boolean | null;
|
||||
authorized: boolean;
|
||||
isLoading: boolean;
|
||||
setAuthorized: (value: boolean) => void;
|
||||
};
|
||||
|
||||
export const AuthContext = createContext<AuthContextType>({
|
||||
authorized: null,
|
||||
authorized: false,
|
||||
isLoading: true,
|
||||
setAuthorized: () => {},
|
||||
});
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Navigate, Outlet } from 'react-router-dom';
|
||||
import { useState, useEffect, useContext } from 'react';
|
||||
import Cookie from 'js-cookie';
|
||||
import { AuthContext } from './AuthProvider.tsx';
|
||||
import LoadingScreen from '../components/LoadingScreen.tsx';
|
||||
import { axiosClient } from '../App.tsx';
|
||||
@@ -11,37 +10,24 @@ export type UsernameType = {
|
||||
};
|
||||
|
||||
function ProtectedRoutes() {
|
||||
const { authorized, setAuthorized } = useContext(AuthContext);
|
||||
const { authorized, isLoading } = useContext(AuthContext);
|
||||
const [user, setUser] = useState<UsernameType>({
|
||||
username: null,
|
||||
user_id: null,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
function validateToken() {
|
||||
const token = Cookie.get('token');
|
||||
if (!token) {
|
||||
setAuthorized(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (authorized) {
|
||||
axiosClient
|
||||
.get('/api/auth/validate', { withCredentials: true })
|
||||
.then(async (res) => {
|
||||
.then((res) => {
|
||||
setUser(res.data);
|
||||
console.log('User: ', res.data);
|
||||
setAuthorized(true);
|
||||
})
|
||||
.catch((err) => {
|
||||
setAuthorized(false);
|
||||
console.log(err);
|
||||
console.log('Unauthorized');
|
||||
});
|
||||
.catch(console.error);
|
||||
}
|
||||
validateToken();
|
||||
}, [setAuthorized]);
|
||||
}, [authorized]);
|
||||
|
||||
if (authorized === null) {
|
||||
if (isLoading) {
|
||||
return <LoadingScreen />;
|
||||
}
|
||||
|
||||
|
||||
16
client/src/utils/PublicRoute.tsx
Normal file
16
client/src/utils/PublicRoute.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import { Navigate, Outlet } from 'react-router-dom';
|
||||
import { useContext } from 'react';
|
||||
import { AuthContext } from './AuthProvider';
|
||||
import LoadingScreen from '../components/LoadingScreen';
|
||||
|
||||
function PublicRoute() {
|
||||
const { authorized, isLoading } = useContext(AuthContext);
|
||||
|
||||
if (isLoading) {
|
||||
return <LoadingScreen />;
|
||||
}
|
||||
|
||||
return authorized ? <Navigate to="/chat" replace /> : <Outlet />;
|
||||
}
|
||||
|
||||
export default PublicRoute;
|
||||
Reference in New Issue
Block a user