Fix runner api rate limit bypass
This commit is contained in:
parent
923e41fa4f
commit
e915cde30e
26 changed files with 122 additions and 31 deletions
|
@ -16,6 +16,7 @@ import {
|
|||
abusesSortValidator,
|
||||
abuseUpdateValidator,
|
||||
addAbuseMessageValidator,
|
||||
apiRateLimiter,
|
||||
asyncMiddleware,
|
||||
asyncRetryTransactionMiddleware,
|
||||
authenticate,
|
||||
|
@ -32,6 +33,8 @@ import { AccountModel } from '../../models/account/account'
|
|||
|
||||
const abuseRouter = express.Router()
|
||||
|
||||
abuseRouter.use(apiRateLimiter)
|
||||
|
||||
abuseRouter.get('/',
|
||||
openapiOperationDoc({ operationId: 'getAbuses' }),
|
||||
authenticate,
|
||||
|
|
|
@ -9,6 +9,7 @@ import { getFormattedObjects } from '../../helpers/utils'
|
|||
import { JobQueue } from '../../lib/job-queue'
|
||||
import { Hooks } from '../../lib/plugins/hooks'
|
||||
import {
|
||||
apiRateLimiter,
|
||||
asyncMiddleware,
|
||||
authenticate,
|
||||
commonVideosFiltersValidator,
|
||||
|
@ -41,6 +42,8 @@ import { VideoPlaylistModel } from '../../models/video/video-playlist'
|
|||
|
||||
const accountsRouter = express.Router()
|
||||
|
||||
accountsRouter.use(apiRateLimiter)
|
||||
|
||||
accountsRouter.get('/',
|
||||
paginationValidator,
|
||||
accountsSortValidator,
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
import express from 'express'
|
||||
import { handleToNameAndHost } from '@server/helpers/actors'
|
||||
import { logger } from '@server/helpers/logger'
|
||||
import { AccountBlocklistModel } from '@server/models/account/account-blocklist'
|
||||
import { getServerActor } from '@server/models/application/application'
|
||||
import { ServerBlocklistModel } from '@server/models/server/server-blocklist'
|
||||
import { MActorAccountId, MUserAccountId } from '@server/types/models'
|
||||
import { BlockStatus } from '@shared/models'
|
||||
import { asyncMiddleware, blocklistStatusValidator, optionalAuthenticate } from '../../middlewares'
|
||||
import { logger } from '@server/helpers/logger'
|
||||
import { apiRateLimiter, asyncMiddleware, blocklistStatusValidator, optionalAuthenticate } from '../../middlewares'
|
||||
|
||||
const blocklistRouter = express.Router()
|
||||
|
||||
blocklistRouter.use(apiRateLimiter)
|
||||
|
||||
blocklistRouter.get('/status',
|
||||
optionalAuthenticate,
|
||||
blocklistStatusValidator,
|
||||
|
|
|
@ -4,10 +4,12 @@ import { bulkRemoveCommentsOfValidator } from '@server/middlewares/validators/bu
|
|||
import { VideoCommentModel } from '@server/models/video/video-comment'
|
||||
import { HttpStatusCode } from '@shared/models'
|
||||
import { BulkRemoveCommentsOfBody } from '@shared/models/bulk/bulk-remove-comments-of-body.model'
|
||||
import { asyncMiddleware, authenticate } from '../../middlewares'
|
||||
import { apiRateLimiter, asyncMiddleware, authenticate } from '../../middlewares'
|
||||
|
||||
const bulkRouter = express.Router()
|
||||
|
||||
bulkRouter.use(apiRateLimiter)
|
||||
|
||||
bulkRouter.post('/remove-comments-of',
|
||||
authenticate,
|
||||
asyncMiddleware(bulkRemoveCommentsOfValidator),
|
||||
|
|
|
@ -8,11 +8,13 @@ import { auditLoggerFactory, CustomConfigAuditView, getAuditIdFromRes } from '..
|
|||
import { objectConverter } from '../../helpers/core-utils'
|
||||
import { CONFIG, reloadConfig } from '../../initializers/config'
|
||||
import { ClientHtml } from '../../lib/client-html'
|
||||
import { asyncMiddleware, authenticate, ensureUserHasRight, openapiOperationDoc } from '../../middlewares'
|
||||
import { apiRateLimiter, asyncMiddleware, authenticate, ensureUserHasRight, openapiOperationDoc } from '../../middlewares'
|
||||
import { customConfigUpdateValidator, ensureConfigIsEditable } from '../../middlewares/validators/config'
|
||||
|
||||
const configRouter = express.Router()
|
||||
|
||||
configRouter.use(apiRateLimiter)
|
||||
|
||||
const auditLogger = auditLoggerFactory('config')
|
||||
|
||||
configRouter.get('/',
|
||||
|
|
|
@ -2,10 +2,12 @@ import express from 'express'
|
|||
import { ServerConfigManager } from '@server/lib/server-config-manager'
|
||||
import { ActorCustomPageModel } from '@server/models/account/actor-custom-page'
|
||||
import { HttpStatusCode, UserRight } from '@shared/models'
|
||||
import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../middlewares'
|
||||
import { apiRateLimiter, asyncMiddleware, authenticate, ensureUserHasRight } from '../../middlewares'
|
||||
|
||||
const customPageRouter = express.Router()
|
||||
|
||||
customPageRouter.use(apiRateLimiter)
|
||||
|
||||
customPageRouter.get('/homepage/instance',
|
||||
asyncMiddleware(getInstanceHomepage)
|
||||
)
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import cors from 'cors'
|
||||
import express from 'express'
|
||||
import { buildRateLimiter } from '@server/middlewares'
|
||||
|
||||
import { HttpStatusCode } from '../../../shared/models'
|
||||
import { badRequest } from '../../helpers/express-utils'
|
||||
import { CONFIG } from '../../initializers/config'
|
||||
import { abuseRouter } from './abuse'
|
||||
import { accountsRouter } from './accounts'
|
||||
import { blocklistRouter } from './blocklist'
|
||||
|
@ -32,12 +31,6 @@ apiRouter.use(cors({
|
|||
credentials: true
|
||||
}))
|
||||
|
||||
const apiRateLimiter = buildRateLimiter({
|
||||
windowMs: CONFIG.RATES_LIMIT.API.WINDOW_MS,
|
||||
max: CONFIG.RATES_LIMIT.API.MAX
|
||||
})
|
||||
apiRouter.use(apiRateLimiter)
|
||||
|
||||
apiRouter.use('/server', serverRouter)
|
||||
apiRouter.use('/abuses', abuseRouter)
|
||||
apiRouter.use('/bulk', bulkRouter)
|
||||
|
@ -57,6 +50,8 @@ apiRouter.use('/plugins', pluginRouter)
|
|||
apiRouter.use('/custom-pages', customPageRouter)
|
||||
apiRouter.use('/blocklist', blocklistRouter)
|
||||
apiRouter.use('/runners', runnersRouter)
|
||||
|
||||
// apiRouter.use(apiRateLimiter)
|
||||
apiRouter.use('/ping', pong)
|
||||
apiRouter.use('/*', badRequest)
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import { HttpStatusCode, Job, JobState, JobType, ResultList, UserRight } from '@
|
|||
import { isArray } from '../../helpers/custom-validators/misc'
|
||||
import { JobQueue } from '../../lib/job-queue'
|
||||
import {
|
||||
apiRateLimiter,
|
||||
asyncMiddleware,
|
||||
authenticate,
|
||||
ensureUserHasRight,
|
||||
|
@ -17,6 +18,8 @@ import { listJobsValidator } from '../../middlewares/validators/jobs'
|
|||
|
||||
const jobsRouter = express.Router()
|
||||
|
||||
jobsRouter.use(apiRateLimiter)
|
||||
|
||||
jobsRouter.post('/pause',
|
||||
authenticate,
|
||||
ensureUserHasRight(UserRight.MANAGE_JOBS),
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import express from 'express'
|
||||
import { CONFIG } from '@server/initializers/config'
|
||||
import { OpenTelemetryMetrics } from '@server/lib/opentelemetry/metrics'
|
||||
import { HttpStatusCode, PlaybackMetricCreate } from '@shared/models'
|
||||
import { addPlaybackMetricValidator, asyncMiddleware } from '../../middlewares'
|
||||
import { CONFIG } from '@server/initializers/config'
|
||||
import { addPlaybackMetricValidator, apiRateLimiter, asyncMiddleware } from '../../middlewares'
|
||||
|
||||
const metricsRouter = express.Router()
|
||||
|
||||
metricsRouter.use(apiRateLimiter)
|
||||
|
||||
metricsRouter.post('/playback',
|
||||
asyncMiddleware(addPlaybackMetricValidator),
|
||||
addPlaybackMetric
|
||||
|
|
|
@ -4,10 +4,12 @@ import { OAuthClientModel } from '@server/models/oauth/oauth-client'
|
|||
import { HttpStatusCode, OAuthClientLocal } from '@shared/models'
|
||||
import { logger } from '../../helpers/logger'
|
||||
import { CONFIG } from '../../initializers/config'
|
||||
import { asyncMiddleware, openapiOperationDoc } from '../../middlewares'
|
||||
import { apiRateLimiter, asyncMiddleware, openapiOperationDoc } from '../../middlewares'
|
||||
|
||||
const oauthClientsRouter = express.Router()
|
||||
|
||||
oauthClientsRouter.use(apiRateLimiter)
|
||||
|
||||
oauthClientsRouter.get('/local',
|
||||
openapiOperationDoc({ operationId: 'getOAuthClient' }),
|
||||
asyncMiddleware(getLocalClient)
|
||||
|
|
|
@ -2,16 +2,18 @@ import express from 'express'
|
|||
import memoizee from 'memoizee'
|
||||
import { logger } from '@server/helpers/logger'
|
||||
import { Hooks } from '@server/lib/plugins/hooks'
|
||||
import { getServerActor } from '@server/models/application/application'
|
||||
import { VideoModel } from '@server/models/video/video'
|
||||
import { CategoryOverview, ChannelOverview, TagOverview, VideosOverview } from '../../../shared/models/overviews'
|
||||
import { buildNSFWFilter } from '../../helpers/express-utils'
|
||||
import { MEMOIZE_TTL, OVERVIEWS } from '../../initializers/constants'
|
||||
import { asyncMiddleware, optionalAuthenticate, videosOverviewValidator } from '../../middlewares'
|
||||
import { apiRateLimiter, asyncMiddleware, optionalAuthenticate, videosOverviewValidator } from '../../middlewares'
|
||||
import { TagModel } from '../../models/video/tag'
|
||||
import { getServerActor } from '@server/models/application/application'
|
||||
|
||||
const overviewsRouter = express.Router()
|
||||
|
||||
overviewsRouter.use(apiRateLimiter)
|
||||
|
||||
overviewsRouter.get('/videos',
|
||||
videosOverviewValidator,
|
||||
optionalAuthenticate,
|
||||
|
|
|
@ -4,6 +4,7 @@ import { getFormattedObjects } from '@server/helpers/utils'
|
|||
import { listAvailablePluginsFromIndex } from '@server/lib/plugins/plugin-index'
|
||||
import { PluginManager } from '@server/lib/plugins/plugin-manager'
|
||||
import {
|
||||
apiRateLimiter,
|
||||
asyncMiddleware,
|
||||
authenticate,
|
||||
availablePluginsSortValidator,
|
||||
|
@ -35,6 +36,8 @@ import {
|
|||
|
||||
const pluginRouter = express.Router()
|
||||
|
||||
pluginRouter.use(apiRateLimiter)
|
||||
|
||||
pluginRouter.get('/available',
|
||||
openapiOperationDoc({ operationId: 'getAvailablePlugins' }),
|
||||
authenticate,
|
||||
|
|
|
@ -6,6 +6,8 @@ import { runnerRegistrationTokensRouter } from './registration-tokens'
|
|||
|
||||
const runnersRouter = express.Router()
|
||||
|
||||
// No api route limiter here, they are defined in child routers
|
||||
|
||||
runnersRouter.use('/', manageRunnersRouter)
|
||||
runnersRouter.use('/', runnerJobsRouter)
|
||||
runnersRouter.use('/', runnerJobFilesRouter)
|
||||
|
|
|
@ -3,7 +3,7 @@ import { logger, loggerTagsFactory } from '@server/helpers/logger'
|
|||
import { proxifyHLS, proxifyWebTorrentFile } from '@server/lib/object-storage'
|
||||
import { VideoPathManager } from '@server/lib/video-path-manager'
|
||||
import { getStudioTaskFilePath } from '@server/lib/video-studio'
|
||||
import { asyncMiddleware } from '@server/middlewares'
|
||||
import { apiRateLimiter, asyncMiddleware } from '@server/middlewares'
|
||||
import { jobOfRunnerGetValidator } from '@server/middlewares/validators/runners'
|
||||
import {
|
||||
runnerJobGetVideoStudioTaskFileValidator,
|
||||
|
@ -16,18 +16,21 @@ const lTags = loggerTagsFactory('api', 'runner')
|
|||
const runnerJobFilesRouter = express.Router()
|
||||
|
||||
runnerJobFilesRouter.post('/jobs/:jobUUID/files/videos/:videoId/max-quality',
|
||||
apiRateLimiter,
|
||||
asyncMiddleware(jobOfRunnerGetValidator),
|
||||
asyncMiddleware(runnerJobGetVideoTranscodingFileValidator),
|
||||
asyncMiddleware(getMaxQualityVideoFile)
|
||||
)
|
||||
|
||||
runnerJobFilesRouter.post('/jobs/:jobUUID/files/videos/:videoId/previews/max-quality',
|
||||
apiRateLimiter,
|
||||
asyncMiddleware(jobOfRunnerGetValidator),
|
||||
asyncMiddleware(runnerJobGetVideoTranscodingFileValidator),
|
||||
getMaxQualityVideoPreview
|
||||
)
|
||||
|
||||
runnerJobFilesRouter.post('/jobs/:jobUUID/files/videos/:videoId/studio/task-files/:filename',
|
||||
apiRateLimiter,
|
||||
asyncMiddleware(jobOfRunnerGetValidator),
|
||||
asyncMiddleware(runnerJobGetVideoTranscodingFileValidator),
|
||||
runnerJobGetVideoStudioTaskFileValidator,
|
||||
|
|
|
@ -7,6 +7,7 @@ import { MIMETYPES } from '@server/initializers/constants'
|
|||
import { sequelizeTypescript } from '@server/initializers/database'
|
||||
import { getRunnerJobHandlerClass, updateLastRunnerContact } from '@server/lib/runners'
|
||||
import {
|
||||
apiRateLimiter,
|
||||
asyncMiddleware,
|
||||
authenticate,
|
||||
ensureUserHasRight,
|
||||
|
@ -69,11 +70,13 @@ const runnerJobsRouter = express.Router()
|
|||
// ---------------------------------------------------------------------------
|
||||
|
||||
runnerJobsRouter.post('/jobs/request',
|
||||
apiRateLimiter,
|
||||
asyncMiddleware(getRunnerFromTokenValidator),
|
||||
asyncMiddleware(requestRunnerJob)
|
||||
)
|
||||
|
||||
runnerJobsRouter.post('/jobs/:jobUUID/accept',
|
||||
apiRateLimiter,
|
||||
asyncMiddleware(runnerJobGetValidator),
|
||||
acceptRunnerJobValidator,
|
||||
asyncMiddleware(getRunnerFromTokenValidator),
|
||||
|
@ -81,6 +84,7 @@ runnerJobsRouter.post('/jobs/:jobUUID/accept',
|
|||
)
|
||||
|
||||
runnerJobsRouter.post('/jobs/:jobUUID/abort',
|
||||
apiRateLimiter,
|
||||
asyncMiddleware(jobOfRunnerGetValidator),
|
||||
abortRunnerJobValidator,
|
||||
asyncMiddleware(abortRunnerJob)
|
||||
|
@ -88,6 +92,7 @@ runnerJobsRouter.post('/jobs/:jobUUID/abort',
|
|||
|
||||
runnerJobsRouter.post('/jobs/:jobUUID/update',
|
||||
runnerJobUpdateVideoFiles,
|
||||
apiRateLimiter, // Has to be after multer middleware to parse runner token
|
||||
asyncMiddleware(jobOfRunnerGetValidator),
|
||||
updateRunnerJobValidator,
|
||||
asyncMiddleware(updateRunnerJobController)
|
||||
|
@ -101,6 +106,7 @@ runnerJobsRouter.post('/jobs/:jobUUID/error',
|
|||
|
||||
runnerJobsRouter.post('/jobs/:jobUUID/success',
|
||||
postRunnerJobSuccessVideoFiles,
|
||||
apiRateLimiter, // Has to be after multer middleware to parse runner token
|
||||
asyncMiddleware(jobOfRunnerGetValidator),
|
||||
successRunnerJobValidator,
|
||||
asyncMiddleware(postRunnerJobSuccess)
|
||||
|
|
|
@ -2,6 +2,7 @@ import express from 'express'
|
|||
import { logger, loggerTagsFactory } from '@server/helpers/logger'
|
||||
import { generateRunnerToken } from '@server/helpers/token-generator'
|
||||
import {
|
||||
apiRateLimiter,
|
||||
asyncMiddleware,
|
||||
authenticate,
|
||||
ensureUserHasRight,
|
||||
|
@ -19,15 +20,18 @@ const lTags = loggerTagsFactory('api', 'runner')
|
|||
const manageRunnersRouter = express.Router()
|
||||
|
||||
manageRunnersRouter.post('/register',
|
||||
apiRateLimiter,
|
||||
asyncMiddleware(registerRunnerValidator),
|
||||
asyncMiddleware(registerRunner)
|
||||
)
|
||||
manageRunnersRouter.post('/unregister',
|
||||
apiRateLimiter,
|
||||
asyncMiddleware(getRunnerFromTokenValidator),
|
||||
asyncMiddleware(unregisterRunner)
|
||||
)
|
||||
|
||||
manageRunnersRouter.delete('/:runnerId',
|
||||
apiRateLimiter,
|
||||
authenticate,
|
||||
ensureUserHasRight(UserRight.MANAGE_RUNNERS),
|
||||
asyncMiddleware(deleteRunnerValidator),
|
||||
|
@ -35,6 +39,7 @@ manageRunnersRouter.delete('/:runnerId',
|
|||
)
|
||||
|
||||
manageRunnersRouter.get('/',
|
||||
apiRateLimiter,
|
||||
authenticate,
|
||||
ensureUserHasRight(UserRight.MANAGE_RUNNERS),
|
||||
paginationValidator,
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import express from 'express'
|
||||
import { logger, loggerTagsFactory } from '@server/helpers/logger'
|
||||
import { generateRunnerRegistrationToken } from '@server/helpers/token-generator'
|
||||
import {
|
||||
apiRateLimiter,
|
||||
asyncMiddleware,
|
||||
authenticate,
|
||||
ensureUserHasRight,
|
||||
|
@ -12,19 +14,20 @@ import {
|
|||
import { deleteRegistrationTokenValidator } from '@server/middlewares/validators/runners'
|
||||
import { RunnerRegistrationTokenModel } from '@server/models/runner/runner-registration-token'
|
||||
import { HttpStatusCode, ListRunnerRegistrationTokensQuery, UserRight } from '@shared/models'
|
||||
import { logger, loggerTagsFactory } from '@server/helpers/logger'
|
||||
|
||||
const lTags = loggerTagsFactory('api', 'runner')
|
||||
|
||||
const runnerRegistrationTokensRouter = express.Router()
|
||||
|
||||
runnerRegistrationTokensRouter.post('/registration-tokens/generate',
|
||||
apiRateLimiter,
|
||||
authenticate,
|
||||
ensureUserHasRight(UserRight.MANAGE_RUNNERS),
|
||||
asyncMiddleware(generateRegistrationToken)
|
||||
)
|
||||
|
||||
runnerRegistrationTokensRouter.delete('/registration-tokens/:id',
|
||||
apiRateLimiter,
|
||||
authenticate,
|
||||
ensureUserHasRight(UserRight.MANAGE_RUNNERS),
|
||||
asyncMiddleware(deleteRegistrationTokenValidator),
|
||||
|
@ -32,6 +35,7 @@ runnerRegistrationTokensRouter.delete('/registration-tokens/:id',
|
|||
)
|
||||
|
||||
runnerRegistrationTokensRouter.get('/registration-tokens',
|
||||
apiRateLimiter,
|
||||
authenticate,
|
||||
ensureUserHasRight(UserRight.MANAGE_RUNNERS),
|
||||
paginationValidator,
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
import express from 'express'
|
||||
import { apiRateLimiter } from '@server/middlewares'
|
||||
import { searchChannelsRouter } from './search-video-channels'
|
||||
import { searchPlaylistsRouter } from './search-video-playlists'
|
||||
import { searchVideosRouter } from './search-videos'
|
||||
|
||||
const searchRouter = express.Router()
|
||||
|
||||
searchRouter.use(apiRateLimiter)
|
||||
|
||||
searchRouter.use('/', searchVideosRouter)
|
||||
searchRouter.use('/', searchChannelsRouter)
|
||||
searchRouter.use('/', searchPlaylistsRouter)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import express from 'express'
|
||||
import { apiRateLimiter } from '@server/middlewares'
|
||||
import { contactRouter } from './contact'
|
||||
import { debugRouter } from './debug'
|
||||
import { serverFollowsRouter } from './follows'
|
||||
|
@ -9,6 +10,8 @@ import { statsRouter } from './stats'
|
|||
|
||||
const serverRouter = express.Router()
|
||||
|
||||
serverRouter.use(apiRateLimiter)
|
||||
|
||||
serverRouter.use('/', serverFollowsRouter)
|
||||
serverRouter.use('/', serverRedundancyRouter)
|
||||
serverRouter.use('/', statsRouter)
|
||||
|
|
|
@ -15,6 +15,7 @@ import { Redis } from '../../../lib/redis'
|
|||
import { buildUser, createUserAccountAndChannelAndPlaylist } from '../../../lib/user'
|
||||
import {
|
||||
adminUsersSortValidator,
|
||||
apiRateLimiter,
|
||||
asyncMiddleware,
|
||||
asyncRetryTransactionMiddleware,
|
||||
authenticate,
|
||||
|
@ -50,6 +51,9 @@ import { twoFactorRouter } from './two-factor'
|
|||
const auditLogger = auditLoggerFactory('users')
|
||||
|
||||
const usersRouter = express.Router()
|
||||
|
||||
usersRouter.use(apiRateLimiter)
|
||||
|
||||
usersRouter.use('/', emailVerificationRouter)
|
||||
usersRouter.use('/', registrationsRouter)
|
||||
usersRouter.use('/', twoFactorRouter)
|
||||
|
|
|
@ -2,6 +2,7 @@ import express from 'express'
|
|||
import { auditLoggerFactory, getAuditIdFromRes, VideoChannelSyncAuditView } from '@server/helpers/audit-logger'
|
||||
import { logger } from '@server/helpers/logger'
|
||||
import {
|
||||
apiRateLimiter,
|
||||
asyncMiddleware,
|
||||
asyncRetryTransactionMiddleware,
|
||||
authenticate,
|
||||
|
@ -17,6 +18,8 @@ import { HttpStatusCode, VideoChannelSyncState } from '@shared/models'
|
|||
const videoChannelSyncRouter = express.Router()
|
||||
const auditLogger = auditLoggerFactory('channel-syncs')
|
||||
|
||||
videoChannelSyncRouter.use(apiRateLimiter)
|
||||
|
||||
videoChannelSyncRouter.post('/',
|
||||
authenticate,
|
||||
ensureSyncIsEnabled,
|
||||
|
|
|
@ -19,6 +19,7 @@ import { JobQueue } from '../../lib/job-queue'
|
|||
import { deleteLocalActorImageFile, updateLocalActorImageFiles } from '../../lib/local-actor'
|
||||
import { createLocalVideoChannel, federateAllVideosOfChannel } from '../../lib/video-channel'
|
||||
import {
|
||||
apiRateLimiter,
|
||||
asyncMiddleware,
|
||||
asyncRetryTransactionMiddleware,
|
||||
authenticate,
|
||||
|
@ -57,6 +58,8 @@ const reqBannerFile = createReqFiles([ 'bannerfile' ], MIMETYPES.IMAGE.MIMETYPE_
|
|||
|
||||
const videoChannelRouter = express.Router()
|
||||
|
||||
videoChannelRouter.use(apiRateLimiter)
|
||||
|
||||
videoChannelRouter.get('/',
|
||||
paginationValidator,
|
||||
videoChannelsSortValidator,
|
||||
|
|
|
@ -25,6 +25,7 @@ import { sendCreateVideoPlaylist, sendDeleteVideoPlaylist, sendUpdateVideoPlayli
|
|||
import { getLocalVideoPlaylistActivityPubUrl, getLocalVideoPlaylistElementActivityPubUrl } from '../../lib/activitypub/url'
|
||||
import { updatePlaylistMiniatureFromExisting } from '../../lib/thumbnail'
|
||||
import {
|
||||
apiRateLimiter,
|
||||
asyncMiddleware,
|
||||
asyncRetryTransactionMiddleware,
|
||||
authenticate,
|
||||
|
@ -52,6 +53,8 @@ const reqThumbnailFile = createReqFiles([ 'thumbnailfile' ], MIMETYPES.IMAGE.MIM
|
|||
|
||||
const videoPlaylistRouter = express.Router()
|
||||
|
||||
videoPlaylistRouter.use(apiRateLimiter)
|
||||
|
||||
videoPlaylistRouter.get('/privacies', listVideoPlaylistPrivacies)
|
||||
|
||||
videoPlaylistRouter.get('/',
|
||||
|
|
|
@ -15,6 +15,7 @@ import { sequelizeTypescript } from '../../../initializers/database'
|
|||
import { JobQueue } from '../../../lib/job-queue'
|
||||
import { Hooks } from '../../../lib/plugins/hooks'
|
||||
import {
|
||||
apiRateLimiter,
|
||||
asyncMiddleware,
|
||||
asyncRetryTransactionMiddleware,
|
||||
authenticate,
|
||||
|
@ -50,6 +51,8 @@ import { viewRouter } from './view'
|
|||
const auditLogger = auditLoggerFactory('videos')
|
||||
const videosRouter = express.Router()
|
||||
|
||||
videosRouter.use(apiRateLimiter)
|
||||
|
||||
videosRouter.use('/', blacklistRouter)
|
||||
videosRouter.use('/', statsRouter)
|
||||
videosRouter.use('/', rateVideoRouter)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
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 { optionalAuthenticate } from './auth'
|
||||
|
@ -39,6 +40,11 @@ export function buildRateLimiter (options: {
|
|||
})
|
||||
}
|
||||
|
||||
export const apiRateLimiter = buildRateLimiter({
|
||||
windowMs: CONFIG.RATES_LIMIT.API.WINDOW_MS,
|
||||
max: CONFIG.RATES_LIMIT.API.MAX
|
||||
})
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Private
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
@ -14,7 +14,6 @@ import {
|
|||
import {
|
||||
cleanupTests,
|
||||
createSingleServer,
|
||||
makePostBodyRequest,
|
||||
PeerTubeServer,
|
||||
setAccessTokensToServers,
|
||||
setDefaultVideoChannel,
|
||||
|
@ -641,24 +640,47 @@ describe('Test runner common actions', function () {
|
|||
})
|
||||
})
|
||||
|
||||
it('Should rate limit an unknown runner', async function () {
|
||||
const path = '/api/v1/ping'
|
||||
const fields = { runnerToken: 'toto' }
|
||||
it('Should rate limit an unknown runner, but not a registered one', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
await server.videos.quickUpload({ name: 'video' })
|
||||
await waitJobs([ server ])
|
||||
|
||||
const { job } = await server.runnerJobs.autoAccept({ runnerToken })
|
||||
|
||||
for (let i = 0; i < 20; i++) {
|
||||
try {
|
||||
await makePostBodyRequest({ url: server.url, path, fields, expectedStatus: HttpStatusCode.OK_200 })
|
||||
await server.runnerJobs.request({ runnerToken })
|
||||
await server.runnerJobs.update({ runnerToken, jobToken: job.jobToken, jobUUID: job.uuid })
|
||||
} catch {}
|
||||
}
|
||||
|
||||
await makePostBodyRequest({ url: server.url, path, fields, expectedStatus: HttpStatusCode.TOO_MANY_REQUESTS_429 })
|
||||
// Invalid
|
||||
{
|
||||
await server.runnerJobs.request({ runnerToken: 'toto', expectedStatus: HttpStatusCode.TOO_MANY_REQUESTS_429 })
|
||||
await server.runnerJobs.update({
|
||||
runnerToken: 'toto',
|
||||
jobToken: job.jobToken,
|
||||
jobUUID: job.uuid,
|
||||
expectedStatus: HttpStatusCode.TOO_MANY_REQUESTS_429
|
||||
})
|
||||
}
|
||||
|
||||
it('Should not rate limit a registered runner', async function () {
|
||||
const path = '/api/v1/ping'
|
||||
// Not provided
|
||||
{
|
||||
await server.runnerJobs.request({ runnerToken: undefined, expectedStatus: HttpStatusCode.TOO_MANY_REQUESTS_429 })
|
||||
await server.runnerJobs.update({
|
||||
runnerToken: undefined,
|
||||
jobToken: job.jobToken,
|
||||
jobUUID: job.uuid,
|
||||
expectedStatus: HttpStatusCode.TOO_MANY_REQUESTS_429
|
||||
})
|
||||
}
|
||||
|
||||
for (let i = 0; i < 20; i++) {
|
||||
await makePostBodyRequest({ url: server.url, path, fields: { runnerToken }, expectedStatus: HttpStatusCode.OK_200 })
|
||||
// Registered
|
||||
{
|
||||
await server.runnerJobs.request({ runnerToken })
|
||||
await server.runnerJobs.update({ runnerToken, jobToken: job.jobToken, jobUUID: job.uuid })
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue