`Meteor.userId()` don't work when call method in hook

// Method
Meteor.methods({
  test: function() {
    console.log('userId', Meteor.userId()) // Don't work
    ......
  },
})
----------------
// Hook
Collection.after.insert(function (userId, doc) {
   Meteor.call('test')
   .....
})

Please help me

Do you call the insert inside or outside a method or publication? Please add the code where the insert happens if you are not sure.

have you tried using this.userId

1 Like

thanks for your reply.
Oh I use Meteor.defer() in Hook

// Method
Meteor.methods({
  test: function() {
    console.log('userId', Meteor.userId())
    // Don't work: Meteor.userId(), this.userId, Meteor.user()...
    ......
  },
})
----------------
// Hook
Collection.after.insert(function (userId, doc) {
    Meteor.defer(function () {
           Meteor.call('test')
    })
   .....
})
-----------
// Collection call (Out of Method)
Collection.insert({..............})

Could I get current user in other function?

export const myFun = function(params){
    let userId = Meteor.userId() // ?
    
   return userId
}

Unfortunately, like with setTimeout, the context in which a call was made is lost when using Meteor.defer. Which means that this will not contain the same things, and other methods like Meteor.user() won’t work as they need the context of a client initiated request to be able to access client specific variables like userId.
I’m unsure if the collection hooks have an impact of their own here as well.

You will either need to move the defer into the call, or extract the method into a server side only module and call that, passing in the userId. Definitely don’t pass userId into the methods method call. Allowing methods to accept userId as a parameter is dangerous as clients can then call the method pretending to be another user.

4 Likes

@coagmano thanks for your explain

Have you tried putting a Meteor.bindEnvironment inside the defer like so:

Collection.after.insert(function (userId, doc) {
    Meteor.defer(Meteor.bindEnvironment(function () {
           Meteor.call('test')
    }))
   .....
})

It’s not very well documented, but is mentioned a couple of times here and here.

SORRY IN ADVANCE FOR THE NECROMANCY

However I thought I’d share what I just came up with in the hopes that it will help others in the future.

export const bindDefer = (fn) => {
	const boundFn = Meteor.bindEnvironment(fn);
	Meteor.defer(() => boundFn());
};

Use it like so…

bindDefer(() => {
	console.log(this.userId);
});
1 Like

A question for someone familar with Meteor-core: is there a reason why Meteor.defer doesn’t automatically use Meter.bindEnvironment internally? Is there an overhead/downside to using it as standard?

1 Like