Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[fix #8218] cleaning up reset tokens also cleans up enroll tokens #8474

Merged
merged 5 commits into from
Mar 29, 2017
Merged

[fix #8218] cleaning up reset tokens also cleans up enroll tokens #8474

merged 5 commits into from
Mar 29, 2017

Conversation

mutdmour
Copy link
Contributor

@mutdmour mutdmour commented Mar 10, 2017

The issue was with _.extend overriding two documents (a token filter by reason and a time filter) with the same key ($or). Put the two filters in an ($add) to solve the issue, and added two tests to ensure no interference between those two.

Fixes #8218

@abernix abernix changed the title fix for bug #8218: cleaning up reset tokens also cleans up enroll tokens [fix #8218] cleaning up reset tokens also cleans up enroll tokens Mar 11, 2017
Copy link
Contributor

@abernix abernix left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks very much for working on this! Looks good functionality wise, but just a few formatting changes if you don't mind?

@@ -1697,6 +1697,34 @@ if (Meteor.isServer) (function () {
}
)

Tinytest.add(
'passwords - enroll tokens don\'t get cleaned up when reset tokens are cleaned up',
Copy link
Contributor

@abernix abernix Mar 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please just use double quotes around this to avoid the need to escape the '.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will fix it. There was another test that I based this on.
Tinytest.add( 'passwords - reset password doesn\t work if email changed after email sent',
Now I look closely and realize that was a typo. I can fix this as well.

Accounts._expirePasswordResetTokens(new Date(), userId);

test.isTrue(Meteor.users.findOne(userId).services.password.reset);
}
Copy link
Contributor

@abernix abernix Mar 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No real preference about how you format your commands and the assertions that follow them, but please try to make them consistent – maybe like this?

var userId = ...

Accounts.sendEnrollmentEmail(userId, email);
test.isTrue(!!Meteor.users.findOne(userId).services.password.reset);

Accounts._expirePasswordResetTokens(new Date(), userId);
test.isTrue(Meteor.users.findOne(userId).services.password.reset);

Copy link
Contributor Author

@mutdmour mutdmour Mar 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, I can change that, though this was consistent with the other tests in the same file.

test.isTrue(!!Meteor.users.findOne(userId).services.password.reset);

Accounts._expirePasswordEnrollTokens(new Date(), userId);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same questions as above.

var email = test.id + '-intercept@example.com';
var userId = Accounts.createUser({email: email, password: 'password'});
Accounts.sendEnrollmentEmail(userId, email);
test.isTrue(!!Meteor.users.findOne(userId).services.password.reset);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain why you're using !! on this test? If you're trying to coerce something, perhaps it would be better to use a different test? Either way, it's not clear if you're trying to explicitly test for something different than the test.isTrue below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did it mostly to stay consistent with the rest of the tests on token cleanup. I have looked into it and I don't see why use !!. Meteor.users.findOne(userId).services.password.reset returns an object or undefined. At first I thought it was to handle empty object case {}. Though both cases test.isTrue({}) and test.isTrue(!!{}) are true. Both cases test.isTrue(undefined) and test.isTrue(!!undefined) are false. I can remove the !!. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could do without the the coercion notation (!!) however I believe this test is trying to test that it is entirely unchanged (right?) so it should probably test for exactly the same thing (i.e. with !!).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not to test if it's exactly the same thing. It's test for existence of the reset or enroll token object, which is added in the line before.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean that when line 1710 runs Meteor.users.findOne(userId).services.password.reset, it's meant to make sure that it's the same as when it ran on line 1706, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes exactly. Maybe it's better to test for equality then directly.
var resetToken = Meteor.users.findOne(userId).services.password.reset;
test.isTrue(resetToken);
Accounts._expirePasswordResetTokens(new Date(), userId);
test.isEqual(resetToken, Meteor.users.findOne(userId).services.password.reset);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that sounds best to me. Mind making the fix? Then I think we're good to go.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

{ "services.password.reset.when": { $lt: oldestValidDate } },
{ "services.password.reset.when": { $lt: +oldestValidDate } }
]
}]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize the formatting here wasn't great to begin with, but this could still use some cleaning up - we should take this opportunity to fix it.

At the very least, with this complexity, the $or should become a variable:

  const resetRangeOr = {
    $or: [
      "services.password.reset.when": { $lt: oldestValidDate } },
      "services.password.reset.when": { $lt: +oldestValidDate } },
    ],
  };

Then, we should fix the indentation and stop extend-ing into a variable name which doesn't make sense after it's changed (Since _.extend mutates the first parameter, and then it's no longer the userFilter once the tokenFilter and resetRange are in there):

accounts.users.update(
  _.extend(
    {},
    userFilter,
    { $and: [ tokenFilter, resetRangeOr ] }
  )
);

Or instead of the last suggestion (though I realize this doesn't match the existing code, it's much more clear):

  // resetRangeOr and userFilter are already defined above.
  const expireFilter = { $and: [tokenFilter, resetRangeOf] };

  accounts.users.update({ ...userFilter, ...expireFilter });

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question, what's this ... notation? I have not seen it before and a hard one to get an answer for from google. why does it solve my "unknown operator" issue?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great question, and hard to search for dots on Google. 😄

This is Object spread notation, taking advantage of the Spread operator but using a Stage-3 ECMAScript proposal seen here. Stage-3 proposals are very likely to become a part of the official specification and we have enabled in Meteor via babel-preset-meteor.

@abernix
Copy link
Contributor

abernix commented Mar 24, 2017

I think your 00a2cb8 failed because of a problematic commit on the devel branch. If you rebase off devel and try again it should work. (And I think you can revert your attempt to fix it with b6d687e 😄)

Sorry for the troubles!

@mutdmour
Copy link
Contributor Author

@abernix I think this is ready. Let me know if there's anything else needed. I have a fix for another issue ready but cannot create branches. Can you add me as a collaborator so I can create branches?

@hwillson
Copy link
Contributor

@mutdmour Since you're working off of your own fork, you can create as many branches as you want there. When you're ready to submit your PR, you can then do so from your branch. Creating branches within the Meteor project itself is very tightly controlled (to try to keep things nice and clean), and not necessary for submitting bug fix / feature request PR's.

@mutdmour
Copy link
Contributor Author

@hwillson Thanks ya, that makes sense. I thought I could not create branches on my fork either, but I just tried doing it locally first and that worked.

@abernix abernix merged commit 1f83143 into meteor:devel Mar 29, 2017
abernix pushed a commit that referenced this pull request Mar 29, 2017
)

* solved issue 8218 with expireresettoken removing enroll tokens

* style fix

* tests fix

* solved issue 8218 with expireresettoken removing enroll tokens

* style fix
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants