Session object in server side routing method - Meteor - 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.

Related

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

Meteor Iron:Route with Meteor 1.2

I'm learning Meteor by following this tutorial.
Here is my git https://github.com/nicholaschong12/meteor-slackclone
I'm getting this error:
Uncaught TypeError: Cannot read property 'channel' of undefined
Uncaught TypeError: Function.prototype.apply: Arguments list has wrong
type
Meteor.startup(function(){
Session.set('channel',this.params.channel);
});
Please help me to understand this error.
Thank You
Looking at the error:
Uncaught TypeError: Cannot read property 'channel' of undefined
We can see that it is trying to read a property 'channel' of an undefined object. This object from your code is:
this.params
Reading the iron:router docs, tells us that:
When a user goes to that url, the actual value of the parameter will be stored as a property on this.params in your route function.
However in the code snippet you provided:
Meteor.startup(function(){
Session.set('channel',this.params.channel);
});
You are trying to access this.params inside a Meteor.startup callback function, not a Router.route function. In this context this.params is undefined, as the error is telling you.
Change your startup code to match the tutorial:
Meteor.startup(function() {
Session.set('channel', 'general');
});
And in your routing code you can use values from the route like this:
Router.route('/:channel', function () {
Session.set('channel', this.params.channel);
this.render('messages');
});
In this context this.params will return an object, including the channel property defined in the routes path.

Updating the email address in Meteor.js user accounts

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,}/
}
}
})

Implementing a simple search with Meteor and Iron Router

In the next phase of my Meteor journey (read: learning the ropes!), I'd like to implement a simple search based on user inputed values, then redirect to a route specific to the record returned from the server.
At the moment, I'm picking up the inputed values via this code:
Template.home.events 'submit form': (event, template) ->
event.preventDefault()
console.log 'form submitted!'
countryFirst = event.target.firstCountrySearch.value
countrySecond = event.target.secondCountrySearch.value
Session.set 'countryPairSearchInputs', [countryFirst, countrySecond]
countryPairSearchInputs = Session.get 'countryPairSearchInputs'
console.log(countryPairSearchInputs)
return Router.go('explore')
Happily, the console log returns the desired countryPairSearchInputs variable - an array of two ids. In my routes.coffee file I then have the following:
#route "explore",
path: "/explore/:_id"
waitOn: ->
Meteor.subscribe 'countryPairsSearch'
On the server side, I have:
Meteor.publish 'countryPairsSearch', getCountryPairsSearch
And finally, I have a search.coffee file in my /lib directory that defines the getCountryPairsSearch function:
#getCountryPairsSearch = ->
CountryPairs.findOne $and: [
{ country_a_id: $in: Session.get('countryPairSearchInputs') }
{ country_b_id: $in: Session.get('countryPairSearchInputs') }
]
With regards to the search function itself, I have a CountryPairs collection where each record has two ids (country_a_id and country_b_id) - the aim here is to allow users to input two countries, with the corresponding CountryPair then being returning.
I'm currently struggling to tie all the pieces together - the console output on searching is currently:
Uncaught Error: Missing required parameters on path "/explore/:_id". The missing params are: ["_id"]. The params object passed in was: undefined.
Any help would be greatly appreciated - as you can probably tell I'm new to Meteor and am still getting used to the pub/sub methodology!
Edited: mixed up client/server for the publish method when I first posted - the danger of late-night posting!
First, seems you're expecting an :id parameter on your 'explore' route.
If I understand you're case, you're not expecting any params here, so you can just delete ':id' from your route:
#route "explore",
path: "/explore/"
waitOn: ->
Meteor.subscribe 'countryPairsSearch'
or either add a params to your Router.go call:
Router.go('explore', {_id: yourIdVar});
Secondly, you're trying to use a client function: Session.get() server-side. Try to update the publication using a parameter ; or using a method.call.
client-side
Meteor.subscribe 'countryPairsSearch' countryA countryB
not sure about the coffeescript syntax, check http://docs.meteor.com/#/full/meteor_subscribe
and server-side
#getCountryPairsSearch = (countryA, countryB) ->
CountryPairs.findOne $and: [
{ country_a_id: $in: countryA }
{ country_b_id: $in: countryB }
]

Resources