refactor, security updates, cv extraction upgrades
This commit is contained in:
@@ -32,7 +32,7 @@ import ForgotPasswordPage from "./pages/ForgotPasswordPage";
|
||||
import ResetPasswordPage from "./pages/ResetPasswordPage";
|
||||
import RouteErrorPage from "./pages/RouteErrorPage";
|
||||
import { api } from "./api";
|
||||
import { clearAuthToken, getAuthToken } from "./auth";
|
||||
import { clearAuthClientState, setAuthUserKey } from "./auth";
|
||||
import AppShell, { NavItem } from "./layout/AppShell";
|
||||
import { clearAccentColor, getAccentColor, getThemeModePref, setAccentColor, setThemeModePref, ThemeModePref } from "./themePrefs";
|
||||
|
||||
@@ -112,6 +112,7 @@ function Shell({ jobPageSize, setJobPageSize, jobColumns, setJobColumns, themeMo
|
||||
const [quickOpen, setQuickOpen] = useState(false);
|
||||
const [refreshToken, setRefreshToken] = useState(0);
|
||||
const [requireAuth, setRequireAuth] = useState<boolean | null>(null);
|
||||
const [authResolved, setAuthResolved] = useState(false);
|
||||
const [isAdmin, setIsAdmin] = useState(false);
|
||||
const [me, setMe] = useState<MeResponse | null>(null);
|
||||
const [mobileDrawerOpen, setMobileDrawerOpen] = useState(false);
|
||||
@@ -124,7 +125,26 @@ function Shell({ jobPageSize, setJobPageSize, jobColumns, setJobColumns, themeMo
|
||||
api.get<AuthConfig>("/auth/config").then((r) => setRequireAuth(Boolean(r.data?.requireAuth))).catch(() => setRequireAuth(false));
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
api.get<MeResponse>("/auth/me").then((r) => { setMe(r.data); setIsAdmin(Boolean(r.data?.roles?.includes("Admin"))); }).catch(() => { setMe(null); setIsAdmin(false); });
|
||||
let active = true;
|
||||
api.get<MeResponse>("/auth/me")
|
||||
.then((r) => {
|
||||
if (!active) return;
|
||||
setMe(r.data);
|
||||
setIsAdmin(Boolean(r.data?.roles?.includes("Admin")));
|
||||
setAuthUserKey(r.data?.id || r.data?.email || r.data?.userName || null, false);
|
||||
})
|
||||
.catch(() => {
|
||||
if (!active) return;
|
||||
setMe(null);
|
||||
setIsAdmin(false);
|
||||
clearAuthClientState(false);
|
||||
})
|
||||
.finally(() => {
|
||||
if (active) setAuthResolved(true);
|
||||
});
|
||||
return () => {
|
||||
active = false;
|
||||
};
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
const load = () => {
|
||||
@@ -134,6 +154,27 @@ function Shell({ jobPageSize, setJobPageSize, jobColumns, setJobColumns, themeMo
|
||||
const id = window.setInterval(load, 60000);
|
||||
return () => window.clearInterval(id);
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
const onAuthChanged = () => {
|
||||
setAuthResolved(false);
|
||||
api.get<MeResponse>("/auth/me")
|
||||
.then((r) => {
|
||||
setMe(r.data);
|
||||
setIsAdmin(Boolean(r.data?.roles?.includes("Admin")));
|
||||
setAuthUserKey(r.data?.id || r.data?.email || r.data?.userName || null, false);
|
||||
})
|
||||
.catch(() => {
|
||||
setMe(null);
|
||||
setIsAdmin(false);
|
||||
clearAuthClientState(false);
|
||||
})
|
||||
.finally(() => setAuthResolved(true));
|
||||
};
|
||||
|
||||
window.addEventListener("auth-changed", onAuthChanged);
|
||||
return () => window.removeEventListener("auth-changed", onAuthChanged);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const onKeyDown = (e: KeyboardEvent) => {
|
||||
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "k") {
|
||||
@@ -145,9 +186,8 @@ function Shell({ jobPageSize, setJobPageSize, jobColumns, setJobColumns, themeMo
|
||||
return () => window.removeEventListener("keydown", onKeyDown);
|
||||
}, []);
|
||||
|
||||
const token = getAuthToken();
|
||||
if (requireAuth === null) return <Box sx={{ p: 4 }}><Typography variant="h6">Loading...</Typography></Box>;
|
||||
if (requireAuth && !token) return <Navigate to="/login" replace state={{ from: path }} />;
|
||||
if (requireAuth === null || !authResolved) return <Box sx={{ p: 4 }}><Typography variant="h6">Loading...</Typography></Box>;
|
||||
if (requireAuth && !me) return <Navigate to="/login" replace state={{ from: path }} />;
|
||||
|
||||
const pageTitle = titleFor(path, t);
|
||||
const breadcrumbs = breadcrumbsFor(path, t);
|
||||
@@ -223,7 +263,7 @@ function Shell({ jobPageSize, setJobPageSize, jobColumns, setJobColumns, themeMo
|
||||
onOpenNotifications={() => navigate("/reminders")}
|
||||
onOpenSettings={() => navigate("/settings")}
|
||||
onOpenProfile={() => navigate("/profile")}
|
||||
onSignOut={() => { clearAuthToken(); navigate("/login"); }}
|
||||
onSignOut={() => { void api.post("/auth/logout").catch(() => undefined).finally(() => { clearAuthClientState(); navigate("/login"); }); }}
|
||||
rightActions={rightActions}
|
||||
>
|
||||
<Suspense fallback={<PageLoader />}>
|
||||
|
||||
Reference in New Issue
Block a user