Skip to content

Commit 4414327

Browse files
authored
Improve route protection and authentication flow (#798)
* Improve route protection and authentication flow * Cleanup
1 parent 01827a1 commit 4414327

File tree

1 file changed

+56
-38
lines changed

1 file changed

+56
-38
lines changed

frontend/src/router.tsx

Lines changed: 56 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { LOGIN_TOKENS, useAuth, useUser } from "@lib/hooks";
33
import UpdatePage from "@pages/update";
44
import { Loader2 } from "lucide-react";
55
import { lazy, Suspense } from "react";
6-
import { BrowserRouter, Route, Routes } from "react-router-dom";
6+
import { BrowserRouter, Navigate, Outlet, Route, Routes, useLocation } from "react-router-dom";
77

88
// Lazy import pages
99
const Resources = lazy(() => import("@pages/resources"));
@@ -63,8 +63,6 @@ const useExchangeToken = () => {
6363
};
6464

6565
export const Router = () => {
66-
const { data: user, error } = useUser();
67-
6866
// Handle exchange token loop to avoid showing login flash
6967
const exchangeTokenPending = useExchangeToken();
7068
if (exchangeTokenPending) {
@@ -75,13 +73,6 @@ export const Router = () => {
7573
);
7674
}
7775

78-
// Only how login once error indicating logged out state actually recieved
79-
if (error) return <Login />;
80-
// Don't display anything if !error and !user. This is loading state.
81-
if (!user) return null;
82-
// Don't try displaying pages if user disabled, will fail to load with many errors.
83-
if (!user.enabled) return <UserDisabled />;
84-
8576
return (
8677
<Suspense
8778
fallback={
@@ -93,34 +84,36 @@ export const Router = () => {
9384
<BrowserRouter>
9485
<Routes>
9586
<Route path="login" element={<Login />} />
96-
<Route path="/" element={<Layout />}>
97-
<Route path="" element={<Home />} />
98-
<Route path="settings" element={<Settings />} />
99-
<Route path="tree" element={<Tree />} />
100-
<Route path="containers" element={<ContainersPage />} />
101-
<Route path="resources" element={<AllResources />} />
102-
<Route path="schedules" element={<SchedulesPage />} />
103-
<Route path="alerts" element={<AlertsPage />} />
104-
<Route path="user-groups/:id" element={<UserGroupPage />} />
105-
<Route path="users/:id" element={<UserPage />} />
106-
<Route path="updates">
107-
<Route path="" element={<UpdatesPage />} />
108-
<Route path=":id" element={<UpdatePage />} />
109-
</Route>
110-
<Route path=":type">
111-
<Route path="" element={<Resources />} />
112-
<Route path=":id" element={<Resource />} />
113-
<Route
114-
path=":id/service/:service"
115-
element={<StackServicePage />}
116-
/>
117-
<Route
118-
path=":id/container/:container"
119-
element={<ContainerPage />}
120-
/>
121-
<Route path=":id/network/:network" element={<NetworkPage />} />
122-
<Route path=":id/image/:image" element={<ImagePage />} />
123-
<Route path=":id/volume/:volume" element={<VolumePage />} />
87+
<Route element={<RequireAuth />}>
88+
<Route path="/" element={<Layout />}>
89+
<Route path="" element={<Home />} />
90+
<Route path="settings" element={<Settings />} />
91+
<Route path="tree" element={<Tree />} />
92+
<Route path="containers" element={<ContainersPage />} />
93+
<Route path="resources" element={<AllResources />} />
94+
<Route path="schedules" element={<SchedulesPage />} />
95+
<Route path="alerts" element={<AlertsPage />} />
96+
<Route path="user-groups/:id" element={<UserGroupPage />} />
97+
<Route path="users/:id" element={<UserPage />} />
98+
<Route path="updates">
99+
<Route path="" element={<UpdatesPage />} />
100+
<Route path=":id" element={<UpdatePage />} />
101+
</Route>
102+
<Route path=":type">
103+
<Route path="" element={<Resources />} />
104+
<Route path=":id" element={<Resource />} />
105+
<Route
106+
path=":id/service/:service"
107+
element={<StackServicePage />}
108+
/>
109+
<Route
110+
path=":id/container/:container"
111+
element={<ContainerPage />}
112+
/>
113+
<Route path=":id/network/:network" element={<NetworkPage />} />
114+
<Route path=":id/image/:image" element={<ImagePage />} />
115+
<Route path=":id/volume/:volume" element={<VolumePage />} />
116+
</Route>
124117
</Route>
125118
</Route>
126119
</Routes>
@@ -131,4 +124,29 @@ export const Router = () => {
131124
// return <RouterProvider router={ROUTER} />;
132125
};
133126

127+
const RequireAuth = () => {
128+
const { data: user, error } = useUser();
129+
const location = useLocation();
130+
131+
if (error) {
132+
if (location.pathname === "/") {
133+
return <Navigate to="/login" replace />;
134+
}
135+
const backto = encodeURIComponent(location.pathname + location.search);
136+
return <Navigate to={`/login?backto=${backto}`} replace />;
137+
}
138+
139+
if (!user) {
140+
return (
141+
<div className="w-screen h-screen flex justify-center items-center">
142+
<Loader2 className="w-8 h-8 animate-spin" />
143+
</div>
144+
);
145+
}
146+
147+
if (!user.enabled) return <UserDisabled />;
148+
149+
return <Outlet />;
150+
};
151+
134152

0 commit comments

Comments
 (0)