new features
This commit is contained in:
@@ -20,6 +20,7 @@ import { requirePermission } from '../middleware/rbac.middleware';
|
||||
import { auditExport } from '../middleware/audit.middleware';
|
||||
import auditService, { AuditAction, AuditResourceType, AuditFilters } from '../services/audit.service';
|
||||
import cleanupService from '../services/cleanup.service';
|
||||
import pool from '../config/database';
|
||||
import logger from '../utils/logger';
|
||||
|
||||
const router = Router();
|
||||
@@ -264,4 +265,64 @@ router.delete(
|
||||
}
|
||||
);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// DELETE /api/admin/users/:userId/sync-data — selective sync data deletion
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const syncDataBodySchema = z.object({
|
||||
types: z.array(z.enum(['profile', 'ausbildung', 'untersuchungen', 'fuehrerschein', 'befoerderungen'])).min(1),
|
||||
});
|
||||
|
||||
const SYNC_TABLE_MAP: Record<string, string> = {
|
||||
profile: 'mitglieder_profile',
|
||||
ausbildung: 'ausbildungen',
|
||||
untersuchungen: 'untersuchungen',
|
||||
fuehrerschein: 'fahrgenehmigungen',
|
||||
befoerderungen: 'befoerderungen',
|
||||
};
|
||||
|
||||
router.delete(
|
||||
'/users/:userId/sync-data',
|
||||
authenticate,
|
||||
requirePermission('admin:write'),
|
||||
async (req: Request, res: Response): Promise<void> => {
|
||||
try {
|
||||
const userId = req.params.userId;
|
||||
const { types } = syncDataBodySchema.parse(req.body);
|
||||
|
||||
const client = await pool.connect();
|
||||
try {
|
||||
await client.query('BEGIN');
|
||||
const results: Record<string, number> = {};
|
||||
|
||||
for (const type of types) {
|
||||
const table = SYNC_TABLE_MAP[type];
|
||||
if (!table) continue;
|
||||
const result = await client.query(
|
||||
`DELETE FROM ${table} WHERE user_id = $1`,
|
||||
[userId]
|
||||
);
|
||||
results[type] = result.rowCount ?? 0;
|
||||
}
|
||||
|
||||
await client.query('COMMIT');
|
||||
logger.info('Admin deleted sync data', { userId, types, results, admin: req.user?.id });
|
||||
res.json({ success: true, data: results });
|
||||
} catch (error) {
|
||||
await client.query('ROLLBACK');
|
||||
throw error;
|
||||
} finally {
|
||||
client.release();
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
res.status(400).json({ success: false, message: 'Invalid parameters', errors: error.issues });
|
||||
return;
|
||||
}
|
||||
logger.error('Failed to delete sync data', { error, userId: req.params.userId });
|
||||
res.status(500).json({ success: false, message: 'Fehler beim Löschen der Sync-Daten' });
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -22,8 +22,8 @@ router.get('/:id/status-history', authenticate, equipmentController.getStatusHi
|
||||
router.post('/', authenticate, requirePermission('ausruestung:create'), equipmentController.createEquipment.bind(equipmentController));
|
||||
router.patch('/:id', authenticate, requirePermission('ausruestung:create'), equipmentController.updateEquipment.bind(equipmentController));
|
||||
router.patch('/:id/status', authenticate, requirePermission('ausruestung:create'), equipmentController.updateStatus.bind(equipmentController));
|
||||
router.post('/:id/wartung', authenticate, requirePermission('ausruestung:create'), equipmentController.addWartung.bind(equipmentController));
|
||||
router.post('/wartung/:wartungId/upload', authenticate, requirePermission('ausruestung:create'), uploadWartung.single('datei'), equipmentController.uploadWartungFile.bind(equipmentController));
|
||||
router.post('/:id/wartung', authenticate, requirePermission('ausruestung:manage_maintenance'), equipmentController.addWartung.bind(equipmentController));
|
||||
router.post('/wartung/:wartungId/upload', authenticate, requirePermission('ausruestung:manage_maintenance'), uploadWartung.single('datei'), equipmentController.uploadWartungFile.bind(equipmentController));
|
||||
|
||||
// ── Delete — admin only ──────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ const router = Router();
|
||||
|
||||
// ── User-facing (any authenticated user) ──────────────────────────────────
|
||||
router.get('/me', authenticate, permissionController.getMyPermissions.bind(permissionController));
|
||||
router.get('/users-with', authenticate, permissionController.getUsersWithPermission.bind(permissionController));
|
||||
|
||||
// ── Admin-only routes ─────────────────────────────────────────────────────
|
||||
router.get('/admin/matrix', authenticate, requirePermission('admin:view'), permissionController.getMatrix.bind(permissionController));
|
||||
|
||||
@@ -25,7 +25,7 @@ router.delete('/:id', authenticate, requirePermission('fahrzeuge:delete'), vehic
|
||||
// ── Status + maintenance log — gruppenfuehrer+ ──────────────────────────────
|
||||
|
||||
router.patch('/:id/status', authenticate, requirePermission('fahrzeuge:change_status'), vehicleController.updateVehicleStatus.bind(vehicleController));
|
||||
router.post('/:id/wartung', authenticate, requirePermission('fahrzeuge:change_status'), vehicleController.addWartung.bind(vehicleController));
|
||||
router.post('/wartung/:wartungId/upload', authenticate, requirePermission('fahrzeuge:change_status'), uploadWartung.single('datei'), vehicleController.uploadWartungFile.bind(vehicleController));
|
||||
router.post('/:id/wartung', authenticate, requirePermission('fahrzeuge:manage_maintenance'), vehicleController.addWartung.bind(vehicleController));
|
||||
router.post('/wartung/:wartungId/upload', authenticate, requirePermission('fahrzeuge:manage_maintenance'), uploadWartung.single('datei'), vehicleController.uploadWartungFile.bind(vehicleController));
|
||||
|
||||
export default router;
|
||||
|
||||
Reference in New Issue
Block a user