Merge pull request #11302 from overleaf/em-rate-limiter-2

Move rate limits in router.js to rate-limiter-flexible

GitOrigin-RevId: 9ac5dfe2fdf3de017e852dee36e26859db3ca4cb
This commit is contained in:
Eric Mc Sween 2023-01-19 07:15:17 -05:00 committed by Copybot
parent 16627a18ef
commit 9eb9203104

View file

@ -71,6 +71,137 @@ const UserContentDomainController = require('./Features/UserContentDomainCheck/U
module.exports = { initialize }
const rateLimiters = {
addEmail: new RateLimiter('add-email', {
points: 10,
duration: 60,
}),
addProjectToTag: new RateLimiter('add-project-to-tag', {
points: 30,
duration: 60,
}),
addProjectsToTag: new RateLimiter('add-projects-to-tag', {
points: 30,
duration: 60,
}),
canSkipCaptcha: new RateLimiter('can-skip-captcha', {
points: 20,
duration: 60,
}),
changePassword: new RateLimiter('change-password', {
points: 10,
duration: 60,
}),
compileProjectHttp: new RateLimiter('compile-project-http', {
points: 800,
duration: 60 * 60,
}),
confirmEmail: new RateLimiter('confirm-email', {
points: 10,
duration: 60,
}),
confirmUniversityDomain: new RateLimiter('confirm-university-domain', {
points: 1,
duration: 60,
}),
createProject: new RateLimiter('create-project', {
points: 20,
duration: 60,
}),
createTag: new RateLimiter('create-tag', {
points: 30,
duration: 60,
}),
deleteEmail: new RateLimiter('delete-email', {
points: 10,
duration: 60,
}),
deleteTag: new RateLimiter('delete-tag', {
points: 30,
duration: 60,
}),
deleteUser: new RateLimiter('delete-user', {
points: 10,
duration: 60,
}),
downloadProjectRevision: new RateLimiter('download-project-revision', {
points: 30,
duration: 60 * 60,
}),
endorseEmail: new RateLimiter('endorse-email', {
points: 30,
duration: 60,
}),
getProjects: new RateLimiter('get-projects', {
points: 30,
duration: 60,
}),
grantTokenAccessReadOnly: new RateLimiter('grant-token-access-read-only', {
points: 10,
duration: 60,
}),
grantTokenAccessReadWrite: new RateLimiter('grant-token-access-read-write', {
points: 10,
duration: 60,
}),
indexAllProjectReferences: new RateLimiter('index-all-project-references', {
points: 30,
duration: 60,
}),
indexProjectReferences: new RateLimiter('index-project-references', {
points: 30,
duration: 60,
}),
miscOutputDownload: new RateLimiter('misc-output-download', {
points: 1000,
duration: 60 * 60,
}),
multipleProjectsZipDownload: new RateLimiter(
'multiple-projects-zip-download',
{
points: 10,
duration: 60,
}
),
openDashboard: new RateLimiter('open-dashboard', {
points: 30,
duration: 60,
}),
openProject: new RateLimiter('open-project', {
points: 15,
duration: 60,
}),
readAndWriteToken: new RateLimiter('read-and-write-token', {
points: 15,
duration: 60,
}),
readOnlyToken: new RateLimiter('read-only-token', {
points: 15,
duration: 60,
}),
removeProjectFromTag: new RateLimiter('remove-project-from-tag', {
points: 30,
duration: 60,
}),
removeProjectsFromTag: new RateLimiter('remove-projects-from-tag', {
points: 30,
duration: 60,
}),
renameTag: new RateLimiter('rename-tag', {
points: 30,
duration: 60,
}),
resendConfirmation: new RateLimiter('resend-confirmation', {
points: 10,
duration: 60,
}),
sendChatMessage: new RateLimiter('send-chat-message', {
points: 100,
duration: 60,
}),
statusCompiler: new RateLimiter('status-compiler', {
points: 10,
duration: 60,
}),
zipDownload: new RateLimiter('zip-download', {
points: 10,
duration: 60,
@ -100,11 +231,7 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
webRouter.post(
'/login/can-skip-captcha',
// Keep in sync with the overleaf-login options.
RateLimiterMiddleware.rateLimit({
endpointName: 'can-skip-captcha',
maxRequests: 20,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.canSkipCaptcha),
CaptchaMiddleware.canSkipCaptcha
)
@ -183,11 +310,7 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
webRouter.post(
'/user/password/update',
AuthenticationController.requireLogin(),
RateLimiterMiddleware.rateLimit({
endpointName: 'change-password',
maxRequests: 10,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.changePassword),
UserController.changePassword
)
webRouter.get(
@ -199,21 +322,13 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
webRouter.get('/user/emails/confirm', UserEmailsController.showConfirm)
webRouter.post(
'/user/emails/confirm',
RateLimiterMiddleware.rateLimit({
endpointName: 'confirm-email',
maxRequests: 10,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.confirmEmail),
UserEmailsController.confirm
)
webRouter.post(
'/user/emails/resend_confirmation',
AuthenticationController.requireLogin(),
RateLimiterMiddleware.rateLimit({
endpointName: 'resend-confirmation',
maxRequests: 10,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.resendConfirmation),
UserEmailsController.resendConfirmation
)
@ -233,21 +348,13 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
webRouter.post(
'/user/emails',
AuthenticationController.requireLogin(),
RateLimiterMiddleware.rateLimit({
endpointName: 'add-email',
maxRequests: 10,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.addEmail),
UserEmailsController.add
)
webRouter.post(
'/user/emails/delete',
AuthenticationController.requireLogin(),
RateLimiterMiddleware.rateLimit({
endpointName: 'delete-email',
maxRequests: 10,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.deleteEmail),
UserEmailsController.remove
)
webRouter.post(
@ -258,11 +365,7 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
webRouter.post(
'/user/emails/endorse',
AuthenticationController.requireLogin(),
RateLimiterMiddleware.rateLimit({
endpointName: 'endorse-email',
maxRequests: 30,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.endorseEmail),
UserEmailsController.endorse
)
}
@ -305,11 +408,7 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
webRouter.post(
'/user/delete',
RateLimiterMiddleware.rateLimit({
endpointName: 'delete-user',
maxRequests: 10,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.deleteUser),
AuthenticationController.requireLogin(),
UserController.tryDeleteUser
)
@ -352,31 +451,19 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
webRouter.get(
'/project',
AuthenticationController.requireLogin(),
RateLimiterMiddleware.rateLimit({
endpointName: 'open-dashboard',
maxRequests: 30,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.openDashboard),
ProjectController.projectListPage
)
webRouter.post(
'/project/new',
AuthenticationController.requireLogin(),
RateLimiterMiddleware.rateLimit({
endpointName: 'create-project',
maxRequests: 20,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.createProject),
ProjectController.newProject
)
webRouter.post(
'/api/project',
AuthenticationController.requireLogin(),
RateLimiterMiddleware.rateLimit({
endpointName: 'get-projects',
maxRequests: 30,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.getProjects),
ProjectListController.getProjectsJson
)
@ -388,11 +475,8 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
]) {
webRouter.get(
route,
RateLimiterMiddleware.rateLimit({
endpointName: 'open-project',
RateLimiterMiddleware.rateLimitV2(rateLimiters.openProject, {
params: ['Project_id'],
maxRequests: 15,
timeInterval: 60,
}),
AuthenticationController.validateUserSession(),
AuthorizationMiddleware.ensureUserCanReadProject,
@ -430,11 +514,8 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
webRouter.post(
'/project/:Project_id/compile',
RateLimiterMiddleware.rateLimit({
endpointName: 'compile-project-http',
RateLimiterMiddleware.rateLimitV2(rateLimiters.compileProjectHttp, {
params: ['Project_id'],
maxRequests: 800,
timeInterval: 60 * 60,
}),
AuthorizationMiddleware.ensureUserCanReadProject,
CompileController.compile
@ -481,12 +562,10 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
)
// Align with limits defined in CompileController.downloadPdf
const rateLimiterMiddlewareOutputFiles = RateLimiterMiddleware.rateLimit({
endpointName: 'misc-output-download',
params: ['Project_id'],
maxRequests: 1000,
timeInterval: 60 * 60,
})
const rateLimiterMiddlewareOutputFiles = RateLimiterMiddleware.rateLimitV2(
rateLimiters.miscOutputDownload,
{ params: ['Project_id'] }
)
// Used by the pdf viewers
webRouter.get(
@ -674,11 +753,7 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
)
webRouter.get(
'/project/:project_id/version/:version/zip',
RateLimiterMiddleware.rateLimit({
endpointName: 'download-project-revision',
maxRequests: 30,
timeInterval: 60 * 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.downloadProjectRevision),
AuthorizationMiddleware.blockRestrictedUserFromProject,
AuthorizationMiddleware.ensureUserCanReadProject,
HistoryController.downloadZipOfVersion
@ -739,11 +814,7 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
webRouter.get(
'/project/download/zip',
AuthenticationController.requireLogin(),
RateLimiterMiddleware.rateLimit({
endpointName: 'multiple-projects-zip-download',
maxRequests: 10,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.multipleProjectsZipDownload),
AuthorizationMiddleware.ensureUserCanReadMultipleProjects,
ProjectDownloadsController.downloadMultipleProjects
)
@ -802,11 +873,7 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
webRouter.post(
'/tag',
AuthenticationController.requireLogin(),
RateLimiterMiddleware.rateLimit({
endpointName: 'create-tag',
maxRequests: 30,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.createTag),
validate({
body: Joi.object({
name: Joi.string().required(),
@ -817,11 +884,7 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
webRouter.post(
'/tag/:tagId/rename',
AuthenticationController.requireLogin(),
RateLimiterMiddleware.rateLimit({
endpointName: 'rename-tag',
maxRequests: 30,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.renameTag),
validate({
body: Joi.object({
name: Joi.string().required(),
@ -832,31 +895,19 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
webRouter.delete(
'/tag/:tagId',
AuthenticationController.requireLogin(),
RateLimiterMiddleware.rateLimit({
endpointName: 'delete-tag',
maxRequests: 30,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.deleteTag),
TagsController.deleteTag
)
webRouter.post(
'/tag/:tagId/project/:projectId',
AuthenticationController.requireLogin(),
RateLimiterMiddleware.rateLimit({
endpointName: 'add-project-to-tag',
maxRequests: 30,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.addProjectToTag),
TagsController.addProjectToTag
)
webRouter.post(
'/tag/:tagId/projects',
AuthenticationController.requireLogin(),
RateLimiterMiddleware.rateLimit({
endpointName: 'add-projects-to-tag',
maxRequests: 30,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.addProjectsToTag),
validate({
body: Joi.object({
projectIds: Joi.array().items(Joi.string()).required(),
@ -867,21 +918,13 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
webRouter.delete(
'/tag/:tagId/project/:projectId',
AuthenticationController.requireLogin(),
RateLimiterMiddleware.rateLimit({
endpointName: 'remove-project-from-tag',
maxRequests: 30,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.removeProjectFromTag),
TagsController.removeProjectFromTag
)
webRouter.delete(
'/tag/:tagId/projects',
AuthenticationController.requireLogin(),
RateLimiterMiddleware.rateLimit({
endpointName: 'remove-projects-from-tag',
maxRequests: 30,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.removeProjectsFromTag),
validate({
body: Joi.object({
projectIds: Joi.array().items(Joi.string()).required(),
@ -1040,32 +1083,20 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
'/project/:project_id/messages',
AuthorizationMiddleware.blockRestrictedUserFromProject,
AuthorizationMiddleware.ensureUserCanReadProject,
RateLimiterMiddleware.rateLimit({
endpointName: 'send-chat-message',
maxRequests: 100,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.sendChatMessage),
ChatController.sendMessage
)
webRouter.post(
'/project/:Project_id/references/index',
AuthorizationMiddleware.ensureUserCanReadProject,
RateLimiterMiddleware.rateLimit({
endpointName: 'index-project-references',
maxRequests: 30,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.indexProjectReferences),
ReferencesController.index
)
webRouter.post(
'/project/:Project_id/references/indexAll',
AuthorizationMiddleware.ensureUserCanReadProject,
RateLimiterMiddleware.rateLimit({
endpointName: 'index-all-project-references',
maxRequests: 30,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.indexAllProjectReferences),
ReferencesController.indexAll
)
@ -1110,11 +1141,7 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
)
publicApiRouter.post(
'/api/institutions/confirm_university_domain',
RateLimiterMiddleware.rateLimit({
endpointName: 'confirm-university-domain',
maxRequests: 1,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.confirmUniversityDomain),
AuthenticationController.requirePrivateApiAuth(),
InstitutionsController.confirmDomain
)
@ -1233,11 +1260,7 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
webRouter.get(
'/status/compiler/:Project_id',
RateLimiterMiddleware.rateLimit({
endpointName: 'status-compiler',
maxRequests: 10,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.statusCompiler),
AuthorizationMiddleware.ensureUserCanReadProject,
function (req, res) {
const projectId = req.params.Project_id
@ -1332,11 +1355,7 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
webRouter.get(
`/read/:token(${TokenAccessController.READ_ONLY_TOKEN_PATTERN})`,
RateLimiterMiddleware.rateLimit({
endpointName: 'read-only-token',
maxRequests: 15,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.readOnlyToken),
AnalyticsRegistrationSourceMiddleware.setSource(
'collaboration',
'link-sharing'
@ -1347,11 +1366,7 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
webRouter.get(
`/:token(${TokenAccessController.READ_AND_WRITE_TOKEN_PATTERN})`,
RateLimiterMiddleware.rateLimit({
endpointName: 'read-and-write-token',
maxRequests: 15,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.readAndWriteToken),
AnalyticsRegistrationSourceMiddleware.setSource(
'collaboration',
'link-sharing'
@ -1362,21 +1377,13 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
webRouter.post(
`/:token(${TokenAccessController.READ_AND_WRITE_TOKEN_PATTERN})/grant`,
RateLimiterMiddleware.rateLimit({
endpointName: 'grant-token-access-read-write',
maxRequests: 10,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.grantTokenAccessReadWrite),
TokenAccessController.grantTokenAccessReadAndWrite
)
webRouter.post(
`/read/:token(${TokenAccessController.READ_ONLY_TOKEN_PATTERN})/grant`,
RateLimiterMiddleware.rateLimit({
endpointName: 'grant-token-access-read-only',
maxRequests: 10,
timeInterval: 60,
}),
RateLimiterMiddleware.rateLimitV2(rateLimiters.grantTokenAccessReadOnly),
TokenAccessController.grantTokenAccessReadOnly
)