mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-08-29 15:18:12 +00:00
Adding license generation functionality
This commit is contained in:
70
libs/auth/src/lib/components/AuthBootstrap.tsx
Normal file
70
libs/auth/src/lib/components/AuthBootstrap.tsx
Normal file
@@ -0,0 +1,70 @@
|
||||
import { useEffect, useState, type ReactNode } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { authStorage } from '../utils/auth-storage';
|
||||
import { hydrateAuth, logout, setUser } from '../store/auth.slice';
|
||||
import type { AuthUser } from '../types/auth.types';
|
||||
|
||||
const BASE_API_URL =
|
||||
(import.meta as { env?: Record<string, string> }).env?.['VITE_BASE_API_URL'] ??
|
||||
'http://localhost:3001/api';
|
||||
|
||||
/**
|
||||
* Restores the signed-in session before the router renders.
|
||||
*
|
||||
* Redux starts empty on every page load while the token lives in
|
||||
* localStorage, so without this a refresh leaves the app half–signed-in: the
|
||||
* route guards see a token and let you through, but pages that read
|
||||
* `auth.user` think you are a stranger.
|
||||
*
|
||||
* A token the server no longer accepts is cleared here rather than left to
|
||||
* strand the user on a page they cannot act on or sign out of.
|
||||
*/
|
||||
export function AuthBootstrap({ children }: { children: ReactNode }) {
|
||||
const dispatch = useDispatch();
|
||||
const [ready, setReady] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
|
||||
async function restore() {
|
||||
dispatch(hydrateAuth());
|
||||
|
||||
const token = authStorage.getToken();
|
||||
if (!token) {
|
||||
if (!cancelled) setReady(true);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`${BASE_API_URL}/auth/me`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const user = (await response.json()) as AuthUser;
|
||||
if (!cancelled) dispatch(setUser(user));
|
||||
} else if (response.status === 401 || response.status === 403) {
|
||||
// Expired or revoked — drop it so the user gets a login screen
|
||||
// instead of a dead end.
|
||||
if (!cancelled) dispatch(logout());
|
||||
}
|
||||
} catch {
|
||||
// Offline or the API is down: keep the stored session and let the
|
||||
// individual screens surface their own errors.
|
||||
} finally {
|
||||
if (!cancelled) setReady(true);
|
||||
}
|
||||
}
|
||||
|
||||
restore();
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [dispatch]);
|
||||
|
||||
// Rendering the router before the session resolves would let the guards
|
||||
// redirect based on a state that is about to change.
|
||||
if (!ready) return null;
|
||||
|
||||
return <>{children}</>;
|
||||
}
|
||||
Reference in New Issue
Block a user