Files
picpeak/backend/src/routes/adminEventRename.js
T
Paul Nothaft 892e47d017 feat: add multi-administrator support with RBAC and fix backup/restore for S3
## Multi-Administrator System
- Add role-based access control (RBAC) with predefined roles (Super Admin, Admin, Editor, Viewer)
- Add granular permissions system for all admin operations
- Add admin user management page with invite functionality
- Add email invitation system for new administrators
- Add permission middleware protecting all admin routes
- Add PermissionGate component for frontend permission checks
- Track event creator (created_by) for audit purposes

## Backup & Restore Fixes
- Fix S3 backup: endpoint URL handling, manifest loading, field name compatibility
- Fix S3 restore: add list-backups endpoint, transform S3 config from frontend format
- Fix PostgreSQL compatibility: add .returning('id') for insert operations
- Fix disk space check: use df command, handle unknown space gracefully
- Fix dry-run validation to not block on warnings
- Fix req.user → req.admin in restore routes

## Database Migrations
- 054: Add roles table with predefined roles
- 055: Add permissions table
- 056: Add role_permissions junction table
- 057: Add role_id to admin_users
- 058: Add admin_invitations table
- 059: Add admin email templates
- 060: Add created_by to events table

## Other Improvements
- Update .gitignore to exclude planning docs and local backup directory
- Remove SQLite database file from tracking
- Add i18n translations for user management (EN/DE)
2026-01-07 17:10:46 +01:00

90 lines
2.4 KiB
JavaScript

/**
* Admin Event Rename Routes
* Handles event renaming operations
*/
const express = require('express');
const { body, validationResult } = require('express-validator');
const { adminAuth } = require('../middleware/auth');
const { requirePermission } = require('../middleware/permissions');
const eventRenameService = require('../services/eventRenameService');
const router = express.Router();
/**
* POST /api/admin/events/:eventId/rename
* Rename an event
*/
router.post('/:eventId/rename', adminAuth, requirePermission('events.edit'), [
body('newEventName')
.trim()
.isLength({ min: 3, max: 100 })
.withMessage('Event name must be between 3 and 100 characters'),
body('resendEmail')
.optional()
.isBoolean()
.withMessage('resendEmail must be a boolean')
], async (req, res) => {
try {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ success: false, errors: errors.array() });
}
const { eventId } = req.params;
const { newEventName, resendEmail = false } = req.body;
const result = await eventRenameService.renameEvent(
parseInt(eventId, 10),
newEventName,
resendEmail,
req.admin
);
if (!result.success) {
return res.status(400).json(result);
}
res.json({
success: true,
message: 'Event renamed successfully',
data: result.data
});
} catch (error) {
console.error('Error renaming event:', error);
res.status(500).json({ success: false, error: 'Failed to rename event' });
}
});
/**
* POST /api/admin/events/:eventId/validate-rename
* Validate a potential rename without executing it
*/
router.post('/:eventId/validate-rename', adminAuth, requirePermission('events.edit'), [
body('newEventName')
.trim()
.isLength({ min: 3, max: 100 })
.withMessage('Event name must be between 3 and 100 characters')
], async (req, res) => {
try {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ valid: false, errors: errors.array() });
}
const { eventId } = req.params;
const { newEventName } = req.body;
const validation = await eventRenameService.validateRename(
parseInt(eventId, 10),
newEventName
);
res.json(validation);
} catch (error) {
console.error('Error validating rename:', error);
res.status(500).json({ valid: false, error: 'Validation failed' });
}
});
module.exports = router;