tractatus/src/routes/newsletter.routes.js
TheFlow 059dd43b72 security: complete Phase 0 Quick Wins implementation
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
2025-10-14 15:32:54 +13:00

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;