Skip to content
This repository has been archived by the owner. It is now read-only.

feat(sms): Add support for rate-limiting sms actions #161

Merged
merged 7 commits into from Feb 9, 2017
Merged

Conversation

@vbudhram
Copy link
Contributor

@vbudhram vbudhram commented Jan 31, 2017

Fixes #160

This PR adds the following support to the custom's server:

  • Rate limit sending X amount of sms to a specific number
  • Rate limit an ip sending X total amount of sms

Connects with mozilla/fxa-features#53, mozilla/fxa-auth-server#1628

@vbudhram vbudhram added the WIP label Jan 31, 2017
@vbudhram vbudhram self-assigned this Jan 31, 2017
@shane-tomlinson shane-tomlinson added this to the FxA-53: Email Confirmation Flow - SMS (Phase 2) milestone Jan 31, 2017
@vbudhram
Copy link
Contributor Author

@vbudhram vbudhram commented Feb 2, 2017

@philbooth @rfk This provides the rate limiting functionality for sms requests. r?

@rfk
Copy link
Member

@rfk rfk commented Feb 2, 2017

@vbudhram this looks solid at a first glance, hopefully I can find the time for a thorough review soon.

But you're right that it also really highlights the need for some serious refactoring in this repo! Let's chat next week about putting a plan in place to untangle the web of logic we've woven here over the years.

format: 'nat',
env: 'SMS_RATE_LIMIT_INTERVAL_SECONDS'
},
maxSMSs: {

This comment has been minimized.

@philbooth

philbooth Feb 2, 2017
Contributor

I'm not a fan of the capitalisation here, especially as it's all lower case above. I suspect you did it because the pluralised double-s looks funny in lower case, but maybe that's a reason to ditch the plural. maxSms?

This comment has been minimized.

@vbudhram

vbudhram Feb 2, 2017
Author Contributor

Heh guess a pattern that I thought made sense to me was to capitalize acronyms only if in between words. No issues changing to maxSmss.


isSMSSendingAction: function isSMSSendingAction(action) {

This comment has been minimized.

@philbooth

philbooth Feb 2, 2017
Contributor

If you switched to ES6 style here, we could end the senseless tyranny of double-named functions that's blighting this module.

This comment has been minimized.

@vbudhram

vbudhram Feb 2, 2017
Author Contributor

Removed the extra function names but couldn't go full ES6, #164.

@@ -123,6 +124,32 @@ module.exports = function (limits, now) {
this.as = this._trim(now, this.as, limits.maxAccountStatusCheck)
}

IpRecord.prototype.isOverSMSLimit = function () {
this.trimSMSRequests(now())

This comment has been minimized.

@philbooth

philbooth Feb 2, 2017
Contributor

...oh you've capitalised them here as well. I don't know, feel free to ignore what I said above in that case, just as long as it's upper-cased everywhere. A sometimes-uppercase-but-sometimes-lowercase mish-mash would keep me awake at night.

// Limit based on number of unique sms request sent by this IP
var count = 0
var seen = {}
this.sms.forEach(function(info) {

This comment has been minimized.

@philbooth

philbooth Feb 2, 2017
Contributor

...but then I see this little guy and I think, no, all-caps is madness.

var count = 0
var seen = {}
this.sms.forEach(function(info) {
if (!(info.u in seen)) {

This comment has been minimized.

@philbooth

philbooth Feb 2, 2017
Contributor

I can see they're used elsewhere here but, for the record, I'm not a fan of these one-character (and two-character) property names. It's like we're explicitly trying to make the code harder to follow. Using t instead of time at least has an element of logic, but why u for the phone number? Am I missing something?

This comment has been minimized.

@vbudhram

vbudhram Feb 2, 2017
Author Contributor

Yea I agree, it is unnecessarily hard to read. Had to use info.u because I was reusing the logic for trimming hits in the record. This being said, I created the following issue #163 so that customs server gets some more ♥️.

This comment has been minimized.

@rfk

rfk Feb 8, 2017
Member

FWIW the u in other places here was for "user".

// Check against SMS records to make sure that this request
// can send SMS
if (smsNumber) {
promises.push(mc.getAsync(smsNumber).then(smsRecord.parse, smsRecord.parse))

This comment has been minimized.

@philbooth

philbooth Feb 2, 2017
Contributor

Scrolls up to the top of the file to look for what mc means. Scrolls back down.

var rec = new SMSRecord()
object = object || {}
rec.rl = object.rl // timestamp when the account was rate-limited
rec.xs = object.xs || [] // timestamps when sms were sent

This comment has been minimized.

@philbooth

philbooth Feb 2, 2017
Contributor

Sigh

This comment has been minimized.

@vbudhram

vbudhram Feb 2, 2017
Author Contributor

@rfk Looking back at code, these records get read/written to memcache. Is that why the code is using as small a possible var names? This pattern was before my time.

This comment has been minimized.

@rfk

rfk Feb 2, 2017
Member

Yes, IIRC exactly this, those properties go straight into memcache as JSON so this was designed to keep the memory pressure down.

This comment has been minimized.

@rfk

rfk Feb 2, 2017
Member

(which is not to argue that it's the right tradeoff today, just to explain why it's there)

This comment has been minimized.

@rfk

rfk Feb 8, 2017
Member

OK, I'll admit, I have no idea what "xs" is supposes to stand for in the email_record class, nor here. But at least it's consistent between the two I suppose...

@philbooth
Copy link
Contributor

@philbooth philbooth commented Feb 2, 2017

Looks fine to me @vbudhram, although I'm not very familiar with this repo so that probably doesn't qualify as an official r+.

This is not aimed at you, but the variable/property names in this repo are completely mad, aren't they?

// Actions that can send sms, and could make us
// very annoying to a user if abused.
const SMS_SENDING_ACTION = {
inviteUserSms: true

This comment has been minimized.

@vladikoff

vladikoff Feb 2, 2017
Contributor

what's the logic behind this inviteUserSms name?

This comment has been minimized.

@vbudhram

vbudhram Feb 3, 2017
Author Contributor

I should have made a note about this. Since the auth-server sms endpoint will be generic, I needed some way to differentiate the type of sms being sent. Currently, this should only be for inviting users, however I could see us reusing the sms endpoint for 2FA etc. I am open for other another name.

This comment has been minimized.

@vbudhram

vbudhram Feb 3, 2017
Author Contributor

@vladikoff Thought about it some more and really what is happening is the user is sending an sms to connect a device, not inviting a user. Renamed to connectDeviceSms.

@vladikoff
Copy link
Contributor

@vladikoff vladikoff commented Feb 6, 2017

Fixes #160

@rfk
rfk approved these changes Feb 8, 2017
var rec = new SMSRecord()
object = object || {}
rec.rl = object.rl // timestamp when the account was rate-limited
rec.xs = object.xs || [] // timestamps when sms were sent

This comment has been minimized.

@rfk

rfk Feb 8, 2017
Member

OK, I'll admit, I have no idea what "xs" is supposes to stand for in the email_record class, nor here. But at least it's consistent between the two I suppose...

@rfk
Copy link
Member

@rfk rfk commented Feb 8, 2017

r+, but with the caveat that we're going to get cracking on that long-overdue refactor in this repo, as discussed IRL earlier today :-)

@vbudhram vbudhram merged commit dd30b0e into master Feb 9, 2017
3 checks passed
3 checks passed
continuous-integration/travis-ci/pr The Travis CI build passed
Details
continuous-integration/travis-ci/push The Travis CI build passed
Details
coverage/coveralls Coverage increased (+0.3%) to 95.441%
Details
@vbudhram
Copy link
Contributor Author

@vbudhram vbudhram commented Feb 9, 2017

@rfk @philbooth Thanks guys!

@shane-tomlinson
Copy link
Member

@shane-tomlinson shane-tomlinson commented Feb 9, 2017

🥇

@shane-tomlinson shane-tomlinson deleted the add-sms-support branch Feb 9, 2017
module.exports = {

isPasswordCheckingAction: function isPasswordCheckingAction(action) {

This comment has been minimized.

@vladikoff

vladikoff Feb 9, 2017
Contributor

this was here because it is useful during debugging / testing, but we can live without it I hope

This comment has been minimized.

@vbudhram

vbudhram Feb 9, 2017
Author Contributor

I think it will be ok? I don't mind adding it back if we need it.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

5 participants