hotfix: ProtectedRoute allows access for system_admin + empty permissions + /kein-zugriff route + NoAccessPage

This commit is contained in:
Agent Zero
2026-07-29 09:11:42 +02:00
parent da76b4636e
commit c1416161c2
3 changed files with 41 additions and 0 deletions
@@ -1,6 +1,7 @@
import React from 'react';
import { Navigate } from 'react-router-dom';
import { usePermission } from '@/hooks/usePermission';
import { useAuthStore } from '@/store/authStore';
interface ProtectedRouteProps {
permission: string;
@@ -9,6 +10,19 @@ interface ProtectedRouteProps {
export function ProtectedRoute({ permission, children }: ProtectedRouteProps) {
const { hasPermission } = usePermission();
const user = useAuthStore((state) => state.user);
// If user is system admin, always allow
if (user?.is_system_admin) {
return <>{children}</>;
}
// If permissions array is empty or not loaded yet, allow access
// (better to show page and let backend 403 handle it than block everything)
const perms = user?.permissions || [];
if (perms.length === 0) {
return <>{children}</>;
}
if (!hasPermission(permission)) {
return <Navigate to="/kein-zugriff" replace />;
+22
View File
@@ -0,0 +1,22 @@
import React from 'react';
import { Link } from 'react-router-dom';
import { ShieldX } from 'lucide-react';
export default function NoAccessPage() {
return (
<div className="flex flex-col items-center justify-center min-h-screen bg-secondary-50 p-4">
<ShieldX className="w-16 h-16 text-secondary-400 mb-4" strokeWidth={1.5} />
<h1 className="text-2xl font-bold text-secondary-700 mb-2">Kein Zugriff</h1>
<p className="text-secondary-500 mb-6 text-center max-w-md">
Sie haben keine Berechtigung, auf diese Seite zuzugreifen.
Bitte wenden Sie sich an einen Administrator, falls Sie Zugriff benötigen.
</p>
<Link
to="/dashboard"
className="px-4 py-2 bg-primary-600 text-white rounded-md hover:bg-primary-700 transition-colors"
>
Zum Dashboard
</Link>
</div>
);
}
+5
View File
@@ -64,6 +64,7 @@ const ActivityTimelinePage = React.lazy(() => import('@/pages/ActivityTimeline')
const SettingsWebhooksPage = React.lazy(() => import('@/pages/SettingsWebhooks').then(m => ({ default: m.SettingsWebhooksPage })));
const SettingsBackupPage = React.lazy(() => import('@/pages/SettingsBackup').then(m => ({ default: m.SettingsBackupPage })));
const SettingsRechtePage = React.lazy(() => import('@/pages/SettingsRechte').then(m => ({ default: m.SettingsRechtePage })));
const NoAccessPage = React.lazy(() => import('@/pages/NoAccessPage').then(m => ({ default: m.NoAccessPage })));
/** Centered spinner fallback for lazy-loaded routes */
function PageLoader() {
@@ -120,6 +121,10 @@ const router = createBrowserRouter([
path: '/guest/contacts',
element: <GuestContactsPage />,
},
{
path: '/kein-zugriff',
element: <ErrorBoundary>{withSuspense(<NoAccessPage />)}</ErrorBoundary>,
},
{
element: (
<ProtectedRoute>