[Solved] Client knows its userId but not publish function

When the very first publish functions are run in my application, the client already knows its userId but not the server. Therefore I send the userId to the server in the subscribe call but that potentially allows a user to impersonate another

// Client
Template.myTemplate.onCreated(function () {
    this.subscribe("test", Meteor.userId())
})

// Server
Meteor.publish("test", userId => {
    const uid = this.userId  // undefined
    // Return data based on userId
})

Putting the client subscribe in an autorun doesn’t make a difference because the client already has his userId therfore the autorun is only called once. Same thing if you add “Meteor.loggingin” as the client has already ended the loggin process.

Template.myTemplate.onCreated(function () {
    this.autorun(() => {
        const uid = Meteor.userId()
        this.subscribe("test", uid)
    }
})

It is clearly a timing issue, as subsequent subscribes don’t have that problem.
Is there any way to wait on the server side ?

Also, the documentation makes it sound like this shouldn’t happen

this.userId
ddp-server/livedata_server.js, line 985
Access inside the publish function. The id of the logged-in user, or null if no user is logged in.

This is constant. However, if the logged-in user changes, the publish function is rerun with the new value.

Your code should look more like this:

// Client
Template.myTemplate.onCreated(function () {
    this.subscribe("test");
});

// Server
Meteor.publish("test", function() {
    const uid = this.userId;
    // Return data based on userId
});

Two things to note:

  1. Do not pass Meteor.userId() in the subscription - it is an unsafe practise and may not be available at the moment of subscription anyway.
  2. Do not use a fat arrow reference in a Meteor.publish - you will lose the correct this context.
2 Likes

Huh… That’s a beginner’s mistake I just made there ! Thanks rob for catching it.

Explanation in case it’s useful to anyone else : the issue has nothing to do with timing. The first publish was just improperly coded with a () => {} function which makes this be undefined. Replacing it with function() {} makes this.userId work as it should.

I got confused because other publish functions were properly written which made me erroneously conclude it was a timing issue as this was the very first publish.

1 Like

Wow, life saver. I was using the fat arrow on my publish. I never would have figured that out.