Files
polskalokalnie/frontend/src/ProtectedRoute.tsx
T

38 lines
1.3 KiB
TypeScript

import { Navigate, Outlet, useLocation } from 'react-router-dom';
import { useAuth } from './auth';
import { ROUTES } from './routes';
/**
* Bramka dostępu dla tras wymagających zalogowania (i opcjonalnie roli ADMIN).
*
* Uwaga na `loading`: po odświeżeniu strony token jest w localStorage, ale profil
* dociąga się asynchronicznie z /auth/me. Bez tego warunku bezpośrednie wejście na
* /konto wyrzucałoby zalogowanego użytkownika na logowanie, zanim profil dotrze.
*
* To zabezpieczenie interfejsu, nie kontrola dostępu do danych - autoryzację
* egzekwuje backend przy każdym endpoincie.
*/
export function ProtectedRoute({ requireAdmin = false }: { requireAdmin?: boolean }) {
const { user, loading } = useAuth();
const location = useLocation();
if (loading) {
return (
<div className="route-loading" role="status" aria-live="polite">
Wczytywanie…
</div>
);
}
if (!user) {
// Zapamiętujemy cel, żeby po zalogowaniu wrócić dokładnie tam, gdzie użytkownik zmierzał.
return <Navigate to={ROUTES.login} state={{ from: `${location.pathname}${location.search}` }} replace />;
}
if (requireAdmin && user.role !== 'ADMIN') {
return <Navigate to={ROUTES.account} replace />;
}
return <Outlet />;
}