feat: rate-limiting

Signed-off-by: Erik Michelson <github@erik.michelson.eu>
This commit is contained in:
Erik Michelson 2024-12-11 17:39:45 +01:00
parent e8f4cbabec
commit beea1c71ce
No known key found for this signature in database
GPG key ID: DB99ADDDC5C0AF82
10 changed files with 70 additions and 6 deletions

View file

@ -9,6 +9,7 @@ const models = require('../../../models')
const logger = require('../../../logger')
const { urlencodedParser } = require('../../utils')
const errors = require('../../../errors')
const rateLimit = require('../../middleware/rateLimit')
const emailAuth = module.exports = Router()
@ -37,7 +38,7 @@ passport.use(new LocalStrategy({
}))
if (config.allowEmailRegister) {
emailAuth.post('/register', urlencodedParser, function (req, res, next) {
emailAuth.post('/register', rateLimit.userEndpoints, urlencodedParser, function (req, res, next) {
if (!req.body.email || !req.body.password) return errors.errorBadRequest(res)
if (!validator.isEmail(req.body.email)) return errors.errorBadRequest(res)
models.User.findOrCreate({
@ -67,7 +68,7 @@ if (config.allowEmailRegister) {
})
}
emailAuth.post('/login', urlencodedParser, function (req, res, next) {
emailAuth.post('/login', rateLimit.userEndpoints, urlencodedParser, function (req, res, next) {
if (!req.body.email || !req.body.password) return errors.errorBadRequest(res)
if (!validator.isEmail(req.body.email)) return errors.errorBadRequest(res)
passport.authenticate('local', {

View file

@ -0,0 +1,33 @@
'use strict'
const { rateLimit } = require('express-rate-limit')
const errors = require('../../errors')
const config = require('../../config')
const determineKey = (req) => {
if (req.user) {
return req.user.id
}
return req.header('cf-connecting-ip') || req.ip
}
// limits requests to user endpoints (login, signup) to 10 requests per 5 minutes
const userEndpoints = rateLimit({
windowMs: 5 * 60 * 1000,
limit: 10,
keyGenerator: determineKey,
handler: (req, res) => errors.errorTooManyRequests(res)
})
// limits the amount of requests to the new note endpoint per 5 minutes based on configuration
const newNotes = rateLimit({
windowMs: 5 * 60 * 1000,
limit: config.rateLimitNewNotes,
keyGenerator: determineKey,
handler: (req, res) => errors.errorTooManyRequests(res)
})
module.exports = {
userEndpoints,
newNotes
}

View file

@ -7,13 +7,22 @@ const router = module.exports = Router()
const noteController = require('./controller')
const slide = require('./slide')
const rateLimit = require('../middleware/rateLimit')
const config = require('../../config')
const applyRateLimitIfConfigured = (req, res, next) => {
if (config.rateLimitNewNotes > 0) {
return rateLimit.newNotes(req, res, next)
}
next()
}
// get new note
router.get('/new', noteController.createFromPOST)
router.get('/new', applyRateLimitIfConfigured, noteController.createFromPOST)
// post new note with content
router.post('/new', markdownParser, noteController.createFromPOST)
router.post('/new', applyRateLimitIfConfigured, markdownParser, noteController.createFromPOST)
// post new note with content and alias
router.post('/new/:noteId', markdownParser, noteController.createFromPOST)
router.post('/new/:noteId', applyRateLimitIfConfigured, markdownParser, noteController.createFromPOST)
// get publish note
router.get('/s/:shortid', noteController.showPublishNote)
// publish note actions