Fail to use Accounts.createUser()

I use a custom UI for registration and sign-in page. When I call Accounts.createUser(), it always return an error no matter what email or password is:

details: undefined
error: 403
errorType: "Meteor.Error"
message: "Signups forbidden [403]"
reason: "Signups forbidden"
stack: “Error↵ at Connection.livedata_result (http://localhost:3000/packages/ddp-client.js?hash=bc32a166cd269e06a394f9418e0024d805bab379:4736:23)↵ at onMessage (http://localhost:3000/packages/ddp-client.js?hash=bc32a166cd269e06a394f9418e0024d805bab379:3385:12)↵ at http://localhost:3000/packages/ddp-client.js?hash=bc32a166cd269e06a394f9418e0024d805bab379:2736:11↵ at Array.forEach (native)↵ at Function..each._.forEach (http://localhost:3000/packages/underscore.js?hash=cde485f60699ff9aced3305f70189e39c665183c:149:11)↵ at SockJS.self.socket.onmessage (http://localhost:3000/packages/ddp-client.js?hash=bc32a166cd269e06a394f9418e0024d805bab379:2735:11)↵ at SockJS.REventTarget.dispatchEvent (http://localhost:3000/packages/ddp-client.js?hash=bc32a166cd269e06a394f9418e0024d805bab379:175:22)↵ at SockJS._dispatchMessage (http://localhost:3000/packages/ddp-client.js?hash=bc32a166cd269e06a394f9418e0024d805bab379:1160:10)↵ at SockJS._didMessage (http://localhost:3000/packages/ddp-client.js?hash=bc32a166cd269e06a394f9418e0024d805bab379:1218:18)↵ at WebSocket.that.ws.onmessage (http://localhost:3000/packages/ddp-client.js?hash=bc32a166cd269e06a394f9418e0024d805bab379:1365:17)”

My code is:

// register.js
import { Accounts } from 'meteor/accounts-base';
export const register = (email, password) => {
  console.log(email, password);  // email: hello@world.com; password: 12345678
  Accounts.createUser({
    email, password
  }, err => {
    if (err) console.log(err);  // always shows an error
  });
}

Did I miss something?

Second question

On our service, Users need to provide the invitation code when registration. The registration will be confirmed on server side to check whether the invitation code matches the email to allow the registration.

I notice that Accounts.createUser() with callback is not supported on the server yet.

if (Meteor.isServer) {
  Meteor.methods({
    register(email, password, code) {
      // check the invitation code here first
      ...
      return new Promise((resolve, reject) => {
        Accounts.createUser({
          email, password
        }, err => {      ///////////////// raise the error
          console.log('register error:', err)
          if (err) reject(err);
          else resolve();
        });
      });
    }
  })
}

Accounts.createUser() also doesn’t return a Promise for Meteor.methods/Meteor.call. How do I register a user on server side with Meteor.methods/Meteor.call?

You might have to allow client-side account creation:

import { AccountsCommon } from 'meteor/accounts-base';

AccountsCommon.config({
  forbidClientAccountCreation: false,
});

As for creating accounts on the server, it’s synchronous. No need to use promises at all:

const newUserId = Accounts.createUser(options);

Use try/catch to handle errors.

Did you mean import { Accounts } from 'meteor/accounts-base'? I can’t find AccountsCommon in ‘meteor/accounts-base’.

I tried the following code, but still can’t register in the client side.

import { Accounts } from 'meteor/accounts-base';
Accounts.config({
  forbidClientAccountCreation: false,
});

I also tried to import the above config on the server side, it shows an Error Can't setforbidClientAccountCreationmore than once event if I use if (Meteor.isServer) { /* config setup here */ }.

fyi, on try/catch see this below. I used to use this pattern often, but found that the NodeJS v8 engine is unable to optimize code within try/catch blocks. Within reason of course, probably will not notice it for normal operations, I just switched to different patterns to not work against this.

This aside, the requirement to try-catch at runtime demands significant hoop-jumping in v8 (Node.js JavaScript engine). Use of try-catch causes runtime de-optimizations resulting in unnecessarily slow execution – particularly for hot code paths. This means if we adopt throwing and try/catch all over a codebase it could significantly affect performance.

Link

Currently not optimizable:

Generator functions
Functions that contain a for-of statement
Functions that contain a try-catch statement
Functions that contain a try-finally statement
Functions that contain a compound let assignment
Functions that contain a compound const assignment
Functions that contain object literals that contain proto, or get or set declarations.

1 Like

It should work fine. Are you correctly putting all your code inside an imports folder so it doesn’t automatically get executed? If not, maybe try running Accounts.config inside a Meteor.startup callback. (server side, of course)

Meteor.startup(function () {
  Accounts.config({ forbidClientAccountCreation: false });
});

I just checked, and I have a file in my project, /imports/startup/server/security.js that works fine:

import { Meteor } from 'meteor/meteor';
import { Accounts } from 'meteor/accounts-base';

// Deny all client-side updates to user documents for security purposes
Meteor.users.deny({
  update() {
    return true;
  },
});

Accounts.config({
  forbidClientAccountCreation: true,
});

I’ve never had any issues handling errors on server side. I’ve been doing this (below) and it works fine:

export const myMethod = new ValidatedMethod({
  name: 'myMethod',

  validate(args) {
    check(args, {
      name: String,
    });
  },

  run({ name }) {
    try {
      // some operation that might fail
    } catch (e) {
      throw new Meteor.Error('some-error', 'Something bad went down');
    }
  },
});

Yes, it doesn’t have any issues, and basically just works. It’s probably a non issue at smaller scale. The fact is that NodeJS/V8 can’t optimize any code that is within a try/catch. It is a black and white statement from NodeJS and is the only fact. So although it works/is convenient, it’s just a learned development behavior. Replacing it with a function/process that doesn’t have a built in performance limitation/penalty may be worth checking for the long run. That’s how we handled it.

Your example seems incomplete and Accounts.createUser returns the created objects key _id, so…

let _id = Accounts.createUser({username: string, email: string, password: string}, [callback]);

So you could return the value of _id on success or just use the callback.
Also I dont know why anyone would want to allow account creation from the client