new features

This commit is contained in:
Matthias Hochmeister
2026-03-23 13:08:19 +01:00
parent 83b84664ce
commit 5032e1593b
41 changed files with 5157 additions and 40 deletions

View File

@@ -0,0 +1,189 @@
import { Router } from 'express';
import bestellungController from '../controllers/bestellung.controller';
import { authenticate } from '../middleware/auth.middleware';
import { requirePermission } from '../middleware/rbac.middleware';
import { uploadBestellung } from '../middleware/upload';
const router = Router();
// ---------------------------------------------------------------------------
// Vendors (Lieferanten)
// ---------------------------------------------------------------------------
router.get(
'/vendors',
authenticate,
requirePermission('bestellungen:view'),
bestellungController.listVendors.bind(bestellungController)
);
router.post(
'/vendors',
authenticate,
requirePermission('bestellungen:manage_vendors'),
bestellungController.createVendor.bind(bestellungController)
);
router.patch(
'/vendors/:id',
authenticate,
requirePermission('bestellungen:manage_vendors'),
bestellungController.updateVendor.bind(bestellungController)
);
router.delete(
'/vendors/:id',
authenticate,
requirePermission('bestellungen:manage_vendors'),
bestellungController.deleteVendor.bind(bestellungController)
);
// ---------------------------------------------------------------------------
// Orders (Bestellungen)
// ---------------------------------------------------------------------------
router.get(
'/',
authenticate,
requirePermission('bestellungen:view'),
bestellungController.listOrders.bind(bestellungController)
);
router.post(
'/',
authenticate,
requirePermission('bestellungen:create'),
bestellungController.createOrder.bind(bestellungController)
);
// Export must come before /:id to avoid param capture
router.get(
'/export/:id',
authenticate,
requirePermission('bestellungen:export'),
bestellungController.exportOrder.bind(bestellungController)
);
router.get(
'/:id',
authenticate,
requirePermission('bestellungen:view'),
bestellungController.getOrder.bind(bestellungController)
);
router.patch(
'/:id',
authenticate,
requirePermission('bestellungen:create'),
bestellungController.updateOrder.bind(bestellungController)
);
router.delete(
'/:id',
authenticate,
requirePermission('bestellungen:delete'),
bestellungController.deleteOrder.bind(bestellungController)
);
router.patch(
'/:id/status',
authenticate,
requirePermission('bestellungen:create'),
bestellungController.updateStatus.bind(bestellungController)
);
// ---------------------------------------------------------------------------
// Line Items (Bestellpositionen)
// ---------------------------------------------------------------------------
router.post(
'/:id/items',
authenticate,
requirePermission('bestellungen:create'),
bestellungController.addLineItem.bind(bestellungController)
);
router.patch(
'/items/:itemId',
authenticate,
requirePermission('bestellungen:create'),
bestellungController.updateLineItem.bind(bestellungController)
);
router.delete(
'/items/:itemId',
authenticate,
requirePermission('bestellungen:delete'),
bestellungController.deleteLineItem.bind(bestellungController)
);
router.patch(
'/items/:itemId/received',
authenticate,
requirePermission('bestellungen:create'),
bestellungController.updateReceivedQuantity.bind(bestellungController)
);
// ---------------------------------------------------------------------------
// Files (Bestellung Dateien)
// ---------------------------------------------------------------------------
router.post(
'/:id/files',
authenticate,
requirePermission('bestellungen:create'),
uploadBestellung.single('datei'),
bestellungController.uploadFile.bind(bestellungController)
);
router.delete(
'/files/:fileId',
authenticate,
requirePermission('bestellungen:delete'),
bestellungController.deleteFile.bind(bestellungController)
);
router.get(
'/:id/files',
authenticate,
requirePermission('bestellungen:view'),
bestellungController.listFiles.bind(bestellungController)
);
// ---------------------------------------------------------------------------
// Reminders (Erinnerungen)
// ---------------------------------------------------------------------------
router.post(
'/:id/reminders',
authenticate,
requirePermission('bestellungen:manage_reminders'),
bestellungController.addReminder.bind(bestellungController)
);
router.patch(
'/reminders/:remId',
authenticate,
requirePermission('bestellungen:manage_reminders'),
bestellungController.markReminderDone.bind(bestellungController)
);
router.delete(
'/reminders/:remId',
authenticate,
requirePermission('bestellungen:manage_reminders'),
bestellungController.deleteReminder.bind(bestellungController)
);
// ---------------------------------------------------------------------------
// History & Export
// ---------------------------------------------------------------------------
router.get(
'/:id/history',
authenticate,
requirePermission('bestellungen:view'),
bestellungController.getHistory.bind(bestellungController)
);
export default router;

View File

@@ -18,15 +18,15 @@ router.get('/calendar-token', authenticate, bookingController.getCalendarToken.b
// ── Write operations ──────────────────────────────────────────────────────────
router.post('/', authenticate, bookingController.create.bind(bookingController));
router.patch('/:id', authenticate, requirePermission('kalender:edit_bookings'), bookingController.update.bind(bookingController));
router.post('/', authenticate, requirePermission('kalender:manage_bookings'), bookingController.create.bind(bookingController));
router.patch('/:id', authenticate, requirePermission('kalender:manage_bookings'), bookingController.update.bind(bookingController));
// Soft-cancel (sets abgesagt=TRUE) — creator or bookings:write
router.delete('/:id', authenticate, bookingController.cancel.bind(bookingController));
router.patch('/:id/cancel', authenticate, bookingController.cancel.bind(bookingController));
// Hard-delete (admin only)
router.delete('/:id/force', authenticate, requirePermission('kalender:delete_bookings'), bookingController.hardDelete.bind(bookingController));
router.delete('/:id/force', authenticate, requirePermission('kalender:manage_bookings'), bookingController.hardDelete.bind(bookingController));
// ── Single booking read — after specific routes to avoid path conflicts ───────

View File

@@ -1,11 +1,12 @@
import { Router } from 'express';
import bookstackController from '../controllers/bookstack.controller';
import { authenticate } from '../middleware/auth.middleware';
import { requirePermission } from '../middleware/rbac.middleware';
const router = Router();
router.get('/recent', authenticate, bookstackController.getRecent.bind(bookstackController));
router.get('/search', authenticate, bookstackController.search.bind(bookstackController));
router.get('/pages/:id', authenticate, bookstackController.getPage.bind(bookstackController));
router.get('/recent', authenticate, requirePermission('wissen:view'), bookstackController.getRecent.bind(bookstackController));
router.get('/search', authenticate, requirePermission('wissen:view'), bookstackController.search.bind(bookstackController));
router.get('/pages/:id', authenticate, requirePermission('wissen:view'), bookstackController.getPage.bind(bookstackController));
export default router;

View File

@@ -22,7 +22,7 @@ router.get('/kategorien', authenticate, eventsController.listKategorien.bind(eve
router.post(
'/kategorien',
authenticate,
requirePermission('kalender:manage_categories'),
requirePermission('kalender:create'),
eventsController.createKategorie.bind(eventsController)
);
@@ -33,7 +33,7 @@ router.post(
router.patch(
'/kategorien/:id',
authenticate,
requirePermission('kalender:manage_categories'),
requirePermission('kalender:create'),
eventsController.updateKategorie.bind(eventsController)
);
@@ -44,7 +44,7 @@ router.patch(
router.delete(
'/kategorien/:id',
authenticate,
requirePermission('kalender:manage_categories'),
requirePermission('kalender:create'),
eventsController.deleteKategorie.bind(eventsController)
);

View File

@@ -0,0 +1,38 @@
import { Router } from 'express';
import shopController from '../controllers/shop.controller';
import { authenticate } from '../middleware/auth.middleware';
import { requirePermission } from '../middleware/rbac.middleware';
const router = Router();
// ---------------------------------------------------------------------------
// Catalog Items
// ---------------------------------------------------------------------------
router.get('/items', authenticate, requirePermission('shop:view'), shopController.getItems.bind(shopController));
router.get('/items/:id', authenticate, requirePermission('shop:view'), shopController.getItemById.bind(shopController));
router.post('/items', authenticate, requirePermission('shop:manage_catalog'), shopController.createItem.bind(shopController));
router.patch('/items/:id', authenticate, requirePermission('shop:manage_catalog'), shopController.updateItem.bind(shopController));
router.delete('/items/:id', authenticate, requirePermission('shop:manage_catalog'), shopController.deleteItem.bind(shopController));
router.get('/categories', authenticate, requirePermission('shop:view'), shopController.getCategories.bind(shopController));
// ---------------------------------------------------------------------------
// Requests
// ---------------------------------------------------------------------------
router.get('/requests', authenticate, requirePermission('shop:approve_requests'), shopController.getRequests.bind(shopController));
router.get('/requests/my', authenticate, shopController.getMyRequests.bind(shopController));
router.get('/requests/:id', authenticate, shopController.getRequestById.bind(shopController));
router.post('/requests', authenticate, requirePermission('shop:create_request'), shopController.createRequest.bind(shopController));
router.patch('/requests/:id/status', authenticate, requirePermission('shop:approve_requests'), shopController.updateRequestStatus.bind(shopController));
router.delete('/requests/:id', authenticate, requirePermission('shop:approve_requests'), shopController.deleteRequest.bind(shopController));
// ---------------------------------------------------------------------------
// Linking requests to orders
// ---------------------------------------------------------------------------
router.post('/requests/:id/link', authenticate, requirePermission('shop:link_orders'), shopController.linkToOrder.bind(shopController));
router.delete('/requests/:id/link/:bestellungId', authenticate, requirePermission('shop:link_orders'), shopController.unlinkFromOrder.bind(shopController));
export default router;

View File

@@ -1,12 +1,13 @@
import { Router } from 'express';
import vikunjaController from '../controllers/vikunja.controller';
import { authenticate } from '../middleware/auth.middleware';
import { requirePermission } from '../middleware/rbac.middleware';
const router = Router();
router.get('/tasks', authenticate, vikunjaController.getMyTasks.bind(vikunjaController));
router.get('/tasks', authenticate, requirePermission('vikunja:widget_tasks'), vikunjaController.getMyTasks.bind(vikunjaController));
router.get('/overdue', authenticate, vikunjaController.getOverdueTasks.bind(vikunjaController));
router.get('/projects', authenticate, vikunjaController.getProjects.bind(vikunjaController));
router.post('/tasks', authenticate, vikunjaController.createTask.bind(vikunjaController));
router.get('/projects', authenticate, requirePermission('vikunja:create_tasks'), vikunjaController.getProjects.bind(vikunjaController));
router.post('/tasks', authenticate, requirePermission('vikunja:create_tasks'), vikunjaController.createTask.bind(vikunjaController));
export default router;