Skip to content

Commit 4cc907f

Browse files
committed
Updating docs and fixing code review comments.
1 parent 50d3437 commit 4cc907f

8 files changed

Lines changed: 626 additions & 429 deletions

File tree

docs/client/data.js

Lines changed: 480 additions & 330 deletions
Large diffs are not rendered by default.

docs/client/full-api/api/accounts.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -401,14 +401,14 @@ client, no arguments are passed.
401401

402402
<h3 id="accounts_rate_limit"><span>Rate Limiting</span></h3>
403403

404-
By default, there are rules added to the [`DDPRateLimiter`](#DDPRateLimiter)
404+
By default, there are rules added to the [`DDPRateLimiter`](#ddpratelimiter)
405405
that rate limit logins, new user registration and password reset calls to a
406-
limit of 5 requests per 10 seconds per IP address. These are a basic solution
406+
limit of 5 requests per 10 seconds per session. These are a basic solution
407407
to dictionary attacks where a malicious user attempts to guess the passwords
408408
of legitimate users by attempting all possible passwords.
409409

410410
These rate limiting rules can be removed by calling
411411
`Accounts.removeDefaultRateLimit()`. Please see the
412-
[`DDPRateLimiter`](#DDPRateLimiter) docs for more information.
412+
[`DDPRateLimiter`](#ddpratelimiter) docs for more information.
413413

414414
{{/template}}

docs/client/full-api/api/methods.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,22 @@ options about how the client executes the method.
182182

183183
<h2 id="ddpratelimiter"><span>DDPRateLimiter</span></h2>
184184

185-
A rate limiter added directly to DDP. The DDPRateLimiter allows you to add rules to limit calls by one or more of user IDs, IP addresses, method names and/or subscription names. The rate limiter is called on every method and subscription invocation. A default rule of limiting 'login' attempts to 5 calls every 10 seconds per IP address has been added to the [`Accounts base package`](#accounts_api). The rule can be removed by calling [`Accounts.removeDefaultRateLimit()`].
185+
The DDPRateLimiter allows users to add rules to limit calls to Meteor methods
186+
and subscriptions by one or more of user IDs, IP addresses, sessions, and
187+
method & subscription names. The rate limiter is called on every method and
188+
subscription invocation. A default rule of limiting login, password reset and
189+
new user creation attempts to 5 calls every 10 seconds per session has been
190+
added to the [`accounts package`](#accounts_api). The rule can be removed by
191+
calling `Accounts.removeDefaultRateLimit()`.
192+
193+
The DDPRateLimiter is configured with a set of rules. Each rule is a set of
194+
keys to be inspected with filters on those keys to specify all DDP messages
195+
that satisfy the rule. Each of these possible messages that satisfy the rule
196+
is given a bucket by creating a unique string composed of all the keys in the
197+
rule and the values from the message. After each rule's specified time
198+
interval, all the buckets are deleted. A rate limit is said to have been hit
199+
when a bucket has reached the rule's capacity, at which point errors will be
200+
returned for that input until the buckets are reset.
186201

187202
{{> autoApiBox "DDPRateLimiter.addRule"}}
188203
{{> autoApiBox "DDPRateLimiter.removeRule"}}

docs/client/full-api/tableOfContents.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ var toc = [
4040
{instance: "this", name: "stop", id: "publish_stop"},
4141
{instance: "this", name: "connection", id: "publish_connection"}
4242
],
43-
"Meteor.subscribe"
43+
"Meteor.subscribe",
44+
{name: "DDPRateLimiter", id: "ddpratelimiter"}
4445
],
4546

4647
{name: "Methods", id: "methods_header"}, [
@@ -54,7 +55,7 @@ var toc = [
5455
"Meteor.Error",
5556
"Meteor.call",
5657
"Meteor.apply",
57-
{name: "DDPRateLimiter", id: "ddpratelimiter"},
58+
{name: "DDPRateLimiter", id: "ddpratelimiter"}
5859
],
5960

6061
{name: "Check", id: "check_package"}, [

docs/client/names.json

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,28 @@
11
[
2+
"Accounts",
23
"Accounts",
34
"Accounts.changePassword",
4-
"Accounts.config",
55
"Accounts.createUser",
66
"Accounts.emailTemplates",
77
"Accounts.forgotPassword",
8-
"Accounts.onCreateUser",
9-
"Accounts.onEmailVerificationLink",
10-
"Accounts.onEnrollmentLink",
11-
"Accounts.onLogin",
12-
"Accounts.onLoginFailure",
13-
"Accounts.onResetPasswordLink",
148
"Accounts.resetPassword",
159
"Accounts.sendEnrollmentEmail",
1610
"Accounts.sendResetPasswordEmail",
1711
"Accounts.sendVerificationEmail",
1812
"Accounts.setPassword",
1913
"Accounts.ui",
2014
"Accounts.ui.config",
21-
"Accounts.validateLoginAttempt",
22-
"Accounts.validateNewUser",
2315
"Accounts.verifyEmail",
16+
"Ap.config",
17+
"Ap.onCreateUser",
18+
"Ap.onEmailVerificationLink",
19+
"Ap.onEnrollmentLink",
20+
"Ap.onLogin",
21+
"Ap.onLoginFailure",
22+
"Ap.onResetPasswordLink",
23+
"Ap.userId",
24+
"Ap.validateLoginAttempt",
25+
"Ap.validateNewUser",
2426
"App",
2527
"App.accessRule",
2628
"App.configurePlugin",
@@ -86,6 +88,9 @@
8688
"DDPCommon.MethodInvocation#setUserId",
8789
"DDPCommon.MethodInvocation#unblock",
8890
"DDPCommon.MethodInvocation#userId",
91+
"DDPRateLimiter.addRule",
92+
"DDPRateLimiter.removeRule",
93+
"DDPRateLimiter.setErrorMessage",
8994
"EJSON",
9095
"EJSON.CustomType",
9196
"EJSON.CustomType#clone",
@@ -138,7 +143,7 @@
138143
"Meteor.status",
139144
"Meteor.subscribe",
140145
"Meteor.user",
141-
"Meteor.userId",
146+
"Meteor.users",
142147
"Meteor.users",
143148
"Meteor.wrapAsync",
144149
"Mongo",
@@ -148,6 +153,8 @@
148153
"Mongo.Collection#find",
149154
"Mongo.Collection#findOne",
150155
"Mongo.Collection#insert",
156+
"Mongo.Collection#rawCollection",
157+
"Mongo.Collection#rawDatabase",
151158
"Mongo.Collection#remove",
152159
"Mongo.Collection#update",
153160
"Mongo.Collection#upsert",

packages/ddp-rate-limiter/ddp-rate-limiter.js

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
// Rate Limiter built into DDP with a default error message.
22
DDPRateLimiter = {
33
errorMessage : function (rateLimitResult) {
4-
return "Error, too many requests. Please slow down. You must wait " + Math.ceil(
5-
rateLimitResult.timeToReset / 1000) + " seconds before trying again.";
4+
return "Error, too many requests. Please slow down. You must wait " +
5+
Math.ceil(rateLimitResult.timeToReset / 1000) + " seconds before trying " +
6+
"again.";
67
},
78
rateLimiter : new RateLimiter()
89
}
@@ -15,17 +16,24 @@ DDPRateLimiter.getErrorMessage = function (rateLimitResult) {
1516
}
1617
/**
1718
* @summary Update the error message returned when call is rate limited.
18-
* @param {string|function} message Function that takes an object with a timeToReset field that specifies the first time a method or subscription call is allowed
19+
* @param {string|function} message Function that takes an object with a
20+
* timeToReset field that specifies the first time a method or subscription
21+
* call is allowed.
1922
*/
2023
DDPRateLimiter.setErrorMessage = function (message) {
2124
this.errorMessage = message;
2225
}
2326

2427
/**
2528
* @summary Adds a rule with a number of requests allowed per time interval.
26-
* @param {object} rule Rule should be an object where the keys are one or more of `['userId', 'ipAddr', 'type', 'name'] ` and the values are either `null`, a primitive, or a function that returns true if the rule should apply to the provided input for that key.
27-
* @param {integer} numRequests number of requests allowed per time interval. Default = 10.
28-
* @param {integer} timeInterval time interval in milliseconds after which rule's counters are reset. Default = 1000.
29+
* @param {object} rule Rule should be an object where the keys are one or
30+
* more of `['userId', 'ipAddr', 'type', 'name', 'sessionId'] ` and the values
31+
* are either `null`, a primitive, or a function that returns true if the rule
32+
* should apply to the provided input for that key.
33+
* @param {integer} numRequests number of requests allowed per time interval.
34+
* Default = 10.
35+
* @param {integer} timeInterval time interval in milliseconds after which
36+
* rule's counters are reset. Default = 1000.
2937
* @return {string} Returns unique `ruleId` that can be passed to `removeRule`.
3038
*/
3139
DDPRateLimiter.addRule = function (rule, numRequests, timeInterval) {
@@ -41,6 +49,8 @@ DDPRateLimiter.removeRule = function (id) {
4149
return this.rateLimiter.removeRule(id);
4250
}
4351

52+
// This is accessed inside livedata_server.js, but shouldn't be called by any
53+
// user.
4454
DDPRateLimiter._increment = function (input) {
4555
this.rateLimiter.increment(input);
4656
}

packages/ddp-server/livedata_server.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -580,12 +580,17 @@ _.extend(Session.prototype, {
580580
// reconnect.
581581
return;
582582

583+
// XXX It'd be much better if we had generic hooks where any package can
584+
// hook into subscription handling, but in the mean while we special case
585+
// ddp-rate-limiter package. This is also done for weak requirements to
586+
// add the ddp-rate-limiter package in case we don't have Accounts. A
587+
// user trying to use the ddp-rate-limiter must explicitly require it.
583588
if (Package['ddp-rate-limiter']) {
584589
var DDPRateLimiter = Package['ddp-rate-limiter'].DDPRateLimiter;
585590
var rateLimiterInput = {
586591
userId: self.userId,
587592
ipAddr: self.connectionHandle.clientAddress,
588-
type: msg.msg,
593+
type: "sub",
589594
name: msg.name,
590595
sessionId: self.id
591596
};
@@ -667,12 +672,16 @@ _.extend(Session.prototype, {
667672
});
668673

669674
try {
675+
// XXX It'd be better if we could hook into method handlers better but
676+
// for now, we need to check if the ddp-rate-limiter exists since we
677+
// have a weak requirement for the ddp-rate-limiter package to be added
678+
// to our application.
670679
if (Package['ddp-rate-limiter']) {
671680
var DDPRateLimiter = Package['ddp-rate-limiter'].DDPRateLimiter;
672681
var rateLimiterInput = {
673682
userId: self.userId,
674683
ipAddr: self.connectionHandle.clientAddress,
675-
type: msg.msg,
684+
type: "method",
676685
name: msg.method,
677686
sessionId: self.id
678687
};

0 commit comments

Comments
 (0)