Search code examples
meteormeteor-accounts

Meteor not able to create user after adding attaching schema to users collection


I have installed mizzao:user-status package to track user activity like online, idle status.

I have added status to users collection:

import SimpleSchema from "simpl-schema";

const userSchema = new SimpleSchema({
  status: {
    type: Object,
    optional: true,
  },
  "status.lastlogin": {
    type: Object,
    optional: true,
  },
  "status.lastlogin.date": {
    type: Date,
    optional: true,
  },
  "status.lastlogin.ipAddr": {
    type: String,
    optional: true,
  },
  "status.userAgent": {
    type: String,
    optional: true,
  },
  "status.idle": {
    type: Boolean,
    optional: true,
  },
  "status.lastActivity": {
    type: Date,
    optional: true,
  },
  "status.online": {
    type: Boolean,
    optional: true,
  },
});

Meteor.users.attachSchema(userSchema);

On sign up page I have createUser code:

Accounts.createUser(
      { username, email, password },
      async (error) => {
        if (error && error.reason) {
          setErrors({ signUpFailed: error.reason });
          setIsLoading(false);
          return;
        }
        navigate('/dashboard', { replace: true });
      }
    );

Whenever I try to register I get an error on the server:

Exception while invoking method 'createUser' Error: After filtering out keys not in the schema, your object is now empty

All fields in status are set to optional yet I am still getting this error. If I remove Meteor.users.attachSchema(userSchema); then create user works.


Solution

  • The error is pretty clear. In short it went through your schema, removed things that are not in it and found that it leaves you with empty object. As such you need to define all the other fields that is being used on the users collection. There are two ways how to avoid this issue. First is not to set any schema on the users collection, second is to properly describe everything that is being set and stored there. If you are adjusting the the user documents, then the second approach is best. Bellow is mine description, which also includes definitions for alanning:roles for quick reference. You can find more details on collection2 documentation: https://github.com/Meteor-Community-Packages/meteor-collection2#attach-a-schema-to-meteorusers

    const userSchema = new SimpleSchema({
      username: {
        type: String,
        // For accounts-password, either emails or username is required, but not both. It is OK to make this
        // optional here because the accounts-password package does its own validation.
        optional: true
      },
      emails: {
        type: Array,
        // For accounts-password, either emails or username is required, but not both. It is OK to make this
        // optional here because the accounts-password package does its own validation.
        optional: true
      },
      'emails.$': {
        type: Object
      },
      'emails.$.address': {
        type: String,
        regEx: SimpleSchema.RegEx.Email,
        optional: true
      },
      'emails.$.verified': {
        type: Boolean,
        optional: true
      },
      'emails.$.primary': {
        type: Boolean,
        optional: true
      },
      createdAt: {
        type: Date
      },
      profile: {
        type: Object,
        optional: true,
        blackbox: true
      },
      services: {
        type: Object,
        optional: true,
        blackbox: true
      },
      roles: {
        type: Array,
        optional: true
      },
      'roles.$': {
        type: Object,
        optional: true,
        blackbox: true
      },
      // In order to avoid an 'Exception in setInterval callback' from Meteor
      heartbeat: {
        type: Date,
        optional: true
      }
    })