Public Access
refactor(frontend): lint, one session guard, one request helper, one user context
This commit is contained in:
1 parent
111ab1e200
commit
d0ea9e900d
78 files changed
+2138
-624
No files matched your search
@@ -0,0 +1,34 @@
|
||||
import {useEffect, useRef} from 'react';
|
||||
import {Navigate, Outlet, useLocation} from 'react-router-dom';
|
||||
import useSessionExpired from '../hooks/useSessionExpired.js';
|
||||
import {sessionEvents} from '../utils/api.js';
|
||||
import {hasSession} from '../utils/auth.js';
|
||||
|
||||
/**
|
||||
* Layout route of the pages that need a login. Without a session it opens the login page, which comes back here;
|
||||
* a 401 on one of these pages ends the session (see apiFetch).
|
||||
*/
|
||||
export default function RequireSession() {
|
||||
const {pathname, search} = useLocation();
|
||||
const expireSession = useSessionExpired();
|
||||
// In a ref, so the listener is added once and not again on every navigation.
|
||||
const expireRef = useRef(expireSession);
|
||||
expireRef.current = expireSession;
|
||||
// A render before the login page shows must not redirect again without the "session expired" state.
|
||||
const expiring = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
// Parallel requests each fire; only the first ends the session. Another tab may have removed the flag already.
|
||||
const onExpired = () => {
|
||||
if (expiring.current) return;
|
||||
expiring.current = true;
|
||||
expireRef.current();
|
||||
};
|
||||
sessionEvents.addEventListener('expired', onExpired);
|
||||
return () => sessionEvents.removeEventListener('expired', onExpired);
|
||||
}, []);
|
||||
|
||||
return hasSession() || expiring.current
|
||||
? <Outlet/>
|
||||
: <Navigate to="/login" replace state={{from: pathname + search}}/>;
|
||||
}
|
||||
Reference in new issue
Block a user