calendar and vehicle booking rework
This commit is contained in:
@@ -226,8 +226,8 @@ class BookingController {
|
|||||||
const isOwner = booking.gebucht_von === req.user!.id;
|
const isOwner = booking.gebucht_von === req.user!.id;
|
||||||
const groups: string[] = req.user?.groups ?? [];
|
const groups: string[] = req.user?.groups ?? [];
|
||||||
const isAdmin = groups.includes('dashboard_admin');
|
const isAdmin = groups.includes('dashboard_admin');
|
||||||
const canCancelOwn = isAdmin || permissionService.hasPermission(groups, 'kalender:manage_bookings');
|
const canCancelOwn = isAdmin || permissionService.hasPermission(groups, 'fahrzeugbuchungen:manage');
|
||||||
const canCancelAny = isAdmin || permissionService.hasPermission(groups, 'kalender:manage_bookings');
|
const canCancelAny = isAdmin || permissionService.hasPermission(groups, 'fahrzeugbuchungen:manage');
|
||||||
|
|
||||||
if (!(isOwner && canCancelOwn) && !canCancelAny) {
|
if (!(isOwner && canCancelOwn) && !canCancelAny) {
|
||||||
res.status(403).json({ success: false, message: 'Keine Berechtigung' });
|
res.status(403).json({ success: false, message: 'Keine Berechtigung' });
|
||||||
|
|||||||
@@ -18,15 +18,15 @@ router.get('/calendar-token', authenticate, bookingController.getCalendarToken.b
|
|||||||
|
|
||||||
// ── Write operations ──────────────────────────────────────────────────────────
|
// ── Write operations ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
router.post('/', authenticate, requirePermission('kalender:manage_bookings'), bookingController.create.bind(bookingController));
|
router.post('/', authenticate, requirePermission('fahrzeugbuchungen:create'), bookingController.create.bind(bookingController));
|
||||||
router.patch('/:id', authenticate, requirePermission('kalender:manage_bookings'), bookingController.update.bind(bookingController));
|
router.patch('/:id', authenticate, requirePermission('fahrzeugbuchungen:manage'), bookingController.update.bind(bookingController));
|
||||||
|
|
||||||
// Soft-cancel (sets abgesagt=TRUE) — creator or bookings:write
|
// Soft-cancel (sets abgesagt=TRUE) — creator or bookings:write
|
||||||
router.delete('/:id', authenticate, bookingController.cancel.bind(bookingController));
|
router.delete('/:id', authenticate, bookingController.cancel.bind(bookingController));
|
||||||
router.patch('/:id/cancel', authenticate, bookingController.cancel.bind(bookingController));
|
router.patch('/:id/cancel', authenticate, bookingController.cancel.bind(bookingController));
|
||||||
|
|
||||||
// Hard-delete (admin only)
|
// Hard-delete (admin only)
|
||||||
router.delete('/:id/force', authenticate, requirePermission('kalender:manage_bookings'), bookingController.hardDelete.bind(bookingController));
|
router.delete('/:id/force', authenticate, requirePermission('fahrzeugbuchungen:manage'), bookingController.hardDelete.bind(bookingController));
|
||||||
|
|
||||||
// ── Single booking read — after specific routes to avoid path conflicts ───────
|
// ── Single booking read — after specific routes to avoid path conflicts ───────
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const router = Router();
|
|||||||
router.get(
|
router.get(
|
||||||
'/',
|
'/',
|
||||||
authenticate,
|
authenticate,
|
||||||
requirePermission('kalender:view_bookings'),
|
requirePermission('fahrzeugbuchungen:view'),
|
||||||
buchungskategorieController.list.bind(buchungskategorieController)
|
buchungskategorieController.list.bind(buchungskategorieController)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ router.get(
|
|||||||
router.get(
|
router.get(
|
||||||
'/active',
|
'/active',
|
||||||
authenticate,
|
authenticate,
|
||||||
requirePermission('kalender:view_bookings'),
|
requirePermission('fahrzeugbuchungen:view'),
|
||||||
buchungskategorieController.listActive.bind(buchungskategorieController)
|
buchungskategorieController.listActive.bind(buchungskategorieController)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ router.get(
|
|||||||
router.post(
|
router.post(
|
||||||
'/',
|
'/',
|
||||||
authenticate,
|
authenticate,
|
||||||
requirePermission('kalender:manage_bookings'),
|
requirePermission('fahrzeugbuchungen:manage'),
|
||||||
buchungskategorieController.create.bind(buchungskategorieController)
|
buchungskategorieController.create.bind(buchungskategorieController)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ router.post(
|
|||||||
router.patch(
|
router.patch(
|
||||||
'/:id',
|
'/:id',
|
||||||
authenticate,
|
authenticate,
|
||||||
requirePermission('kalender:manage_bookings'),
|
requirePermission('fahrzeugbuchungen:manage'),
|
||||||
buchungskategorieController.update.bind(buchungskategorieController)
|
buchungskategorieController.update.bind(buchungskategorieController)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ router.patch(
|
|||||||
router.delete(
|
router.delete(
|
||||||
'/:id',
|
'/:id',
|
||||||
authenticate,
|
authenticate,
|
||||||
requirePermission('kalender:manage_bookings'),
|
requirePermission('fahrzeugbuchungen:manage'),
|
||||||
buchungskategorieController.deactivate.bind(buchungskategorieController)
|
buchungskategorieController.deactivate.bind(buchungskategorieController)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ router.delete(
|
|||||||
router.delete(
|
router.delete(
|
||||||
'/:id/permanent',
|
'/:id/permanent',
|
||||||
authenticate,
|
authenticate,
|
||||||
requirePermission('kalender:manage_bookings'),
|
requirePermission('fahrzeugbuchungen:manage'),
|
||||||
buchungskategorieController.remove.bind(buchungskategorieController)
|
buchungskategorieController.remove.bind(buchungskategorieController)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ const DEFAULT_GROUP_HIERARCHY: Record<string, string[]> = {
|
|||||||
|
|
||||||
const DEFAULT_PERMISSION_DEPS: Record<string, string[]> = {
|
const DEFAULT_PERMISSION_DEPS: Record<string, string[]> = {
|
||||||
'kalender:create': ['kalender:view'],
|
'kalender:create': ['kalender:view'],
|
||||||
'kalender:view_bookings': ['kalender:view'],
|
|
||||||
'kalender:manage_bookings': ['kalender:view', 'kalender:view_bookings'],
|
|
||||||
'kalender:widget_events': ['kalender:view'],
|
'kalender:widget_events': ['kalender:view'],
|
||||||
'kalender:widget_bookings': ['kalender:view'],
|
|
||||||
'kalender:widget_quick_add': ['kalender:view', 'kalender:create'],
|
'kalender:widget_quick_add': ['kalender:view', 'kalender:create'],
|
||||||
|
'fahrzeugbuchungen:create': ['fahrzeugbuchungen:view'],
|
||||||
|
'fahrzeugbuchungen:manage': ['fahrzeugbuchungen:view', 'fahrzeugbuchungen:create'],
|
||||||
|
'fahrzeugbuchungen:widget': ['fahrzeugbuchungen:view'],
|
||||||
'fahrzeuge:create': ['fahrzeuge:view'],
|
'fahrzeuge:create': ['fahrzeuge:view'],
|
||||||
'fahrzeuge:change_status': ['fahrzeuge:view'],
|
'fahrzeuge:change_status': ['fahrzeuge:view'],
|
||||||
'fahrzeuge:manage_maintenance': ['fahrzeuge:view'],
|
'fahrzeuge:manage_maintenance': ['fahrzeuge:view'],
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import {
|
|||||||
ExpandLess,
|
ExpandLess,
|
||||||
LocalShipping,
|
LocalShipping,
|
||||||
BugReport,
|
BugReport,
|
||||||
|
BookOnline,
|
||||||
} from '@mui/icons-material';
|
} from '@mui/icons-material';
|
||||||
import { useNavigate, useLocation } from 'react-router-dom';
|
import { useNavigate, useLocation } from 'react-router-dom';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
@@ -49,11 +50,6 @@ interface NavigationItem {
|
|||||||
permission?: string;
|
permission?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const kalenderSubItems: SubItem[] = [
|
|
||||||
{ text: 'Veranstaltungen', path: '/kalender' },
|
|
||||||
{ text: 'Fahrzeugbuchungen', path: '/fahrzeugbuchungen' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const adminSubItems: SubItem[] = [
|
const adminSubItems: SubItem[] = [
|
||||||
{ text: 'Services', path: '/admin?tab=0' },
|
{ text: 'Services', path: '/admin?tab=0' },
|
||||||
{ text: 'System', path: '/admin?tab=1' },
|
{ text: 'System', path: '/admin?tab=1' },
|
||||||
@@ -77,9 +73,14 @@ const baseNavigationItems: NavigationItem[] = [
|
|||||||
text: 'Kalender',
|
text: 'Kalender',
|
||||||
icon: <CalendarMonth />,
|
icon: <CalendarMonth />,
|
||||||
path: '/kalender',
|
path: '/kalender',
|
||||||
subItems: kalenderSubItems,
|
|
||||||
permission: 'kalender:view',
|
permission: 'kalender:view',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
text: 'Fahrzeugbuchungen',
|
||||||
|
icon: <BookOnline />,
|
||||||
|
path: '/fahrzeugbuchungen',
|
||||||
|
permission: 'fahrzeugbuchungen:view',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
text: 'Fahrzeuge',
|
text: 'Fahrzeuge',
|
||||||
icon: <DirectionsCar />,
|
icon: <DirectionsCar />,
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ function Dashboard() {
|
|||||||
</Fade>
|
</Fade>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{hasPermission('kalender:view_bookings') && widgetVisible('vehicleBookingList') && (
|
{hasPermission('fahrzeugbuchungen:view') && widgetVisible('vehicleBookingList') && (
|
||||||
<Fade in={!dataLoading} timeout={600} style={{ transitionDelay: '520ms' }}>
|
<Fade in={!dataLoading} timeout={600} style={{ transitionDelay: '520ms' }}>
|
||||||
<Box>
|
<Box>
|
||||||
<VehicleBookingListWidget />
|
<VehicleBookingListWidget />
|
||||||
@@ -178,7 +178,7 @@ function Dashboard() {
|
|||||||
</Fade>
|
</Fade>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{hasPermission('kalender:manage_bookings') && widgetVisible('vehicleBooking') && (
|
{hasPermission('fahrzeugbuchungen:manage') && widgetVisible('vehicleBooking') && (
|
||||||
<Fade in={!dataLoading} timeout={600} style={{ transitionDelay: '560ms' }}>
|
<Fade in={!dataLoading} timeout={600} style={{ transitionDelay: '560ms' }}>
|
||||||
<Box>
|
<Box>
|
||||||
<VehicleBookingQuickAddWidget />
|
<VehicleBookingQuickAddWidget />
|
||||||
|
|||||||
@@ -98,8 +98,8 @@ function FahrzeugBuchungen() {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
const canCreate = hasPermission('kalender:create');
|
const canCreate = hasPermission('fahrzeugbuchungen:create');
|
||||||
const canManage = hasPermission('kalender:manage_bookings');
|
const canManage = hasPermission('fahrzeugbuchungen:manage');
|
||||||
|
|
||||||
const [tabIndex, setTabIndex] = useState(0);
|
const [tabIndex, setTabIndex] = useState(0);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user