Phase 0 Complete (QW-1 through QW-8): ✅ Enhanced input validation with HTML sanitization ✅ Form rate limiting (5 req/min on all submission endpoints) ✅ Modern CSRF protection (SameSite cookies + double-submit pattern) ✅ Security audit logging (CSRF violations captured) ✅ Applied to all public form endpoints: - /api/cases/submit (case studies) - /api/media/inquiries (media inquiries) - /api/newsletter/subscribe (newsletter) New Middleware: - csrf-protection.middleware.js (replaces deprecated csurf package) - Enhanced input-validation.middleware.js applied to all forms Security Features Active: - Security headers (CSP, HSTS, X-Frame-Options, etc.) - Rate limiting (100 req/15min public, 5 req/min forms) - CSRF protection (double-submit cookie pattern) - HTML sanitization (XSS prevention) - Response sanitization (hide stack traces) - Security event logging Implements: inst_041, inst_042, inst_043, inst_044, inst_045, inst_046 Refs: docs/plans/security-implementation-roadmap.md Phase 0
84 lines
2.6 KiB
JavaScript
84 lines
2.6 KiB
JavaScript
/**
|
|
* Newsletter Routes
|
|
* Public subscription management and admin endpoints
|
|
*/
|
|
|
|
const express = require('express');
|
|
const router = express.Router();
|
|
|
|
const newsletterController = require('../controllers/newsletter.controller');
|
|
const { authenticateToken, requireRole } = require('../middleware/auth.middleware');
|
|
const { validateRequired } = require('../middleware/validation.middleware');
|
|
const { asyncHandler } = require('../middleware/error.middleware');
|
|
const { createInputValidationMiddleware } = require('../middleware/input-validation.middleware');
|
|
const { formRateLimiter } = require('../middleware/rate-limit.middleware');
|
|
const { csrfProtection } = require('../middleware/csrf-protection.middleware');
|
|
|
|
/**
|
|
* Public Routes
|
|
*/
|
|
|
|
// Validation schema for newsletter subscription
|
|
const newsletterSubscribeSchema = {
|
|
'email': { required: true, type: 'email', maxLength: 254 },
|
|
'name': { required: false, type: 'name', maxLength: 100 }
|
|
};
|
|
|
|
// POST /api/newsletter/subscribe - Subscribe to newsletter
|
|
router.post('/subscribe',
|
|
formRateLimiter, // 5 requests per minute
|
|
csrfProtection, // CSRF validation
|
|
createInputValidationMiddleware(newsletterSubscribeSchema),
|
|
validateRequired(['email']),
|
|
asyncHandler(newsletterController.subscribe)
|
|
);
|
|
|
|
// GET /api/newsletter/verify/:token - Verify email subscription
|
|
router.get('/verify/:token',
|
|
asyncHandler(newsletterController.verify)
|
|
);
|
|
|
|
// POST /api/newsletter/unsubscribe - Unsubscribe from newsletter
|
|
router.post('/unsubscribe',
|
|
asyncHandler(newsletterController.unsubscribe)
|
|
);
|
|
|
|
// PUT /api/newsletter/preferences - Update subscription preferences
|
|
router.put('/preferences',
|
|
validateRequired(['email']),
|
|
asyncHandler(newsletterController.updatePreferences)
|
|
);
|
|
|
|
/**
|
|
* Admin Routes (require authentication)
|
|
*/
|
|
|
|
// GET /api/newsletter/admin/stats - Get newsletter statistics
|
|
router.get('/admin/stats',
|
|
authenticateToken,
|
|
requireRole('admin', 'moderator'),
|
|
asyncHandler(newsletterController.getStats)
|
|
);
|
|
|
|
// GET /api/newsletter/admin/subscriptions - List all subscriptions
|
|
router.get('/admin/subscriptions',
|
|
authenticateToken,
|
|
requireRole('admin', 'moderator'),
|
|
asyncHandler(newsletterController.listSubscriptions)
|
|
);
|
|
|
|
// GET /api/newsletter/admin/export - Export subscriptions as CSV
|
|
router.get('/admin/export',
|
|
authenticateToken,
|
|
requireRole('admin'),
|
|
asyncHandler(newsletterController.exportSubscriptions)
|
|
);
|
|
|
|
// DELETE /api/newsletter/admin/subscriptions/:id - Delete subscription
|
|
router.delete('/admin/subscriptions/:id',
|
|
authenticateToken,
|
|
requireRole('admin'),
|
|
asyncHandler(newsletterController.deleteSubscription)
|
|
);
|
|
|
|
module.exports = router;
|