📦 feat(authAdminGuard): add ProtectedAdminRoute component to handle authentication and authorization for admin pages
📦 feat(catchAllRoutes): add CatchAllRoute component to redirect to the root ("/") when the catch-all route is matched 🔧 refactor(api.tsx): remove console.log statement 🔧 refactor(AdminPage): remove disabled prop from Checkbox components 🔧 refactor(loginPage): change Link to="/signup" to Link to="/signup" to fix incorrect link 🔧 refactor(routes.tsx): remove import statement for ProtectedRoute component and add import statements for CatchAllRoute and ProtectedAdminRoute components
This commit is contained in:
parent
d9d0513a91
commit
6d3d9569bd
6 changed files with 68 additions and 35 deletions
28
src/frontend/src/components/authAdminGuard/index.tsx
Normal file
28
src/frontend/src/components/authAdminGuard/index.tsx
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { useContext, useEffect } from "react";
|
||||||
|
import { Navigate } from "react-router-dom";
|
||||||
|
import { AuthContext } from "../../contexts/authContext";
|
||||||
|
|
||||||
|
export const ProtectedAdminRoute = ({ children }) => {
|
||||||
|
const { isAuthenticated, logout, getAuthentication, userData } =
|
||||||
|
useContext(AuthContext);
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isAuthenticated && !getAuthentication()) {
|
||||||
|
window.location.replace("/login");
|
||||||
|
logout();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData && userData?.is_superuser === false) {
|
||||||
|
logout();
|
||||||
|
}
|
||||||
|
}, [isAuthenticated, getAuthentication, logout, userData]);
|
||||||
|
|
||||||
|
if (!isAuthenticated && !getAuthentication()) {
|
||||||
|
return <Navigate to="/login" replace />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userData && userData?.is_superuser === false) {
|
||||||
|
return <Navigate to="/login" replace />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return children;
|
||||||
|
};
|
||||||
13
src/frontend/src/components/catchAllRoutes/index.tsx
Normal file
13
src/frontend/src/components/catchAllRoutes/index.tsx
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { useEffect } from "react";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
export const CatchAllRoute = () => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
// Redirect to the root ("/") when the catch-all route is matched
|
||||||
|
useEffect(() => {
|
||||||
|
navigate('/');
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
@ -18,8 +18,6 @@ function ApiInterceptor() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const cookies = new Cookies();
|
const cookies = new Cookies();
|
||||||
|
|
||||||
console.log(accessToken);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const interceptor = api.interceptors.response.use(
|
const interceptor = api.interceptors.response.use(
|
||||||
(response) => response,
|
(response) => response,
|
||||||
|
|
@ -49,7 +47,14 @@ function ApiInterceptor() {
|
||||||
navigate("/login");
|
navigate("/login");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if(!refreshToken && error?.config?.url?.includes(
|
||||||
|
"login"
|
||||||
|
) ){
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
else{
|
||||||
logout();
|
logout();
|
||||||
navigate("/login");
|
navigate("/login");
|
||||||
}
|
}
|
||||||
|
|
@ -58,30 +63,7 @@ function ApiInterceptor() {
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
// else {
|
|
||||||
// let retryCount = 0;
|
|
||||||
// while (retryCount < 4) {
|
|
||||||
// await sleep(5000); // Sleep for 5 seconds
|
|
||||||
// retryCount++;
|
|
||||||
// try {
|
|
||||||
// const response = await axios.request(error.config);
|
|
||||||
// return response;
|
|
||||||
// } catch (error) {
|
|
||||||
// if (retryCount === 3) {
|
|
||||||
// setErrorData({
|
|
||||||
// title: "There was an error on web connection, please: ",
|
|
||||||
// list: [
|
|
||||||
// "Refresh the page",
|
|
||||||
// "Use a new flow tab",
|
|
||||||
// "Check if the backend is up",
|
|
||||||
// "Endpoint: " + error.config?.url,
|
|
||||||
// ],
|
|
||||||
// });
|
|
||||||
// return Promise.reject(error);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import {
|
||||||
} from "../../controllers/API";
|
} from "../../controllers/API";
|
||||||
import ConfirmationModal from "../../modals/ConfirmationModal";
|
import ConfirmationModal from "../../modals/ConfirmationModal";
|
||||||
import UserManagementModal from "../../modals/UserManagementModal";
|
import UserManagementModal from "../../modals/UserManagementModal";
|
||||||
|
import { AuthContext } from "../../contexts/authContext";
|
||||||
|
|
||||||
export default function AdminPage() {
|
export default function AdminPage() {
|
||||||
const [inputValue, setInputValue] = useState("");
|
const [inputValue, setInputValue] = useState("");
|
||||||
|
|
@ -31,6 +32,7 @@ export default function AdminPage() {
|
||||||
const [index, setPageIndex] = useState(0);
|
const [index, setPageIndex] = useState(0);
|
||||||
const [loadingUsers, setLoadingUsers] = useState(true);
|
const [loadingUsers, setLoadingUsers] = useState(true);
|
||||||
const { setErrorData, setSuccessData } = useContext(alertContext);
|
const { setErrorData, setSuccessData } = useContext(alertContext);
|
||||||
|
const { userData } = useContext(AuthContext);
|
||||||
|
|
||||||
const userList = useRef([]);
|
const userList = useRef([]);
|
||||||
|
|
||||||
|
|
@ -136,7 +138,12 @@ export default function AdminPage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
<>
|
<>
|
||||||
|
{
|
||||||
|
userData && (
|
||||||
|
|
||||||
|
|
||||||
<div className="main-page-panel">
|
<div className="main-page-panel">
|
||||||
<div className="m-auto flex h-full flex-row justify-center">
|
<div className="m-auto flex h-full flex-row justify-center">
|
||||||
<div className="basis-5/6">
|
<div className="basis-5/6">
|
||||||
|
|
@ -249,14 +256,12 @@ export default function AdminPage() {
|
||||||
<Checkbox
|
<Checkbox
|
||||||
id="is_disabled"
|
id="is_disabled"
|
||||||
checked={user.is_disabled}
|
checked={user.is_disabled}
|
||||||
disabled
|
|
||||||
/>
|
/>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="relative left-5 truncate py-2">
|
<TableCell className="relative left-5 truncate py-2">
|
||||||
<Checkbox
|
<Checkbox
|
||||||
id="is_superuser"
|
id="is_superuser"
|
||||||
checked={user.is_superuser}
|
checked={user.is_superuser}
|
||||||
disabled
|
|
||||||
/>
|
/>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="truncate py-2 ">
|
<TableCell className="truncate py-2 ">
|
||||||
|
|
@ -338,6 +343,9 @@ export default function AdminPage() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@ export default function LoginPage(): JSX.Element {
|
||||||
</Form.Submit>
|
</Form.Submit>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<Link to="">
|
<Link to="/signup">
|
||||||
<Button className="w-full" variant="outline">
|
<Button className="w-full" variant="outline">
|
||||||
Don't have an account? <b>Sign Up</b>
|
Don't have an account? <b>Sign Up</b>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { Route, Routes } from "react-router-dom";
|
import { Route, Routes } from "react-router-dom";
|
||||||
import { ProtectedRoute } from "./components/authGuard";
|
|
||||||
import { ProtectedLoginRoute } from "./components/authLoginGuard";
|
import { ProtectedLoginRoute } from "./components/authLoginGuard";
|
||||||
import AdminPage from "./pages/AdminPage";
|
import AdminPage from "./pages/AdminPage";
|
||||||
import LoginAdminPage from "./pages/AdminPage/LoginPage";
|
import LoginAdminPage from "./pages/AdminPage/LoginPage";
|
||||||
|
|
@ -9,6 +8,9 @@ import HomePage from "./pages/MainPage";
|
||||||
import DeleteAccountPage from "./pages/deleteAccountPage";
|
import DeleteAccountPage from "./pages/deleteAccountPage";
|
||||||
import LoginPage from "./pages/loginPage";
|
import LoginPage from "./pages/loginPage";
|
||||||
import SignUp from "./pages/signUpPage";
|
import SignUp from "./pages/signUpPage";
|
||||||
|
import { CatchAllRoute } from "./components/catchAllRoutes";
|
||||||
|
import { ProtectedRoute } from "./components/authGuard";
|
||||||
|
import { ProtectedAdminRoute } from "./components/authAdminGuard";
|
||||||
|
|
||||||
const Router = () => {
|
const Router = () => {
|
||||||
return (
|
return (
|
||||||
|
|
@ -43,7 +45,7 @@ const Router = () => {
|
||||||
path="*"
|
path="*"
|
||||||
element={
|
element={
|
||||||
<ProtectedRoute>
|
<ProtectedRoute>
|
||||||
<HomePage />
|
<CatchAllRoute />
|
||||||
</ProtectedRoute>
|
</ProtectedRoute>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
@ -76,9 +78,9 @@ const Router = () => {
|
||||||
<Route
|
<Route
|
||||||
path="/admin"
|
path="/admin"
|
||||||
element={
|
element={
|
||||||
<ProtectedRoute>
|
<ProtectedAdminRoute>
|
||||||
<AdminPage />
|
<AdminPage />
|
||||||
</ProtectedRoute>
|
</ProtectedAdminRoute>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue