From f17ada4e28735ee8316af4bf447f8b2a98d58015 Mon Sep 17 00:00:00 2001 From: Leonardo Ostjen Couto Date: Tue, 16 Nov 2021 16:15:43 -0300 Subject: [PATCH 01/17] users.register setting + rate limiting --- app/api/server/api.js | 7 ++++++- app/lib/server/startup/settings.ts | 1 + packages/rocketchat-i18n/i18n/en.i18n.json | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/api/server/api.js b/app/api/server/api.js index 3b1d6bdfbb9e..88a441aea501 100644 --- a/app/api/server/api.js +++ b/app/api/server/api.js @@ -20,9 +20,11 @@ const logger = new Logger('API'); const rateLimiterDictionary = {}; export const defaultRateLimiterOptions = { numRequestsAllowed: settings.get('API_Enable_Rate_Limiter_Limit_Calls_Default'), + numRequestsAllowedUserRegistration: settings.get('API_Enable_Rate_Limiter_Limit_RegisterUser'), intervalTimeInMS: settings.get('API_Enable_Rate_Limiter_Limit_Time_Default'), }; let prometheusAPIUserAgent = false; +const registerUserRoute = '/api/v1/users.registerpost'; export let API = {}; @@ -264,7 +266,10 @@ export class APIClass extends Restivus { IPAddr: (input) => input, route, }; - rateLimiterDictionary[route].rateLimiter.addRule(rateLimitRule, rateLimiterOptions.numRequestsAllowed, rateLimiterOptions.intervalTimeInMS); + + rateLimiterDictionary[route].rateLimiter.addRule(rateLimitRule, + route === registerUserRoute ? rateLimiterOptions.numRequestsAllowedUserRegistration : rateLimiterOptions.numRequestsAllowed, + rateLimiterOptions.intervalTimeInMS); }); }; routes diff --git a/app/lib/server/startup/settings.ts b/app/lib/server/startup/settings.ts index b8c3309b5cf2..860aae53df01 100644 --- a/app/lib/server/startup/settings.ts +++ b/app/lib/server/startup/settings.ts @@ -3003,6 +3003,7 @@ settingsRegistry.addGroup('Rate Limiter', function() { this.add('API_Enable_Rate_Limiter', true, { type: 'boolean' }); this.add('API_Enable_Rate_Limiter_Dev', true, { type: 'boolean', enableQuery: { _id: 'API_Enable_Rate_Limiter', value: true } }); this.add('API_Enable_Rate_Limiter_Limit_Calls_Default', 10, { type: 'int', enableQuery: { _id: 'API_Enable_Rate_Limiter', value: true } }); + this.add('API_Enable_Rate_Limiter_Limit_RegisterUser', 1, { type: 'int', enableQuery: { _id: 'API_Enable_Rate_Limiter', value: true } }); this.add('API_Enable_Rate_Limiter_Limit_Time_Default', 60000, { type: 'int', enableQuery: { _id: 'API_Enable_Rate_Limiter', value: true } }); }); }); diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 6fd8880bbb61..ddcf67ff0298 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -370,6 +370,7 @@ "API_Enable_Rate_Limiter_Dev": "Enable Rate Limiter in development", "API_Enable_Rate_Limiter_Dev_Description": "Should limit the amount of calls to the endpoints in the development environment?", "API_Enable_Rate_Limiter_Limit_Calls_Default": "Default number calls to the rate limiter", + "API_Enable_Rate_Limiter_Limit_RegisterUser": "Default number calls to the rate limiter for registering a user", "API_Enable_Rate_Limiter_Limit_Calls_Default_Description": "Number of default calls for each endpoint of the REST API, allowed within the time range defined below", "API_Enable_Rate_Limiter_Limit_Time_Default": "Default time limit for the rate limiter (in ms)", "API_Enable_Rate_Limiter_Limit_Time_Default_Description": "Default timeout to limit the number of calls at each endpoint of the REST API(in ms)", From da3aad9f0cd18f668e944705690db345048a3c91 Mon Sep 17 00:00:00 2001 From: Leonardo Ostjen Couto Date: Wed, 17 Nov 2021 10:45:54 -0300 Subject: [PATCH 02/17] refact rate limiting strategy --- app/api/server/api.js | 6 +----- app/api/server/v1/users.js | 4 +++- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/app/api/server/api.js b/app/api/server/api.js index 88a441aea501..5a6d0dc0c32b 100644 --- a/app/api/server/api.js +++ b/app/api/server/api.js @@ -20,11 +20,9 @@ const logger = new Logger('API'); const rateLimiterDictionary = {}; export const defaultRateLimiterOptions = { numRequestsAllowed: settings.get('API_Enable_Rate_Limiter_Limit_Calls_Default'), - numRequestsAllowedUserRegistration: settings.get('API_Enable_Rate_Limiter_Limit_RegisterUser'), intervalTimeInMS: settings.get('API_Enable_Rate_Limiter_Limit_Time_Default'), }; let prometheusAPIUserAgent = false; -const registerUserRoute = '/api/v1/users.registerpost'; export let API = {}; @@ -267,9 +265,7 @@ export class APIClass extends Restivus { route, }; - rateLimiterDictionary[route].rateLimiter.addRule(rateLimitRule, - route === registerUserRoute ? rateLimiterOptions.numRequestsAllowedUserRegistration : rateLimiterOptions.numRequestsAllowed, - rateLimiterOptions.intervalTimeInMS); + rateLimiterDictionary[route].rateLimiter.addRule(rateLimitRule, rateLimiterOptions.numRequestsAllowed, rateLimiterOptions.intervalTimeInMS); }); }; routes diff --git a/app/api/server/v1/users.js b/app/api/server/v1/users.js index 1f3f22e38e6c..307800a992a9 100644 --- a/app/api/server/v1/users.js +++ b/app/api/server/v1/users.js @@ -283,7 +283,9 @@ API.v1.addRoute('users.list', { authRequired: true }, { }, }); -API.v1.addRoute('users.register', { authRequired: false }, { +API.v1.addRoute('users.register', { authRequired: false, + rateLimiterOptions: { numRequestsAllowed: settings.get('API_Enable_Rate_Limiter_Limit_RegisterUser'), + intervalTimeInMS: settings.get('API_Enable_Rate_Limiter_Limit_Time_Default') } }, { post() { if (this.userId) { return API.v1.failure('Logged in users can not register again.'); From dc4030b9a6167b066d335ced9a83dd5079044f64 Mon Sep 17 00:00:00 2001 From: Leonardo Ostjen Couto Date: Wed, 17 Nov 2021 10:50:51 -0300 Subject: [PATCH 03/17] remove empty line --- app/api/server/api.js | 1 - 1 file changed, 1 deletion(-) diff --git a/app/api/server/api.js b/app/api/server/api.js index 5a6d0dc0c32b..3b1d6bdfbb9e 100644 --- a/app/api/server/api.js +++ b/app/api/server/api.js @@ -264,7 +264,6 @@ export class APIClass extends Restivus { IPAddr: (input) => input, route, }; - rateLimiterDictionary[route].rateLimiter.addRule(rateLimitRule, rateLimiterOptions.numRequestsAllowed, rateLimiterOptions.intervalTimeInMS); }); }; From a4d8e68a2ae5807f008840a303ae2b039ee3788f Mon Sep 17 00:00:00 2001 From: Leonardo Ostjen Couto Date: Wed, 17 Nov 2021 11:16:44 -0300 Subject: [PATCH 04/17] method rate limiting + description + i18n --- packages/rocketchat-i18n/i18n/en.i18n.json | 1 + packages/rocketchat-i18n/i18n/pt-BR.i18n.json | 2 ++ server/methods/registerUser.js | 8 +++++++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index ddcf67ff0298..572764600b6c 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -371,6 +371,7 @@ "API_Enable_Rate_Limiter_Dev_Description": "Should limit the amount of calls to the endpoints in the development environment?", "API_Enable_Rate_Limiter_Limit_Calls_Default": "Default number calls to the rate limiter", "API_Enable_Rate_Limiter_Limit_RegisterUser": "Default number calls to the rate limiter for registering a user", + "API_Enable_Rate_Limiter_Limit_RegisterUser_Description": "Number of default calls for user registering endpoints(REST and real-time API's), allowed within the time range defined below", "API_Enable_Rate_Limiter_Limit_Calls_Default_Description": "Number of default calls for each endpoint of the REST API, allowed within the time range defined below", "API_Enable_Rate_Limiter_Limit_Time_Default": "Default time limit for the rate limiter (in ms)", "API_Enable_Rate_Limiter_Limit_Time_Default_Description": "Default timeout to limit the number of calls at each endpoint of the REST API(in ms)", diff --git a/packages/rocketchat-i18n/i18n/pt-BR.i18n.json b/packages/rocketchat-i18n/i18n/pt-BR.i18n.json index f34ce0b737cd..390a426e2e11 100644 --- a/packages/rocketchat-i18n/i18n/pt-BR.i18n.json +++ b/packages/rocketchat-i18n/i18n/pt-BR.i18n.json @@ -370,6 +370,8 @@ "API_Enable_Rate_Limiter_Dev": "Ativar limitador de taxa em desenvolvimento", "API_Enable_Rate_Limiter_Dev_Description": "Deve limitar a quantidade de chamadas para os endpoints no ambiente de desenvolvimento?", "API_Enable_Rate_Limiter_Limit_Calls_Default": "Número padrão de chamadas para o limitador de taxa", + "API_Enable_Rate_Limiter_Limit_RegisterUser": "Número de chamadas para as endpoint de registro de usuário", + "API_Enable_Rate_Limiter_Limit_RegisterUser_Description": "Número de chamadas padrão para as endpoints de registro de usuário(API REST e real-time), permitido dentro do intervalo de tempo definido abaixo", "API_Enable_Rate_Limiter_Limit_Calls_Default_Description": "Número de chamadas padrão para cada endpoint da API REST, permitido dentro do intervalo de tempo definido abaixo", "API_Enable_Rate_Limiter_Limit_Time_Default": "Limite de tempo padrão para o limitador de taxa (em ms)", "API_Enable_Rate_Limiter_Limit_Time_Default_Description": "Tempo limite padrão para limitar o número de chamadas em cada endpoint da API REST (em ms)", diff --git a/server/methods/registerUser.js b/server/methods/registerUser.js index 802f271efc40..3a990dd1bd89 100644 --- a/server/methods/registerUser.js +++ b/server/methods/registerUser.js @@ -5,7 +5,7 @@ import s from 'underscore.string'; import { Users } from '../../app/models'; import { settings } from '../../app/settings'; -import { validateEmailDomain, passwordPolicy } from '../../app/lib'; +import { validateEmailDomain, passwordPolicy, RateLimiter } from '../../app/lib'; import { validateInviteToken } from '../../app/invites/server/functions/validateInviteToken'; Meteor.methods({ @@ -97,3 +97,9 @@ Meteor.methods({ return userId; }, }); + +RateLimiter.limitMethod('registerUser', + settings.get('API_Enable_Rate_Limiter_Limit_RegisterUser'), + settings.get('API_Enable_Rate_Limiter_Limit_Time_Default'), { + userId() { return true; }, + }); From c66c47f0a70c6cb7fc2d9f80500b1f3798a89581 Mon Sep 17 00:00:00 2001 From: Leonardo Ostjen Couto Date: Thu, 18 Nov 2021 18:19:00 -0300 Subject: [PATCH 05/17] update + settings.watch on rest api --- app/api/server/api.js | 11 +++++++++++ app/api/server/v1/users.js | 5 ++--- app/lib/server/startup/settings.ts | 4 ++++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/app/api/server/api.js b/app/api/server/api.js index 01a71effe8a3..5e9eb9bd4cf8 100644 --- a/app/api/server/api.js +++ b/app/api/server/api.js @@ -22,6 +22,12 @@ export const defaultRateLimiterOptions = { numRequestsAllowed: settings.get('API_Enable_Rate_Limiter_Limit_Calls_Default'), intervalTimeInMS: settings.get('API_Enable_Rate_Limiter_Limit_Time_Default'), }; + +export const userRegisterRateLimiterOptions = { + numRequestsAllowed: settings.get('API_Enable_Rate_Limiter_Limit_Calls_Default'), + intervalTimeInMS: settings.get('API_Enable_Rate_Limiter_Limit_Time_Default'), +}; + let prometheusAPIUserAgent = false; export let API = {}; @@ -771,6 +777,11 @@ settings.watch('API_Enable_Rate_Limiter_Limit_Calls_Default', (value) => { API.v1.reloadRoutesToRefreshRateLimiter(); }); +settings.watch('API_Enable_Rate_Limiter_Limit_RegisterUser', (value) => { + userRegisterRateLimiterOptions.numRequestsAllowed = value; + API.v1.reloadRoutesToRefreshRateLimiter(); +}); + settings.watch('Prometheus_API_User_Agent', (value) => { prometheusAPIUserAgent = value; }); diff --git a/app/api/server/v1/users.js b/app/api/server/v1/users.js index 307800a992a9..0517a528cdd9 100644 --- a/app/api/server/v1/users.js +++ b/app/api/server/v1/users.js @@ -26,6 +26,7 @@ import { resetUserE2EEncriptionKey } from '../../../../server/lib/resetUserE2EKe import { setUserStatus } from '../../../../imports/users-presence/server/activeUsers'; import { resetTOTP } from '../../../2fa/server/functions/resetTOTP'; import { Team } from '../../../../server/sdk'; +import { userRegisterRateLimiterOptions } from '..'; API.v1.addRoute('users.create', { authRequired: true }, { post() { @@ -283,9 +284,7 @@ API.v1.addRoute('users.list', { authRequired: true }, { }, }); -API.v1.addRoute('users.register', { authRequired: false, - rateLimiterOptions: { numRequestsAllowed: settings.get('API_Enable_Rate_Limiter_Limit_RegisterUser'), - intervalTimeInMS: settings.get('API_Enable_Rate_Limiter_Limit_Time_Default') } }, { +API.v1.addRoute('users.register', { authRequired: false, rateLimiterOptions: userRegisterRateLimiterOptions }, { post() { if (this.userId) { return API.v1.failure('Logged in users can not register again.'); diff --git a/app/lib/server/startup/settings.ts b/app/lib/server/startup/settings.ts index 860aae53df01..92e4f7373860 100644 --- a/app/lib/server/startup/settings.ts +++ b/app/lib/server/startup/settings.ts @@ -3006,6 +3006,10 @@ settingsRegistry.addGroup('Rate Limiter', function() { this.add('API_Enable_Rate_Limiter_Limit_RegisterUser', 1, { type: 'int', enableQuery: { _id: 'API_Enable_Rate_Limiter', value: true } }); this.add('API_Enable_Rate_Limiter_Limit_Time_Default', 60000, { type: 'int', enableQuery: { _id: 'API_Enable_Rate_Limiter', value: true } }); }); + + this.section('Feature Limiting', function() { + this.add('API_Enable_Rate_Limiter_Limit_RegisterUser', 1, { type: 'int', enableQuery: { _id: 'API_Enable_Rate_Limiter', value: true } }); + }); }); settingsRegistry.addGroup('Troubleshoot', function() { From 6651c3908d2a0d63b6dbdc36d9d2a3e871a64ed1 Mon Sep 17 00:00:00 2001 From: Leonardo Ostjen Couto Date: Fri, 19 Nov 2021 10:48:46 -0300 Subject: [PATCH 06/17] removed duplicated setting --- app/lib/server/startup/settings.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/app/lib/server/startup/settings.ts b/app/lib/server/startup/settings.ts index 92e4f7373860..30057b0efdb6 100644 --- a/app/lib/server/startup/settings.ts +++ b/app/lib/server/startup/settings.ts @@ -3003,7 +3003,6 @@ settingsRegistry.addGroup('Rate Limiter', function() { this.add('API_Enable_Rate_Limiter', true, { type: 'boolean' }); this.add('API_Enable_Rate_Limiter_Dev', true, { type: 'boolean', enableQuery: { _id: 'API_Enable_Rate_Limiter', value: true } }); this.add('API_Enable_Rate_Limiter_Limit_Calls_Default', 10, { type: 'int', enableQuery: { _id: 'API_Enable_Rate_Limiter', value: true } }); - this.add('API_Enable_Rate_Limiter_Limit_RegisterUser', 1, { type: 'int', enableQuery: { _id: 'API_Enable_Rate_Limiter', value: true } }); this.add('API_Enable_Rate_Limiter_Limit_Time_Default', 60000, { type: 'int', enableQuery: { _id: 'API_Enable_Rate_Limiter', value: true } }); }); From f3ef8861b710157ee5fb48382721c0dd8978fd54 Mon Sep 17 00:00:00 2001 From: Leonardo Ostjen Couto Date: Fri, 19 Nov 2021 16:12:34 -0300 Subject: [PATCH 07/17] fixed update setting value on rest api --- app/api/server/api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/api/server/api.js b/app/api/server/api.js index 5e9eb9bd4cf8..78d774162ac0 100644 --- a/app/api/server/api.js +++ b/app/api/server/api.js @@ -778,7 +778,7 @@ settings.watch('API_Enable_Rate_Limiter_Limit_Calls_Default', (value) => { }); settings.watch('API_Enable_Rate_Limiter_Limit_RegisterUser', (value) => { - userRegisterRateLimiterOptions.numRequestsAllowed = value; + rateLimiterDictionary['/api/v1/users.registerpost'].options.numRequestsAllowed = value; API.v1.reloadRoutesToRefreshRateLimiter(); }); From c38e247af2a5a4f7d1d83d42c2440236e15d4771 Mon Sep 17 00:00:00 2001 From: Leonardo Ostjen Couto Date: Mon, 22 Nov 2021 09:40:22 -0300 Subject: [PATCH 08/17] refresh registerUser method on setting update + i18n --- app/api/server/api.js | 12 +++++++++++- app/lib/server/startup/settings.ts | 2 +- packages/rocketchat-i18n/i18n/en.i18n.json | 1 + packages/rocketchat-i18n/i18n/pt-BR.i18n.json | 1 + server/methods/registerUser.js | 2 +- 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/app/api/server/api.js b/app/api/server/api.js index 78d774162ac0..fd326b6d1d4b 100644 --- a/app/api/server/api.js +++ b/app/api/server/api.js @@ -4,9 +4,11 @@ import { DDPCommon } from 'meteor/ddp-common'; import { DDP } from 'meteor/ddp'; import { Accounts } from 'meteor/accounts-base'; import { Restivus } from 'meteor/nimble:restivus'; -import { RateLimiter } from 'meteor/rate-limit'; import _ from 'underscore'; +import { RateLimiter } from 'meteor/rate-limit'; +import { DDPRateLimiter } from 'meteor/ddp-rate-limiter'; +import { RateLimiter as CustomRateLimiter } from '../../lib'; import { Logger } from '../../../server/lib/logger/Logger'; import { getRestPayload } from '../../../server/lib/logger/logPayloads'; import { settings } from '../../settings/server'; @@ -14,6 +16,7 @@ import { metrics } from '../../metrics/server'; import { hasPermission, hasAllPermission } from '../../authorization/server'; import { getDefaultUserFields } from '../../utils/server/functions/getDefaultUserFields'; import { checkCodeForUser } from '../../2fa/server/code'; +import { registerUserRuleId } from '../../../server/methods/registerUser'; const logger = new Logger('API'); @@ -778,8 +781,15 @@ settings.watch('API_Enable_Rate_Limiter_Limit_Calls_Default', (value) => { }); settings.watch('API_Enable_Rate_Limiter_Limit_RegisterUser', (value) => { + // reload rate limiter to REST API rateLimiterDictionary['/api/v1/users.registerpost'].options.numRequestsAllowed = value; API.v1.reloadRoutesToRefreshRateLimiter(); + + // remove old rate limiter rule and create a new one with the updated setting value + DDPRateLimiter.removeRule(registerUserRuleId); + registerUserRuleId = CustomRateLimiter.limitMethod('registerUser', value, settings.get('API_Enable_Rate_Limiter_Limit_Time_Default'), { + userId() { return true; }, + }); }); settings.watch('Prometheus_API_User_Agent', (value) => { diff --git a/app/lib/server/startup/settings.ts b/app/lib/server/startup/settings.ts index 30057b0efdb6..77f4877a2d29 100644 --- a/app/lib/server/startup/settings.ts +++ b/app/lib/server/startup/settings.ts @@ -3006,7 +3006,7 @@ settingsRegistry.addGroup('Rate Limiter', function() { this.add('API_Enable_Rate_Limiter_Limit_Time_Default', 60000, { type: 'int', enableQuery: { _id: 'API_Enable_Rate_Limiter', value: true } }); }); - this.section('Feature Limiting', function() { + this.section('Feature_Limiting', function() { this.add('API_Enable_Rate_Limiter_Limit_RegisterUser', 1, { type: 'int', enableQuery: { _id: 'API_Enable_Rate_Limiter', value: true } }); }); }); diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 47425279bd6e..8f7ce1ddbd90 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -1839,6 +1839,7 @@ "Favorite_Rooms": "Enable Favorite Rooms", "Favorites": "Favorites", "Feature_Depends_on_Livechat_Visitor_navigation_as_a_message_to_be_enabled": "This feature depends on \"Send Visitor Navigation History as a Message\" to be enabled.", + "Feature_Limiting": "Feature Limiting", "Features": "Features", "Features_Enabled": "Features Enabled", "Feature_Disabled": "Feature Disabled", diff --git a/packages/rocketchat-i18n/i18n/pt-BR.i18n.json b/packages/rocketchat-i18n/i18n/pt-BR.i18n.json index 390a426e2e11..fa6bfae94984 100644 --- a/packages/rocketchat-i18n/i18n/pt-BR.i18n.json +++ b/packages/rocketchat-i18n/i18n/pt-BR.i18n.json @@ -1840,6 +1840,7 @@ "Favorites": "Favoritos", "Feature_Depends_on_Livechat_Visitor_navigation_as_a_message_to_be_enabled": "Esse recurso depende de \"Enviar histórico de navegação do visitante como uma mensagem\" para ser ativado.", "Features": "Funcionalidades", + "Feature_Limiting": "Limitação de funcionalidades", "Features_Enabled": "Funcionalidades habilitadas", "Feature_Disabled": "Funcionalidade desabilitada", "Federation": "Federação", diff --git a/server/methods/registerUser.js b/server/methods/registerUser.js index 3a990dd1bd89..12f05da9ce86 100644 --- a/server/methods/registerUser.js +++ b/server/methods/registerUser.js @@ -98,7 +98,7 @@ Meteor.methods({ }, }); -RateLimiter.limitMethod('registerUser', +export const registerUserRuleId = RateLimiter.limitMethod('registerUser', settings.get('API_Enable_Rate_Limiter_Limit_RegisterUser'), settings.get('API_Enable_Rate_Limiter_Limit_Time_Default'), { userId() { return true; }, From 62f761e0405b576c8a7f8c4f407d34fdd8c78225 Mon Sep 17 00:00:00 2001 From: Leonardo Ostjen Couto Date: Mon, 22 Nov 2021 09:50:07 -0300 Subject: [PATCH 09/17] removed useless object --- app/api/server/api.js | 12 ++++++------ app/api/server/v1/users.js | 7 +++++-- server/methods/registerUser.js | 1 + 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/app/api/server/api.js b/app/api/server/api.js index fd326b6d1d4b..a5deba3b89e1 100644 --- a/app/api/server/api.js +++ b/app/api/server/api.js @@ -26,11 +26,6 @@ export const defaultRateLimiterOptions = { intervalTimeInMS: settings.get('API_Enable_Rate_Limiter_Limit_Time_Default'), }; -export const userRegisterRateLimiterOptions = { - numRequestsAllowed: settings.get('API_Enable_Rate_Limiter_Limit_Calls_Default'), - intervalTimeInMS: settings.get('API_Enable_Rate_Limiter_Limit_Time_Default'), -}; - let prometheusAPIUserAgent = false; export let API = {}; @@ -215,6 +210,10 @@ export class APIClass extends Restivus { return rateLimiterDictionary[route]; } + updateRegisterUserRateLimiter() { + + } + shouldVerifyRateLimit(route, userId) { return rateLimiterDictionary.hasOwnProperty(route) && settings.get('API_Enable_Rate_Limiter') === true @@ -782,7 +781,8 @@ settings.watch('API_Enable_Rate_Limiter_Limit_Calls_Default', (value) => { settings.watch('API_Enable_Rate_Limiter_Limit_RegisterUser', (value) => { // reload rate limiter to REST API - rateLimiterDictionary['/api/v1/users.registerpost'].options.numRequestsAllowed = value; + const userRegisterRoute = '/api/v1/users.registerpost'; + rateLimiterDictionary[userRegisterRoute].options.numRequestsAllowed = value; API.v1.reloadRoutesToRefreshRateLimiter(); // remove old rate limiter rule and create a new one with the updated setting value diff --git a/app/api/server/v1/users.js b/app/api/server/v1/users.js index 0517a528cdd9..6b442204b25f 100644 --- a/app/api/server/v1/users.js +++ b/app/api/server/v1/users.js @@ -26,7 +26,6 @@ import { resetUserE2EEncriptionKey } from '../../../../server/lib/resetUserE2EKe import { setUserStatus } from '../../../../imports/users-presence/server/activeUsers'; import { resetTOTP } from '../../../2fa/server/functions/resetTOTP'; import { Team } from '../../../../server/sdk'; -import { userRegisterRateLimiterOptions } from '..'; API.v1.addRoute('users.create', { authRequired: true }, { post() { @@ -284,7 +283,11 @@ API.v1.addRoute('users.list', { authRequired: true }, { }, }); -API.v1.addRoute('users.register', { authRequired: false, rateLimiterOptions: userRegisterRateLimiterOptions }, { +API.v1.addRoute('users.register', { authRequired: false, + rateLimiterOptions: { + numRequestsAllowed: settings.get('API_Enable_Rate_Limiter_Limit_Calls_Default'), + intervalTimeInMS: settings.get('API_Enable_Rate_Limiter_Limit_Time_Default'), + } }, { post() { if (this.userId) { return API.v1.failure('Logged in users can not register again.'); diff --git a/server/methods/registerUser.js b/server/methods/registerUser.js index 12f05da9ce86..52a6c04855b6 100644 --- a/server/methods/registerUser.js +++ b/server/methods/registerUser.js @@ -8,6 +8,7 @@ import { settings } from '../../app/settings'; import { validateEmailDomain, passwordPolicy, RateLimiter } from '../../app/lib'; import { validateInviteToken } from '../../app/invites/server/functions/validateInviteToken'; + Meteor.methods({ async registerUser(formData) { const AllowAnonymousRead = settings.get('Accounts_AllowAnonymousRead'); From dd89480e6fe99a89046f10a7c6a0f345f56e1ccd Mon Sep 17 00:00:00 2001 From: Leonardo Ostjen Couto Date: Mon, 22 Nov 2021 09:51:23 -0300 Subject: [PATCH 10/17] removed empty method --- app/api/server/api.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/app/api/server/api.js b/app/api/server/api.js index a5deba3b89e1..fb83ff245bb7 100644 --- a/app/api/server/api.js +++ b/app/api/server/api.js @@ -25,7 +25,6 @@ export const defaultRateLimiterOptions = { numRequestsAllowed: settings.get('API_Enable_Rate_Limiter_Limit_Calls_Default'), intervalTimeInMS: settings.get('API_Enable_Rate_Limiter_Limit_Time_Default'), }; - let prometheusAPIUserAgent = false; export let API = {}; @@ -210,10 +209,6 @@ export class APIClass extends Restivus { return rateLimiterDictionary[route]; } - updateRegisterUserRateLimiter() { - - } - shouldVerifyRateLimit(route, userId) { return rateLimiterDictionary.hasOwnProperty(route) && settings.get('API_Enable_Rate_Limiter') === true From 708d65c514ffd01f7a5c202c86189ee1bf203329 Mon Sep 17 00:00:00 2001 From: Leonardo Ostjen Couto Date: Mon, 22 Nov 2021 10:24:01 -0300 Subject: [PATCH 11/17] fixed exception in server launch --- app/api/server/api.js | 9 ++++++--- app/lib/server/startup/settings.ts | 4 ++-- packages/rocketchat-i18n/i18n/en.i18n.json | 4 +++- packages/rocketchat-i18n/i18n/pt-BR.i18n.json | 4 +++- server/methods/registerUser.js | 1 - 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/app/api/server/api.js b/app/api/server/api.js index fb83ff245bb7..4332580fa103 100644 --- a/app/api/server/api.js +++ b/app/api/server/api.js @@ -775,10 +775,13 @@ settings.watch('API_Enable_Rate_Limiter_Limit_Calls_Default', (value) => { }); settings.watch('API_Enable_Rate_Limiter_Limit_RegisterUser', (value) => { - // reload rate limiter to REST API const userRegisterRoute = '/api/v1/users.registerpost'; - rateLimiterDictionary[userRegisterRoute].options.numRequestsAllowed = value; - API.v1.reloadRoutesToRefreshRateLimiter(); + + // reload rate limiter to REST API + if (rateLimiterDictionary[userRegisterRoute]) { + rateLimiterDictionary[userRegisterRoute].options.numRequestsAllowed = value; + API.v1.reloadRoutesToRefreshRateLimiter(); + } // remove old rate limiter rule and create a new one with the updated setting value DDPRateLimiter.removeRule(registerUserRuleId); diff --git a/app/lib/server/startup/settings.ts b/app/lib/server/startup/settings.ts index 77f4877a2d29..c82a375cc700 100644 --- a/app/lib/server/startup/settings.ts +++ b/app/lib/server/startup/settings.ts @@ -2977,7 +2977,7 @@ settingsRegistry.addGroup('Setup_Wizard', function() { }); settingsRegistry.addGroup('Rate Limiter', function() { - this.section('DDP Rate Limiter', function() { + this.section('DDP_Rate_Limiter', function() { this.add('DDP_Rate_Limit_IP_Enabled', true, { type: 'boolean' }); this.add('DDP_Rate_Limit_IP_Requests_Allowed', 120000, { type: 'int', enableQuery: { _id: 'DDP_Rate_Limit_IP_Enabled', value: true } }); this.add('DDP_Rate_Limit_IP_Interval_Time', 60000, { type: 'int', enableQuery: { _id: 'DDP_Rate_Limit_IP_Enabled', value: true } }); @@ -2999,7 +2999,7 @@ settingsRegistry.addGroup('Rate Limiter', function() { this.add('DDP_Rate_Limit_Connection_By_Method_Interval_Time', 10000, { type: 'int', enableQuery: { _id: 'DDP_Rate_Limit_Connection_By_Method_Enabled', value: true } }); }); - this.section('API Rate Limiter', function() { + this.section('API_Rate_Limiter', function() { this.add('API_Enable_Rate_Limiter', true, { type: 'boolean' }); this.add('API_Enable_Rate_Limiter_Dev', true, { type: 'boolean', enableQuery: { _id: 'API_Enable_Rate_Limiter', value: true } }); this.add('API_Enable_Rate_Limiter_Limit_Calls_Default', 10, { type: 'int', enableQuery: { _id: 'API_Enable_Rate_Limiter', value: true } }); diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 8f7ce1ddbd90..d7647f3c6fd5 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -371,7 +371,7 @@ "API_Enable_Rate_Limiter_Dev_Description": "Should limit the amount of calls to the endpoints in the development environment?", "API_Enable_Rate_Limiter_Limit_Calls_Default": "Default number calls to the rate limiter", "API_Enable_Rate_Limiter_Limit_RegisterUser": "Default number calls to the rate limiter for registering a user", - "API_Enable_Rate_Limiter_Limit_RegisterUser_Description": "Number of default calls for user registering endpoints(REST and real-time API's), allowed within the time range defined below", + "API_Enable_Rate_Limiter_Limit_RegisterUser_Description": "Number of default calls for user registering endpoints(REST and real-time API's), allowed within the time range defined in the API Rate Limiter section.", "API_Enable_Rate_Limiter_Limit_Calls_Default_Description": "Number of default calls for each endpoint of the REST API, allowed within the time range defined below", "API_Enable_Rate_Limiter_Limit_Time_Default": "Default time limit for the rate limiter (in ms)", "API_Enable_Rate_Limiter_Limit_Time_Default_Description": "Default timeout to limit the number of calls at each endpoint of the REST API(in ms)", @@ -387,6 +387,7 @@ "API_Personal_Access_Tokens_Regenerate_Modal": "If you lost or forgot your token, you can regenerate it, but remember that all applications that use this token should be updated", "API_Personal_Access_Tokens_Remove_Modal": "Are you sure you wish to remove this personal access token?", "API_Personal_Access_Tokens_To_REST_API": "Personal access tokens to REST API", + "API_Rate_Limiter": "API Rate Limiter", "API_Shield_Types": "Shield Types", "API_Shield_Types_Description": "Types of shields to enable as a comma separated list, choose from `online`, `channel` or `*` for all", "API_Shield_user_require_auth": "Require authentication for users shields", @@ -1342,6 +1343,7 @@ "Days": "Days", "DB_Migration": "Database Migration", "DB_Migration_Date": "Database Migration Date", + "DDP_Rate_Limit": "DDP Rate Limit", "DDP_Rate_Limit_Connection_By_Method_Enabled": "Limit by Connection per Method: enabled", "DDP_Rate_Limit_Connection_By_Method_Interval_Time": "Limit by Connection per Method: interval time", "DDP_Rate_Limit_Connection_By_Method_Requests_Allowed": "Limit by Connection per Method: requests allowed", diff --git a/packages/rocketchat-i18n/i18n/pt-BR.i18n.json b/packages/rocketchat-i18n/i18n/pt-BR.i18n.json index fa6bfae94984..71cabb1d2b73 100644 --- a/packages/rocketchat-i18n/i18n/pt-BR.i18n.json +++ b/packages/rocketchat-i18n/i18n/pt-BR.i18n.json @@ -372,7 +372,7 @@ "API_Enable_Rate_Limiter_Limit_Calls_Default": "Número padrão de chamadas para o limitador de taxa", "API_Enable_Rate_Limiter_Limit_RegisterUser": "Número de chamadas para as endpoint de registro de usuário", "API_Enable_Rate_Limiter_Limit_RegisterUser_Description": "Número de chamadas padrão para as endpoints de registro de usuário(API REST e real-time), permitido dentro do intervalo de tempo definido abaixo", - "API_Enable_Rate_Limiter_Limit_Calls_Default_Description": "Número de chamadas padrão para cada endpoint da API REST, permitido dentro do intervalo de tempo definido abaixo", + "API_Enable_Rate_Limiter_Limit_Calls_Default_Description": "Número de chamadas padrão para cada endpoint da API REST, permitido dentro do intervalo de tempo definido na seção de limitação de taxa.", "API_Enable_Rate_Limiter_Limit_Time_Default": "Limite de tempo padrão para o limitador de taxa (em ms)", "API_Enable_Rate_Limiter_Limit_Time_Default_Description": "Tempo limite padrão para limitar o número de chamadas em cada endpoint da API REST (em ms)", "API_Enable_Shields": "Ativar Protetores", @@ -387,6 +387,7 @@ "API_Personal_Access_Tokens_Regenerate_Modal": "Se perdeu ou esqueceu o seu código, pode recuperá-lo, mas lembre-se de que todos os aplicativos que usam esse código devem ser atualizados", "API_Personal_Access_Tokens_Remove_Modal": "Tem certeza de que deseja remover este código de acesso pessoal?", "API_Personal_Access_Tokens_To_REST_API": "Código de acesso pessoal para API REST", + "API_Rate_Limiter": "Limitação de Taxa de API", "API_Shield_Types": "Tipos de escudo", "API_Shield_Types_Description": "Tipos de escudos para habilitar como uma lista separada por vírgulas, escolha entre `online`, `channel` ou `*` para todos", "API_Shield_user_require_auth": "Exigir autenticaçāo para escudos de usuários", @@ -1342,6 +1343,7 @@ "Days": "Dias", "DB_Migration": "Migração de Banco de Dados", "DB_Migration_Date": "Data da migração do banco de dados", + "DDP_Rate_Limit": "Limitação de Taxa de DDP", "DDP_Rate_Limit_Connection_By_Method_Enabled": "Limite por Conexão por Método: Habilitado", "DDP_Rate_Limit_Connection_By_Method_Interval_Time": "Limite por Conexão por Método: Intervalo de tempo", "DDP_Rate_Limit_Connection_By_Method_Requests_Allowed": "Limite por Conexão por Método: Solicitações permitidas", diff --git a/server/methods/registerUser.js b/server/methods/registerUser.js index 52a6c04855b6..12f05da9ce86 100644 --- a/server/methods/registerUser.js +++ b/server/methods/registerUser.js @@ -8,7 +8,6 @@ import { settings } from '../../app/settings'; import { validateEmailDomain, passwordPolicy, RateLimiter } from '../../app/lib'; import { validateInviteToken } from '../../app/invites/server/functions/validateInviteToken'; - Meteor.methods({ async registerUser(formData) { const AllowAnonymousRead = settings.get('Accounts_AllowAnonymousRead'); From 2365b5559b3e2d282b6ab650f5faa61c5d2d66c5 Mon Sep 17 00:00:00 2001 From: Leonardo Ostjen Couto Date: Mon, 22 Nov 2021 10:45:44 -0300 Subject: [PATCH 12/17] renamed setting --- app/api/server/api.js | 4 ++-- app/lib/server/startup/settings.ts | 2 +- server/methods/registerUser.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/api/server/api.js b/app/api/server/api.js index 4332580fa103..5a7b6e53cdb9 100644 --- a/app/api/server/api.js +++ b/app/api/server/api.js @@ -774,11 +774,11 @@ settings.watch('API_Enable_Rate_Limiter_Limit_Calls_Default', (value) => { API.v1.reloadRoutesToRefreshRateLimiter(); }); -settings.watch('API_Enable_Rate_Limiter_Limit_RegisterUser', (value) => { +settings.watch('Rate_Limiter_Limit_RegisterUser', (value) => { const userRegisterRoute = '/api/v1/users.registerpost'; // reload rate limiter to REST API - if (rateLimiterDictionary[userRegisterRoute]) { + if (rateLimiterDictionary[userRegisterRoute ]) { rateLimiterDictionary[userRegisterRoute].options.numRequestsAllowed = value; API.v1.reloadRoutesToRefreshRateLimiter(); } diff --git a/app/lib/server/startup/settings.ts b/app/lib/server/startup/settings.ts index c82a375cc700..68e644eb120d 100644 --- a/app/lib/server/startup/settings.ts +++ b/app/lib/server/startup/settings.ts @@ -3007,7 +3007,7 @@ settingsRegistry.addGroup('Rate Limiter', function() { }); this.section('Feature_Limiting', function() { - this.add('API_Enable_Rate_Limiter_Limit_RegisterUser', 1, { type: 'int', enableQuery: { _id: 'API_Enable_Rate_Limiter', value: true } }); + this.add('Rate_Limiter_Limit_RegisterUser', 1, { type: 'int', enableQuery: { _id: 'API_Enable_Rate_Limiter', value: true } }); }); }); diff --git a/server/methods/registerUser.js b/server/methods/registerUser.js index 12f05da9ce86..cb48c3088063 100644 --- a/server/methods/registerUser.js +++ b/server/methods/registerUser.js @@ -99,7 +99,7 @@ Meteor.methods({ }); export const registerUserRuleId = RateLimiter.limitMethod('registerUser', - settings.get('API_Enable_Rate_Limiter_Limit_RegisterUser'), + settings.get('Rate_Limiter_Limit_RegisterUser'), settings.get('API_Enable_Rate_Limiter_Limit_Time_Default'), { userId() { return true; }, }); From f387005b56d330f4a99289984fafd7e8f429bdfe Mon Sep 17 00:00:00 2001 From: Leonardo Ostjen Couto Date: Mon, 22 Nov 2021 10:49:42 -0300 Subject: [PATCH 13/17] updated numRequestsAllowed in users.register --- app/api/server/v1/users.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/api/server/v1/users.js b/app/api/server/v1/users.js index 6b442204b25f..e7a77315b2c2 100644 --- a/app/api/server/v1/users.js +++ b/app/api/server/v1/users.js @@ -285,7 +285,7 @@ API.v1.addRoute('users.list', { authRequired: true }, { API.v1.addRoute('users.register', { authRequired: false, rateLimiterOptions: { - numRequestsAllowed: settings.get('API_Enable_Rate_Limiter_Limit_Calls_Default'), + numRequestsAllowed: settings.get('Rate_Limiter_Limit_RegisterUser'), intervalTimeInMS: settings.get('API_Enable_Rate_Limiter_Limit_Time_Default'), } }, { post() { From 313ac3b20730734f94e17fb8e404efdd7cf272bb Mon Sep 17 00:00:00 2001 From: Leonardo Ostjen Couto Date: Mon, 22 Nov 2021 10:51:15 -0300 Subject: [PATCH 14/17] i18n update --- packages/rocketchat-i18n/i18n/en.i18n.json | 4 ++-- packages/rocketchat-i18n/i18n/pt-BR.i18n.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index d7647f3c6fd5..e3d09b5700bb 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -370,8 +370,8 @@ "API_Enable_Rate_Limiter_Dev": "Enable Rate Limiter in development", "API_Enable_Rate_Limiter_Dev_Description": "Should limit the amount of calls to the endpoints in the development environment?", "API_Enable_Rate_Limiter_Limit_Calls_Default": "Default number calls to the rate limiter", - "API_Enable_Rate_Limiter_Limit_RegisterUser": "Default number calls to the rate limiter for registering a user", - "API_Enable_Rate_Limiter_Limit_RegisterUser_Description": "Number of default calls for user registering endpoints(REST and real-time API's), allowed within the time range defined in the API Rate Limiter section.", + "Rate_Limiter_Limit_RegisterUser": "Default number calls to the rate limiter for registering a user", + "Rate_Limiter_Limit_RegisterUser_Description": "Number of default calls for user registering endpoints(REST and real-time API's), allowed within the time range defined in the API Rate Limiter section.", "API_Enable_Rate_Limiter_Limit_Calls_Default_Description": "Number of default calls for each endpoint of the REST API, allowed within the time range defined below", "API_Enable_Rate_Limiter_Limit_Time_Default": "Default time limit for the rate limiter (in ms)", "API_Enable_Rate_Limiter_Limit_Time_Default_Description": "Default timeout to limit the number of calls at each endpoint of the REST API(in ms)", diff --git a/packages/rocketchat-i18n/i18n/pt-BR.i18n.json b/packages/rocketchat-i18n/i18n/pt-BR.i18n.json index 71cabb1d2b73..04b8f0f6528f 100644 --- a/packages/rocketchat-i18n/i18n/pt-BR.i18n.json +++ b/packages/rocketchat-i18n/i18n/pt-BR.i18n.json @@ -370,8 +370,8 @@ "API_Enable_Rate_Limiter_Dev": "Ativar limitador de taxa em desenvolvimento", "API_Enable_Rate_Limiter_Dev_Description": "Deve limitar a quantidade de chamadas para os endpoints no ambiente de desenvolvimento?", "API_Enable_Rate_Limiter_Limit_Calls_Default": "Número padrão de chamadas para o limitador de taxa", - "API_Enable_Rate_Limiter_Limit_RegisterUser": "Número de chamadas para as endpoint de registro de usuário", - "API_Enable_Rate_Limiter_Limit_RegisterUser_Description": "Número de chamadas padrão para as endpoints de registro de usuário(API REST e real-time), permitido dentro do intervalo de tempo definido abaixo", + "Rate_Limiter_Limit_RegisterUser": "Número de chamadas para as endpoint de registro de usuário", + "Rate_Limiter_Limit_RegisterUser_Description": "Número de chamadas padrão para as endpoints de registro de usuário(API REST e real-time), permitido dentro do intervalo de tempo definido abaixo", "API_Enable_Rate_Limiter_Limit_Calls_Default_Description": "Número de chamadas padrão para cada endpoint da API REST, permitido dentro do intervalo de tempo definido na seção de limitação de taxa.", "API_Enable_Rate_Limiter_Limit_Time_Default": "Limite de tempo padrão para o limitador de taxa (em ms)", "API_Enable_Rate_Limiter_Limit_Time_Default_Description": "Tempo limite padrão para limitar o número de chamadas em cada endpoint da API REST (em ms)", From 903a12b60e378cd8de970900d24fb727bf3ba7b4 Mon Sep 17 00:00:00 2001 From: Leonardo Ostjen Couto Date: Mon, 22 Nov 2021 11:05:23 -0300 Subject: [PATCH 15/17] lint --- app/api/server/api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/api/server/api.js b/app/api/server/api.js index 5a7b6e53cdb9..5d303670dfbb 100644 --- a/app/api/server/api.js +++ b/app/api/server/api.js @@ -778,7 +778,7 @@ settings.watch('Rate_Limiter_Limit_RegisterUser', (value) => { const userRegisterRoute = '/api/v1/users.registerpost'; // reload rate limiter to REST API - if (rateLimiterDictionary[userRegisterRoute ]) { + if (rateLimiterDictionary[userRegisterRoute]) { rateLimiterDictionary[userRegisterRoute].options.numRequestsAllowed = value; API.v1.reloadRoutesToRefreshRateLimiter(); } From a2e1d7fc6dd62729f57ef00895f1ccb3d13e9e67 Mon Sep 17 00:00:00 2001 From: Leonardo Ostjen Couto Date: Mon, 22 Nov 2021 17:19:54 -0300 Subject: [PATCH 16/17] moved settings.watch to endpoint --- app/api/server/api.js | 25 +++++++------------------ app/api/server/v1/users.js | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/app/api/server/api.js b/app/api/server/api.js index 5d303670dfbb..ad649b2d16d6 100644 --- a/app/api/server/api.js +++ b/app/api/server/api.js @@ -6,9 +6,7 @@ import { Accounts } from 'meteor/accounts-base'; import { Restivus } from 'meteor/nimble:restivus'; import _ from 'underscore'; import { RateLimiter } from 'meteor/rate-limit'; -import { DDPRateLimiter } from 'meteor/ddp-rate-limiter'; -import { RateLimiter as CustomRateLimiter } from '../../lib'; import { Logger } from '../../../server/lib/logger/Logger'; import { getRestPayload } from '../../../server/lib/logger/logPayloads'; import { settings } from '../../settings/server'; @@ -16,7 +14,6 @@ import { metrics } from '../../metrics/server'; import { hasPermission, hasAllPermission } from '../../authorization/server'; import { getDefaultUserFields } from '../../utils/server/functions/getDefaultUserFields'; import { checkCodeForUser } from '../../2fa/server/code'; -import { registerUserRuleId } from '../../../server/methods/registerUser'; const logger = new Logger('API'); @@ -450,6 +447,13 @@ export class APIClass extends Restivus { }); } + updateRateLimiterDictionaryForRoute(route, value) { + if (rateLimiterDictionary[route]) { + rateLimiterDictionary[route].options.numRequestsAllowed = value; + API.v1.reloadRoutesToRefreshRateLimiter(); + } + } + _initAuth() { const loginCompatibility = (bodyParams, request) => { // Grab the username or email that the user is logging in with @@ -774,21 +778,6 @@ settings.watch('API_Enable_Rate_Limiter_Limit_Calls_Default', (value) => { API.v1.reloadRoutesToRefreshRateLimiter(); }); -settings.watch('Rate_Limiter_Limit_RegisterUser', (value) => { - const userRegisterRoute = '/api/v1/users.registerpost'; - - // reload rate limiter to REST API - if (rateLimiterDictionary[userRegisterRoute]) { - rateLimiterDictionary[userRegisterRoute].options.numRequestsAllowed = value; - API.v1.reloadRoutesToRefreshRateLimiter(); - } - - // remove old rate limiter rule and create a new one with the updated setting value - DDPRateLimiter.removeRule(registerUserRuleId); - registerUserRuleId = CustomRateLimiter.limitMethod('registerUser', value, settings.get('API_Enable_Rate_Limiter_Limit_Time_Default'), { - userId() { return true; }, - }); -}); settings.watch('Prometheus_API_User_Agent', (value) => { prometheusAPIUserAgent = value; diff --git a/app/api/server/v1/users.js b/app/api/server/v1/users.js index e7a77315b2c2..d50a4bb5c8c4 100644 --- a/app/api/server/v1/users.js +++ b/app/api/server/v1/users.js @@ -2,6 +2,7 @@ import { Meteor } from 'meteor/meteor'; import { Match, check } from 'meteor/check'; import { TAPi18n } from 'meteor/rocketchat:tap-i18n'; import _ from 'underscore'; +import { DDPRateLimiter } from 'meteor/ddp-rate-limiter'; import { Users, Subscriptions } from '../../../models/server'; import { Users as UsersRaw } from '../../../models/server/raw'; @@ -26,6 +27,9 @@ import { resetUserE2EEncriptionKey } from '../../../../server/lib/resetUserE2EKe import { setUserStatus } from '../../../../imports/users-presence/server/activeUsers'; import { resetTOTP } from '../../../2fa/server/functions/resetTOTP'; import { Team } from '../../../../server/sdk'; +import { RateLimiter as CustomRateLimiter } from '../../../lib'; +import { registerUserRuleId } from '../../../../server/methods/registerUser'; + API.v1.addRoute('users.create', { authRequired: true }, { post() { @@ -948,3 +952,15 @@ API.v1.addRoute('users.logout', { authRequired: true }, { }); }, }); + +settings.watch('Rate_Limiter_Limit_RegisterUser', (value) => { + const userRegisterRoute = '/api/v1/users.registerpost'; + + API.v1.updateRateLimiterDictionaryForRoute(userRegisterRoute, value); + + // remove old rate limiter rule and create a new one with the updated setting value + DDPRateLimiter.removeRule(registerUserRuleId); + registerUserRuleId = CustomRateLimiter.limitMethod('registerUser', value, settings.get('API_Enable_Rate_Limiter_Limit_Time_Default'), { + userId() { return true; }, + }); +}); From 270ad615e0917051a7480bf9bacc94ec18187670 Mon Sep 17 00:00:00 2001 From: Leonardo Ostjen Couto Date: Mon, 22 Nov 2021 17:44:21 -0300 Subject: [PATCH 17/17] created a new settings.watch for methods + improved rate limiter dictionary method --- app/api/server/api.js | 5 +++-- app/api/server/v1/users.js | 9 --------- server/methods/registerUser.js | 12 +++++++++++- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/app/api/server/api.js b/app/api/server/api.js index ad649b2d16d6..6a94630edd5c 100644 --- a/app/api/server/api.js +++ b/app/api/server/api.js @@ -447,9 +447,10 @@ export class APIClass extends Restivus { }); } - updateRateLimiterDictionaryForRoute(route, value) { + updateRateLimiterDictionaryForRoute(route, numRequestsAllowed, intervalTimeInMS) { if (rateLimiterDictionary[route]) { - rateLimiterDictionary[route].options.numRequestsAllowed = value; + rateLimiterDictionary[route].options.numRequestsAllowed = numRequestsAllowed ?? rateLimiterDictionary[route].options.numRequestsAllowed; + rateLimiterDictionary[route].options.intervalTimeInMS = intervalTimeInMS ?? rateLimiterDictionary[route].options.intervalTimeInMS; API.v1.reloadRoutesToRefreshRateLimiter(); } } diff --git a/app/api/server/v1/users.js b/app/api/server/v1/users.js index d50a4bb5c8c4..a6c514a7c8ec 100644 --- a/app/api/server/v1/users.js +++ b/app/api/server/v1/users.js @@ -2,7 +2,6 @@ import { Meteor } from 'meteor/meteor'; import { Match, check } from 'meteor/check'; import { TAPi18n } from 'meteor/rocketchat:tap-i18n'; import _ from 'underscore'; -import { DDPRateLimiter } from 'meteor/ddp-rate-limiter'; import { Users, Subscriptions } from '../../../models/server'; import { Users as UsersRaw } from '../../../models/server/raw'; @@ -27,8 +26,6 @@ import { resetUserE2EEncriptionKey } from '../../../../server/lib/resetUserE2EKe import { setUserStatus } from '../../../../imports/users-presence/server/activeUsers'; import { resetTOTP } from '../../../2fa/server/functions/resetTOTP'; import { Team } from '../../../../server/sdk'; -import { RateLimiter as CustomRateLimiter } from '../../../lib'; -import { registerUserRuleId } from '../../../../server/methods/registerUser'; API.v1.addRoute('users.create', { authRequired: true }, { @@ -957,10 +954,4 @@ settings.watch('Rate_Limiter_Limit_RegisterUser', (value) => { const userRegisterRoute = '/api/v1/users.registerpost'; API.v1.updateRateLimiterDictionaryForRoute(userRegisterRoute, value); - - // remove old rate limiter rule and create a new one with the updated setting value - DDPRateLimiter.removeRule(registerUserRuleId); - registerUserRuleId = CustomRateLimiter.limitMethod('registerUser', value, settings.get('API_Enable_Rate_Limiter_Limit_Time_Default'), { - userId() { return true; }, - }); }); diff --git a/server/methods/registerUser.js b/server/methods/registerUser.js index cb48c3088063..5dd2675bc384 100644 --- a/server/methods/registerUser.js +++ b/server/methods/registerUser.js @@ -2,6 +2,7 @@ import { Meteor } from 'meteor/meteor'; import { Match, check } from 'meteor/check'; import { Accounts } from 'meteor/accounts-base'; import s from 'underscore.string'; +import { DDPRateLimiter } from 'meteor/ddp-rate-limiter'; import { Users } from '../../app/models'; import { settings } from '../../app/settings'; @@ -98,8 +99,17 @@ Meteor.methods({ }, }); -export const registerUserRuleId = RateLimiter.limitMethod('registerUser', +let registerUserRuleId = RateLimiter.limitMethod('registerUser', settings.get('Rate_Limiter_Limit_RegisterUser'), settings.get('API_Enable_Rate_Limiter_Limit_Time_Default'), { userId() { return true; }, }); + + +settings.watch('Rate_Limiter_Limit_RegisterUser', (value) => { + // remove old DDP rate limiter rule and create a new one with the updated setting value + DDPRateLimiter.removeRule(registerUserRuleId); + registerUserRuleId = RateLimiter.limitMethod('registerUser', value, settings.get('API_Enable_Rate_Limiter_Limit_Time_Default'), { + userId() { return true; }, + }); +});