Updating the email address in Meteor.js user accounts - meteor

I've been troubleshooting a lot of user errors today, using Meteor.js and the Accounts-ui-bootstrap3 package. So far my favorite error is the 'Token Expired' on a password reset, but the one that really causes issues is 'User Not Found' when the correct email address is entered in. It took a while to work out, but the problem is caused by accounts created with the email address in all caps. Apparently Accounts is case sensitive for email addresses.
Now while I have since updated all of my code to lowercase incoming user emails, I still have to fix the existing users. I created a server method to deal with this:
Meteor.methods({
sanitizeEmails: function() {
Meteor.users.find({
'emails.address': /[A-Z]{1,}/
}).map(function(user) {
console.log(user.emails[0].address);
Meteor.users.update({
_id: user._id
}, {
$set: {
'emails.0.address': user.emails[0].address.toLowerCase()
}
});
});
}
});
Which should go through, find any names with an upper case letter, and update the email address to a lower case version. It doesn't work, it throws an index error in the MongoDB driver:
I20150904-01:30:23.322(-7)? Exception while invoking method 'normalizeEmails' MongoError: E11000 duplicate key error index: meteor.users.$emails.address_1 dup key: { : "usedtobetaller#fixemandhow.com" }
I20150904-01:30:23.322(-7)? at Object.Future.wait (/home/mowgli/.meteor/packages/meteor-tool/.1.1.4.70jrul++os.linux.x86_64+web.browser+web.cordova/mt-os.linux.x86_64/dev_bundle/server-lib/node_modules/fibers/future.js:398:15)
I20150904-01:30:23.323(-7)? at [object Object].<anonymous> (packages/meteor/helpers.js:119:1)
I20150904-01:30:23.323(-7)? at [object Object].MongoConnection.(anonymous function) [as update] (packages/mongo/mongo_driver.js:678:1)
I20150904-01:30:23.323(-7)? at [object Object].Mongo.Collection.(anonymous function) [as update] (packages/mongo/collection.js:575:1)
I20150904-01:30:23.323(-7)? at server/main.invitePub.coffee:320:22
I20150904-01:30:23.323(-7)? at packages/mongo/mongo_driver.js:974:1
I20150904-01:30:23.323(-7)? at [object Object]._.extend.forEach (packages/mongo/mongo_driver.js:965:1)
I20150904-01:30:23.323(-7)? at [object Object]._.extend.map (packages/mongo/mongo_driver.js:973:1)
I20150904-01:30:23.323(-7)? at [object Object].Cursor.(anonymous function) [as map] (packages/mongo/mongo_driver.js:812:1)
I20150904-01:30:23.324(-7)? at [object Object].Meteor.methods.normalizeEmails (server/main.invites.coffee:317:56)
I20150904-01:30:23.324(-7)? - - - - -
I20150904-01:30:23.324(-7)? at Object.toError (/home/mowgli/.meteor/packages/mongo/.1.1.0.zb7oxo++os+web.browser+web.cordova/npm/node_modules/mongodb/lib/mongodb/utils.js:114:11)
I20150904-01:30:23.324(-7)? at /home/mowgli/.meteor/packages/mongo/.1.1.0.zb7oxo++os+web.browser+web.cordova/npm/node_modules/mongodb/lib/mongodb/collection/core.js:577:27
I20150904-01:30:23.324(-7)? at /home/mowgli/.meteor/packages/mongo/.1.1.0.zb7oxo++os+web.browser+web.cordova/npm/node_modules/mongodb/lib/mongodb/db.js:1195:7
I20150904-01:30:23.324(-7)? at /home/mowgli/.meteor/packages/mongo/.1.1.0.zb7oxo++os+web.browser+web.cordova/npm/node_modules/mongodb/lib/mongodb/db.js:1903:9
I20150904-01:30:23.324(-7)? at Server.Base._callHandler (/home/mowgli/.meteor/packages/mongo/.1.1.0.zb7oxo++os+web.browser+web.cordova/npm/node_modules/mongodb/lib/mongodb/connection/base.js:453:41)
I20150904-01:30:23.324(-7)? at /home/mowgli/.meteor/packages/mongo/.1.1.0.zb7oxo++os+web.browser+web.cordova/npm/node_modules/mongodb/lib/mongodb/connection/server.js:487:18
I20150904-01:30:23.324(-7)? at [object Object].MongoReply.parseBody (/home/mowgli/.meteor/packages/mongo/.1.1.0.zb7oxo++os+web.browser+web.cordova/npm/node_modules/mongodb/lib/mongodb/responses/mongo_reply.js:68:5)
I20150904-01:30:23.325(-7)? at [object Object].<anonymous> (/home/mowgli/.meteor/packages/mongo/.1.1.0.zb7oxo++os+web.browser+web.cordova/npm/node_modules/mongodb/lib/mongodb/connection/server.js:445:20)
I20150904-01:30:23.325(-7)? at [object Object].emit (events.js:95:17)
I20150904-01:30:23.325(-7)? at [object Object].<anonymous> (/home/mowgli/.meteor/packages/mongo/.1.1.0.zb7oxo++os+web.browser+web.cordova/npm/node_modules/mongodb/lib/mongodb/connection/connection_pool.js:207:13)
EDIT:
Apparently I have duplicate emails, so Accounts-UI emails are case sensitive. It's entirely possible to end up with three users bob#email.com, Bob#email.com, and BOB#email.com.
I'm leaving this up as a cautionary tale and a simple example of updating email addresses in Meteor

This is a little hardcore for this issue, however this code will keep ANY account from getting created (even on the server) with caps in the email address:
if (Meteor.isServer) {
Accounts.validateNewUser(function(user) {
if (user.emails[0].address.match(/[A-Z]{1,}/) {
throw new Meteor.Error(403, "Emails may only be lowercase.");
return false;
}
return true;
});
}

I did some testing and accounts package do not let you create two users with the same email (it's not case-sensitive).
I've tried creating two users: "alex#email.com" and "Alex#email.com"
On the second try I get: "Email already exists."
I think that your mongo search is not correct:
Meteor.users.find({
'emails.address': /[A-Z]{1,}/
})
'emails.address' is not a valid key for searching, 'emails' is an array.
I think the correct syntax would be:
Meteor.users.find({
emails: {
$elemMatch: {
address: /[A-Z]{1,}/
}
}
})

Related

where to write the AutoForm.addHooks() code to manipulate the submitted autoform values

Below is the hook code that I want to use to manipulate the submitted values from QuickForm.
var hooksObject = {
before: {
insert: function(doc) {
console.log(doc);
return doc;
}
}
};
AutoForm.addHooks('insertBankDetailForm', hooksObject, true);
I have read the docs and it says "These calls should be anywhere in top-level client code and do not need to be within Meteor.startup. You should not put them in an autorun, template rendered function, or anywhere else where they will be called multiple times since that will cause the hooks to run multiple times for a single submission."
I tried placing the code most of the places, but I am unable to understand the location where it need to be kept. I get below error when I use above code in index.js at location D:\PROJECT\imports\startup\client\index.js
Error: Oops! Did you forget to return the modified document from your docToForm hook for the insertBankDetailForm form?
at autoFormEachDocToForm (aldeed_autoform.js?hash=62240ad…:6595)
at Array.forEach (<anonymous>)
at Function._.each._.forEach (underscore.js?hash=cde485f…:149)
at Blaze.View.<anonymous> (aldeed_autoform.js?hash=62240ad…:6592)
at blaze.js?hash=f33d3df…:1934
at Function.Template._withTemplateInstanceFunc (blaze.js?hash=f33d3df…:3744)
at blaze.js?hash=f33d3df…:1932
at Object.Blaze._withCurrentView (blaze.js?hash=f33d3df…:2271)
at viewAutorun (blaze.js?hash=f33d3df…:1931)
at Tracker.Computation._compute (tracker.js?hash=997515f…:339)
meteor.js?hash=27829e9…:930 Exception from Tracker recompute function:
meteor.js?hash=27829e9…:930 TypeError: Cannot read property 'setMembers' of undefined
at doMaterialize (blaze.js?hash=f33d3df…:2093)
at Object.Tracker.nonreactive (tracker.js?hash=997515f…:640)
at Blaze.View.doRender (blaze.js?hash=f33d3df…:2090)
at blaze.js?hash=f33d3df…:1934
at Function.Template._withTemplateInstanceFunc (blaze.js?hash=f33d3df…:3744)
at blaze.js?hash=f33d3df…:1932
at Object.Blaze._withCurrentView (blaze.js?hash=f33d3df…:2271)
at viewAutorun (blaze.js?hash=f33d3df…:1931)
at Tracker.Computation._compute (tracker.js?hash=997515f…:339)
at Tracker.Computation._recompute (tracker.js?hash=997515f…:358)
aldeed_autoform.js?hash=62240ad…:2037 Uncaught TypeError: Cannot read property 'removeEmptyStrings' of undefined
at Object.autoFormGetFormValues [as getFormValues] (aldeed_autoform.js?hash=62240ad…:2037)
at autoFormRegFormCallback (aldeed_autoform.js?hash=62240ad…:6575)
at aldeed_autoform.js?hash=62240ad…:670
at Function._.each._.forEach (underscore.js?hash=cde485f…:157)
at formPreserveConstructor.FormPreserve._retrieveRegisteredDocuments (aldeed_autoform.js?hash=62240ad…:669)
at Object.callback (aldeed_autoform.js?hash=62240ad…:628)
at pollProviders (reload.js?hash=02487cd…:180)
at Object.Reload._migrate (reload.js?hash=02487cd…:198)
at reload.js?hash=02487cd…:252
at underscore.js?hash=cde485f…:717
NOTE: Any help would be deeply appreciated and rewarded.

Error after update to Meteor 1.3 - Handler with name 'onBeforeAction' already exists

My app has been working until I've updated it to Meteor 1.3. Now I get this error:
Exception in callback of async function: Error: Handler with name 'onBeforeAction' already exists.
at MiddlewareStack._create (http://localhost:3000/packages/iron_middleware-stack.js?hash=8a2aa73e86a32698fb9f60cea452e0ecb2e72b7f:190:13)
at MiddlewareStack.push (http://localhost:3000/packages/iron_middleware-stack.js?hash=8a2aa73e86a32698fb9f60cea452e0ecb2e72b7f:206:22)
at http://localhost:3000/packages/iron_middleware-stack.js?hash=8a2aa73e86a32698fb9f60cea452e0ecb2e72b7f:224:12
at Array.forEach (native)
at Function._.each._.forEach (http://localhost:3000/packages/underscore.js?hash=8de51f9d86e95ae2ffee15a8db324a1decccba3e:139:11)
at MiddlewareStack.append (http://localhost:3000/packages/iron_middleware-stack.js?hash=8a2aa73e86a32698fb9f60cea452e0ecb2e72b7f:220:5)
at http://localhost:3000/packages/iron_middleware-stack.js?hash=8a2aa73e86a32698fb9f60cea452e0ecb2e72b7f:226:19
at Array.forEach (native)
at Function._.each._.forEach (http://localhost:3000/packages/underscore.js?hash=8de51f9d86e95ae2ffee15a8db324a1decccba3e:139:11)
at MiddlewareStack.append (http://localhost:3000/packages/iron_middleware-stack.js?hash=8a2aa73e86a32698fb9f60cea452e0ecb2e72b7f:220:5)
The only places where I use onBeforeAction is in my iron-router route controllers. They're all in the same router.js file.
I define several route controllers, first an ApplicationController that extends RouteController and then various controllers that extend ApplicationController.
ApplicationController = RouteController.extend({
onBeforeAction: function() {
//some code
this.next();
}
});
SomeController = ApplicationController.extend({
onBeforeAction: function() {
//some code
this.next();
}
});
From the error message I'm unable to work out what is wrong or where to look for the problem.
Versions of packages mentioned in error message are:
iron:router#1.0.12
iron:middleware-stack#1.0.11
underscore#1.0.6
I'd really appreciate some pointers in the right direction.
First of i would highly recommend you if it is possible to change your router and switch to FlowRouter. This is the official Meteor router by now, as stated here : Meteor Guide
Try this : meteor update iron:middleware-stack.
It seems that your problem is related to this issue and it has been fixed in 1.1.0 version.

Meteor audit-argument-checks

I have a Meteor project where I'm using audit-argument-check. I'm getting an error message
Error: Did not check() all arguments during publisher 'document
I'm know this is related the audit-argument-check not being able to check all arguments. But as far as I'm concerned, I checked all of them. Concrete, I have defined a collection 'documents' and attached a SimpleSchema. As part of iron-router, I have the following:
Router.route('customerDocumentShow', {
template: 'customerDocumentShow',
path: 'customer/documents/:_id',
waitOn: function () {
return Meteor.subscribe('document', this.params._id);
},
data: function () {
return Documents.findOne(this.params._id);
}
});
So I'm passing only the documentId (this.params._id). On the server, I have defined a method:
Meteor.methods({
documentsReadMethod: function(documentId){
check(documentId, String);
var documentItem = Document.findOne(argument);
if (!documentItem) {
throw new Meteor.Error(500, 'Error 500: Not Found', 'No documents found.');
}
return documentItem;
}
});
So I'm checking to documentId in the server method. So not sure why I'm getting this error message.
Note: One thing I'm not entirely sure about though is how I need to call this method (right now, it's documentsReadMethod_. I'm not explicitly calling (on the client):
Meteor.call(documentsReadMethod, this.params_id);
as I'm using autoform, collection2 and simpleschema. I've been spending the entire weekend, but have no clue. Any idea's ?
Note: the code is on github: https://github.com/wymedia/meteor-starter-base
The problem is in the publish. You didn't check the id here:
https://github.com/wymedia/meteor-starter-base/blob/master/server/publications/documents.js#L16
Just add check(id, String); line 16 and it should work.
I have the same problem with another tuto !
Answer found at check is not defined in meteor.js : since Meteor v1.2, you have to add this package:
$ meteor add check

Session object in server side routing method - Meteor

I have this error when running my app and attempting to route to root/about
ReferenceError: Session is not defined at [object Object].route.onBeforeAction (app/lib/routes.js:38:8) at boundNext (packages/iron:middleware-stack/lib/middleware_stack.js:251:1) at runWithEnvironment (packages/meteor/dynamics_nodejs.js:108:1) at packages/meteor/dynamics_nodejs.js:121:1 at [object Object].urlencodedParser (/home/action/.parts/packages/meteor/1.0/packages/iron_router/.1.0.7.42k4wv++os+web.browser+web.cordova/npm/node_modules/body-parser/lib/types/urlencoded.js:72:36) at packages/iron:router/lib/router.js:277:1 at [object Object]._.extend.withValue (packages/meteor/dynamics_nodejs.js:56:1) at [object Object].hookWithOptions (packages/iron:router/lib/router.js:276:1) at boundNext (packages/iron:middleware-stack/lib/middleware_stack.js:251:1) at runWithEnvironment (packages/meteor/dynamics_nodejs.js:108:1)
Here is my routing code in this location lib/routes.js:
Router.map(function () {
this.route('aboutTemplate', {
name: 'aboutTemplate',
where: 'server',
path: '/about',
onBeforeAction: function(){
Session.set('active_menu_option','about');
this.next();
},
onAfterAction: function(){
},
data: function(){
return {active_menu_option: {'about':'active'}};
}
});
}
I presume the error occurs because this is now a server side route and the session object is not available outside of client scope. But is there any more information someone could give me on this?
also, while I am at it - what is the first argument representing in the above method? How is the first argument 'aboutTemplate' different from the name parameter - name: 'aboutTemplate'?
any help appreciated
Session is a client-only package, you will need a custom package (as told in the question comments) to get it on the server.
As for the first argument of Iron Router route function, it is used to specify parameters (/posts/:id for example) and is used by Iron Router to guess a couple parameters, such as the template to use (Router.route('homepage') on the client will search for the homepage template).
In that case, Iron Router will too guess the name, so your code is slightly redundant (but cleaner, in my own opinion). See more in the guide.

Why is Meteor Collection2 crashing my app with Error: undefined is not allowed by the schema

I just added Meteor collection2 to my app. And in a file in the server folder I added the code:
Schema = {}
Schema.User = new SimpleSchema(
_id:
type: String
regEx: SimpleSchema.RegEx.Id
username:
type: String
regEx: /^[a-z0-9A-Z_]{3,15}$/
emails:
type: [Object]
optional: true
"emails.$.address":
type: String
regEx: SimpleSchema.RegEx.Email
"emails.$.verified":
type: Boolean
createdAt:
type: Date
)
Meteor.users.attachSchema Schema.User
and it is crashing my app with the error:
W20140907-02:06:32.777(-4)? (STDERR) /Users/Nearpoint/.meteor/packages/meteor-tool/.1.0.25.2ltu8i++os.osx.x86_64+web.browser+web.cordova/meteor-tool-os.osx.x86_64/dev_bundle/lib/node_modules/fibers/future.js:173
W20140907-02:06:32.777(-4)? (STDERR) throw(ex);
W20140907-02:06:32.777(-4)? (STDERR) ^
W20140907-02:06:32.792(-4)? (STDERR) Error: undefined is not allowed by the schema
W20140907-02:06:32.792(-4)? (STDERR) at getErrorObject (packages/aldeed:collection2/collection2.js:489)
W20140907-02:06:32.792(-4)? (STDERR) at doValidate (packages/aldeed:collection2/collection2.js:472)
W20140907-02:06:32.792(-4)? (STDERR) at Meteor.Collection.(anonymous function) [as update] (packages/aldeed:collection2/collection2.js:282)
W20140907-02:06:32.792(-4)? (STDERR) at UserConnections.upsert.$set.ipAddr (packages/mizzao:user-status/status.coffee:94:15)
I am running Meteor 0.9.0. And I am attaching the schema code on the server. I do not know what I am doing wrong. I even tried removing all schema fields except _id and it still did not work.
NB - to resolve this if you're using mizzao:user-status, you just need to allow that package to add a status field to your user doc:
Schema.User = new SimpleSchema(
...
status: {
type: Object,
optional: true,
blackbox: true
}
});
I had the exact same problem. By any chance, are you using the mizzao:user-status package? It inserts an additional field for keeping track of user connections. https://github.com/mizzao/meteor-user-status
Any additional package that adds fields to Meteor.users docs before you even set up accounts may cause this problem. Specifically, when you sign on, it will create a blank user object with only the connection fields, which is clearly not allowed by your schema.
Since Users is a default Meteor collection there's probably a property it wants to save that you're not allowing.
I would look at the database using RoboMongo or another tool and make sure you include all the properties.

Resources