feat: implement dynamic rate limiting with database configuration
Mirror to GitHub / mirror (push) Successful in 21s
Test and Lint / backend-test (push) Successful in 1m10s
continuous-integration/drone/push Build is passing
Test and Lint / frontend-test (push) Successful in 2m8s
Version and Release / version-bump (push) Successful in 34s
Version and Release / trigger-drone (push) Successful in 3s

- Add database migration for rate limit settings
- Create rate limit service with dynamic configuration from database
- Implement proper authentication detection for admin and gallery tokens
- Skip rate limiting for authenticated users (configurable)
- Add admin API endpoint to update rate limit settings
- Use correct client IP detection with proxy support
- Cache settings for performance (1 minute cache)
- Default to 1000 requests per 15 minutes for better UX
- Apply auth-specific limits only to login endpoints

Key improvements:
- No more rate limiting for authenticated gallery/admin users
- Configurable via admin settings page
- Immediate effect when settings change
- Better handling of proxied requests

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-07-17 08:43:00 +02:00
parent 8cbe97d2f4
commit 9d0607f4f0
5 changed files with 394 additions and 83 deletions
+65
View File
@@ -7,6 +7,7 @@ const { db, logActivity } = require('../database/db');
const { formatBoolean } = require('../utils/dbCompat');
const { adminAuth } = require('../middleware/auth');
const { clearMaintenanceCache } = require('../middleware/maintenance');
const { clearSettingsCache } = require('../services/rateLimitService');
const router = express.Router();
// Configure multer for logo uploads
@@ -582,4 +583,68 @@ router.post('/favicon', adminAuth, faviconUpload.single('favicon'), async (req,
}
});
// Update rate limit settings
router.put('/security/rate-limit', adminAuth, [
body('rate_limit_enabled').isBoolean().withMessage('Enabled must be a boolean'),
body('rate_limit_window_minutes').isInt({ min: 1, max: 60 }).withMessage('Window must be between 1 and 60 minutes'),
body('rate_limit_max_requests').isInt({ min: 10, max: 10000 }).withMessage('Max requests must be between 10 and 10000'),
body('rate_limit_auth_max_requests').isInt({ min: 1, max: 100 }).withMessage('Auth max requests must be between 1 and 100'),
body('rate_limit_skip_authenticated').isBoolean().withMessage('Skip authenticated must be a boolean'),
body('rate_limit_public_endpoints_only').isBoolean().withMessage('Public endpoints only must be a boolean')
], async (req, res) => {
try {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const {
rate_limit_enabled,
rate_limit_window_minutes,
rate_limit_max_requests,
rate_limit_auth_max_requests,
rate_limit_skip_authenticated,
rate_limit_public_endpoints_only
} = req.body;
// Update each setting
const settings = [
{ key: 'rate_limit_enabled', value: rate_limit_enabled },
{ key: 'rate_limit_window_minutes', value: rate_limit_window_minutes },
{ key: 'rate_limit_max_requests', value: rate_limit_max_requests },
{ key: 'rate_limit_auth_max_requests', value: rate_limit_auth_max_requests },
{ key: 'rate_limit_skip_authenticated', value: rate_limit_skip_authenticated },
{ key: 'rate_limit_public_endpoints_only', value: rate_limit_public_endpoints_only }
];
for (const { key, value } of settings) {
await db('app_settings')
.where('setting_key', key)
.update({
setting_value: JSON.stringify(value),
updated_at: new Date()
});
}
// Clear the rate limit settings cache to apply changes immediately
clearSettingsCache();
// Log activity
await logActivity('settings_updated',
{
category: 'security',
subcategory: 'rate_limit',
changes: settings.length
},
null,
{ type: 'admin', id: req.admin.id, name: req.admin.username }
);
res.json({ message: 'Rate limit settings updated successfully' });
} catch (error) {
console.error('Rate limit settings update error:', error);
res.status(500).json({ error: 'Failed to update rate limit settings' });
}
});
module.exports = router;