]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - server/middlewares/rate-limiter.ts
Fix runner api rate limit bypass
[github/Chocobozzz/PeerTube.git] / server / middlewares / rate-limiter.ts
index bc95139693192d8d25811031c56d970482169307..8257965dd35d2c3a449f428bf92bb70e0af6e804 100644 (file)
@@ -1,10 +1,13 @@
+import express from 'express'
+import RateLimit, { Options as RateLimitHandlerOptions } from 'express-rate-limit'
+import { CONFIG } from '@server/initializers/config'
+import { RunnerModel } from '@server/models/runner/runner'
 import { UserRole } from '@shared/models'
-import RateLimit from 'express-rate-limit'
 import { optionalAuthenticate } from './auth'
 
 const whitelistRoles = new Set([ UserRole.ADMINISTRATOR, UserRole.MODERATOR ])
 
-function buildRateLimiter (options: {
+export function buildRateLimiter (options: {
   windowMs: number
   max: number
   skipFailedRequests?: boolean
@@ -15,17 +18,37 @@ function buildRateLimiter (options: {
     skipFailedRequests: options.skipFailedRequests,
 
     handler: (req, res, next, options) => {
+      // Bypass rate limit for registered runners
+      if (req.body?.runnerToken) {
+        return RunnerModel.loadByToken(req.body.runnerToken)
+          .then(runner => {
+            if (runner) return next()
+
+            return sendRateLimited(res, options)
+          })
+      }
+
+      // Bypass rate limit for admins/moderators
       return optionalAuthenticate(req, res, () => {
         if (res.locals.authenticated === true && whitelistRoles.has(res.locals.oauth.token.User.role)) {
           return next()
         }
 
-        return res.status(options.statusCode).send(options.message)
+        return sendRateLimited(res, options)
       })
     }
   })
 }
 
-export {
-  buildRateLimiter
+export const apiRateLimiter = buildRateLimiter({
+  windowMs: CONFIG.RATES_LIMIT.API.WINDOW_MS,
+  max: CONFIG.RATES_LIMIT.API.MAX
+})
+
+// ---------------------------------------------------------------------------
+// Private
+// ---------------------------------------------------------------------------
+
+function sendRateLimited (res: express.Response, options: RateLimitHandlerOptions) {
+  return res.status(options.statusCode).send(options.message)
 }