rate-limiter.ts 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. import express from 'express'
  2. import RateLimit, { Options as RateLimitHandlerOptions } from 'express-rate-limit'
  3. import { UserRole, UserRoleType } from '@peertube/peertube-models'
  4. import { CONFIG } from '@server/initializers/config.js'
  5. import { RunnerModel } from '@server/models/runner/runner.js'
  6. import { optionalAuthenticate } from './auth.js'
  7. const whitelistRoles = new Set<UserRoleType>([ UserRole.ADMINISTRATOR, UserRole.MODERATOR ])
  8. export function buildRateLimiter (options: {
  9. windowMs: number
  10. max: number
  11. skipFailedRequests?: boolean
  12. }) {
  13. return RateLimit({
  14. windowMs: options.windowMs,
  15. max: options.max,
  16. skipFailedRequests: options.skipFailedRequests,
  17. handler: (req, res, next, options) => {
  18. // Bypass rate limit for registered runners
  19. if (req.body?.runnerToken) {
  20. return RunnerModel.loadByToken(req.body.runnerToken)
  21. .then(runner => {
  22. if (runner) return next()
  23. return sendRateLimited(res, options)
  24. })
  25. }
  26. // Bypass rate limit for admins/moderators
  27. return optionalAuthenticate(req, res, () => {
  28. if (res.locals.authenticated === true && whitelistRoles.has(res.locals.oauth.token.User.role)) {
  29. return next()
  30. }
  31. return sendRateLimited(res, options)
  32. })
  33. }
  34. })
  35. }
  36. export const apiRateLimiter = buildRateLimiter({
  37. windowMs: CONFIG.RATES_LIMIT.API.WINDOW_MS,
  38. max: CONFIG.RATES_LIMIT.API.MAX
  39. })
  40. export const activityPubRateLimiter = buildRateLimiter({
  41. windowMs: CONFIG.RATES_LIMIT.ACTIVITY_PUB.WINDOW_MS,
  42. max: CONFIG.RATES_LIMIT.ACTIVITY_PUB.MAX
  43. })
  44. // ---------------------------------------------------------------------------
  45. // Private
  46. // ---------------------------------------------------------------------------
  47. function sendRateLimited (res: express.Response, options: RateLimitHandlerOptions) {
  48. return res.status(options.statusCode).send(options.message)
  49. }