rights system
This commit is contained in:
@@ -31,7 +31,7 @@ import {
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { Navigate } from 'react-router-dom';
|
||||
import DashboardLayout from '../components/dashboard/DashboardLayout';
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
import { usePermissionContext } from '../contexts/PermissionContext';
|
||||
import { useNotification } from '../contexts/NotificationContext';
|
||||
import { settingsApi } from '../services/settings';
|
||||
|
||||
@@ -61,11 +61,11 @@ const ADMIN_INTERVAL_OPTIONS = [
|
||||
];
|
||||
|
||||
function AdminSettings() {
|
||||
const { user } = useAuth();
|
||||
const { hasPermission } = usePermissionContext();
|
||||
const { showSuccess, showError } = useNotification();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const isAdmin = user?.groups?.includes('dashboard_admin') ?? false;
|
||||
const canAccess = hasPermission('admin:write');
|
||||
|
||||
// State for link collections
|
||||
const [linkCollections, setLinkCollections] = useState<LinkCollection[]>([]);
|
||||
@@ -86,7 +86,7 @@ function AdminSettings() {
|
||||
const { data: settings, isLoading } = useQuery({
|
||||
queryKey: ['admin-settings'],
|
||||
queryFn: () => settingsApi.getAll(),
|
||||
enabled: isAdmin,
|
||||
enabled: canAccess,
|
||||
});
|
||||
|
||||
// Initialize state from fetched settings
|
||||
@@ -197,7 +197,7 @@ function AdminSettings() {
|
||||
reader.readAsDataURL(file);
|
||||
};
|
||||
|
||||
if (!isAdmin) {
|
||||
if (!canAccess) {
|
||||
return <Navigate to="/dashboard" replace />;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ import {
|
||||
} from '@mui/icons-material';
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import DashboardLayout from '../components/dashboard/DashboardLayout';
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
import { usePermissionContext } from '../contexts/PermissionContext';
|
||||
import { trainingApi } from '../services/training';
|
||||
import type { TeilnahmeStatus, UebungTyp, Teilnahme } from '../types/training.types';
|
||||
|
||||
@@ -75,18 +75,6 @@ function formatTime(iso: string): string {
|
||||
return `${String(d.getHours()).padStart(2,'0')}:${String(d.getMinutes()).padStart(2,'0')} Uhr`;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Role helper — reads `role` from the user object (added by Tier 1)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const ROLE_ORDER: Record<string, number> = {
|
||||
mitglied: 0, gruppenfuehrer: 1, kommandant: 2, admin: 3,
|
||||
};
|
||||
|
||||
function hasRole(userRole: string | undefined, minRole: string): boolean {
|
||||
return (ROLE_ORDER[userRole ?? 'mitglied'] ?? 0) >= (ROLE_ORDER[minRole] ?? 0);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// RSVP Status icon
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -199,7 +187,7 @@ function MarkAttendanceDialog({
|
||||
function AttendeeAccordion({
|
||||
teilnahmen,
|
||||
counts,
|
||||
userRole,
|
||||
canSeeList,
|
||||
}: {
|
||||
teilnahmen?: Teilnahme[];
|
||||
counts: {
|
||||
@@ -210,9 +198,8 @@ function AttendeeAccordion({
|
||||
anzahl_erschienen: number;
|
||||
gesamt_eingeladen: number;
|
||||
};
|
||||
userRole?: string;
|
||||
canSeeList: boolean;
|
||||
}) {
|
||||
const canSeeList = hasRole(userRole, 'gruppenfuehrer');
|
||||
|
||||
return (
|
||||
<Accordion disableGutters elevation={0} sx={{ border: '1px solid', borderColor: 'divider', borderRadius: 1 }}>
|
||||
@@ -279,14 +266,13 @@ function AttendeeAccordion({
|
||||
export default function UebungDetail() {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const navigate = useNavigate();
|
||||
const { user } = useAuth();
|
||||
const { hasPermission } = usePermissionContext();
|
||||
const queryClient = useQueryClient();
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
|
||||
|
||||
// We cast user to include `role` (added by Tier 1)
|
||||
const userRole = (user as any)?.role as string | undefined;
|
||||
const canWrite = hasRole(userRole, 'gruppenfuehrer');
|
||||
const canWrite = hasPermission('kalender:create');
|
||||
const canSeeAttendees = hasPermission('kalender:mark_attendance');
|
||||
|
||||
const [markAttendanceOpen, setMarkAttendanceOpen] = useState(false);
|
||||
const [rsvpLoading, setRsvpLoading] = useState<'zugesagt' | 'abgesagt' | null>(null);
|
||||
@@ -531,7 +517,7 @@ export default function UebungDetail() {
|
||||
<AttendeeAccordion
|
||||
teilnahmen={event.teilnahmen}
|
||||
counts={event}
|
||||
userRole={userRole}
|
||||
canSeeList={canSeeAttendees}
|
||||
/>
|
||||
</Paper>
|
||||
</Box>
|
||||
|
||||
Reference in New Issue
Block a user