Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force email validation before login meteor

Tags:

meteor

login

I use

Accounts.config({
    sendVerificationEmail: true, 
    forbidClientAccountCreation: false
})

to send an email verification when users are created. However, when users signup, they are allowed into the product before they validate their mail, which I don't want.

I tried hacking it by creating a template variable that is true when the user is verified, but the user information arrives after the template is rendered, and even with a Meteor. setTimeout() I haven't been able to update the template when the data arrives.

Any suggestions for the proper way to do this?

Tx

like image 485
Sune Theodorsen Avatar asked Mar 13 '13 10:03

Sune Theodorsen


2 Answers

To stop them logging in at all, you could do this:

Meteor.startup(function() {
  if (Meteor.isServer) {
    var loginAttemptVerifier = function(parameters) {
      if (parameters.user && parameters.user.emails && (parameters.user.emails.length > 0)) {
        // return true if verified email, false otherwise.
        var found = _.find(
                           parameters.user.emails, 
                           function(thisEmail) { return thisEmail.verified }
                          );

        if (!found) {
          throw new Meteor.Error(500, 'We sent you an email.');
        }
        return found && parameters.allowed;
      } else {
        console.log("user has no registered emails.");
        return false;
      }
    }
    Accounts.validateLoginAttempt(loginAttemptVerifier);
  }
});
like image 109
cobberboy Avatar answered Nov 02 '22 20:11

cobberboy


Firstly, you you need to make your data 'unhackable', have a look at the publish functions : http://docs.meteor.com/#meteor_publish

So in your Meteor.publish function for your product you should do something like:

This makes sure the client can only see the product if they are logged in & have a verified account. They can still log in but can't see the products until their account is verified.

Server js

Meteor.publish("productinfo", function () {
  user = Meteor.users.findOne({_id:this.userId})
  if(user) {
      if(user.emails[0].verified) {
          //You can put some extra logic in here to check which product the user has, if you're selling or something like that
          return Products.find({});
      }
   }
});

Keep in mind you need to remove autopublish which meteor uses to make life a bit easier, it basically publishes all the collections down to the user, but you want to restrict certain info so you should remove it

Secondly you need to handle the data on your template so that if the user is not logged in the template stuff isn't visible. So even in that step when the browser is initially loading they won't see the products

Client JS

Meteor.subscribe("productinfo");

Template.products.products = function() {
  if(Meteor.userId()) {
    if(Meteor.user().emails[0].verified) {
        return Product.findOne({_id:"your product id"});
    }
  }
}

This way the template helper checks if the user is logged in & they have a verified account. In addition if the code was changed on the client side they would not see the product because of the publish function.

like image 33
Tarang Avatar answered Nov 02 '22 18:11

Tarang