Error: Meteor.userId can only be invoked in method calls or publications in Collection Extends

My code

class AppCollection extends Mongo.Collection {
  // Current user
  _getUserId() {
    return Meteor.isServer && Meteor.userId()
  }

I get error when startup fixture to call Method to insert data

First off, please ease up on creating so many topics. It’s much easier to keep all the context for these questions together (and less messy) to keep it all in the one topic.


Now take a second to think about where this function runs and what Meteor.userId() will return when you run it.

Meteor.userId() only makes sense on the client or when responding to a user request (ie in a method or publication).
At all other times, your code is just running on the server by itself, which is why Meteor.userId()makes no sense in that context.

If you are inserting documents in server code, there won’t be any user associated, so you need to account for that.

In an earlier thread I mentioned that you should look at how the existing package you want to mimic (timestampable) implements the behaviour.
It cheats a little by using a default value of 0 if one doesn’t exist

Where userId comes from is a little more complicated, you can see that timestampable uses collection.before.insert, which comes from the matb33:collection-hooks package (you can find the dependency in Package.js

If you look in collection-hooks they have a function for finding the current user here:

Which checks what environment the function is running in before using a method to find a userId, and falls back to a user configurable default if there isn’t one

3 Likes

Thanks and sorry :blush:

Just to throw my 2 cents in here.

If you are trying to create a collection that keeps track of the user who owns/inserts the document, then what makes the most sense to me is to enforce this using Simple Schema and Collection2. You can even create a schema with just this functionality and then extend any other schema with it to make the functionality available to that collection.

ownable-schema.js

export const OwnableSchema = new SimpleSchema({
    userId: {
        type: String,
        regEx: SimpleSchema.RegEx.Id,
        autoValue() {
            if (this.isInsert && (!this.isFromTrustedCode || !this.isSet)) {
                return this.userId;
            }
            return undefined;
        },
        index: 1,
        denyUpdate: true,
    },
});

ownable-widget.js

import { OwnableSchema } from './ownable-schema.js';

const OwnableWidgetsCollection = new Mongo.Collection('widgets');

const WidgetSchema = new SimpleSchema({
    //Widget Schema here
});

OwnableWidgetsCollection.attachSchema(OwnableSchema);
OwnableWidgetsCollection.attachSchema(WidgetSchema);
1 Like

@copleykj, very thanks for your advise :sunny: