Meteor user has no email address - meteor

Using simple schema and accounts-password. I'm trying to add in an initial account on start-up, but the email and password are not appearing.
Schemas.User = new SimpleSchema({
username: {
type: String,
regEx: /^[a-z0-9A-Z_]{3,15}$/
},
emails: {
type: [Object],
optional: true
},
"emails.$.address": {
type: String,
regEx: SimpleSchema.RegEx.Email
},
"emails.$.verified": {
type: Boolean
},
profile: {
type: Schemas.UserProfile,
optional: true
}
});
and
Meteor.startup(function () {
Meteor.users.remove({});
if (Meteor.users.find().count() == 0) {
Accounts.createUser({
username: "newuser",
emails: [{address:"test#test.com", verified:true}],
password:"mypassword"
});
}
console.log(Meteor.users.find().fetch());
}
Gives us:
[{_id: 'xxx', username:'newuser'}]
No email or password. No errors. Thoughts?
New users in this system can only be added by existing users, so I haven't been able to test the user submission form.

Accounts.createUser takes a String as an email property for the options parameter. As for the password problem, it is maybe due to the lack of a services property in your schema. Add to your Schemas.User the following property:
Schemas.User = new SimpleSchema({
// ...
services: {
type: Object,
optional: true,
blackbox: true
}
}
Finally, the Accounts.createUser documentation (see first link) states:
On the client, you must pass password and at least one of username or email — enough information for the user to be able to log in again later. On the server, you do not need to specify password, but the user will not be able to log in until it has a password (eg, set with Accounts.setPassword).
It seems to not apply in your case, but as a last resort, try to call Accounts.setPassword(userId, "mypassword") afterwards. The user's id is returned by Meteor.createUser.

Related

simpl-schema: How to create an schema that validates every property of an object is of a certain schema?

Basically... I have something of the following type: record<string, User> (aka Map<String,User>). Basically, an object that can have any field, as long as it is an user.
How do I create an Schema that validates that?
There is an older question that seems to ask the same thing Can SimpleSchema express "object with custom keys and specific schema for values"? , however being asked for an older version of this library.
The accepted answer assumes the usage of Custom Validators
https://github.com/longshotlabs/simpl-schema#type
Another SimpleSchema instance, meaning Object type with this schema
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.
// Third-party login packages may not require either. Adjust this schema as necessary for your usage.
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.
// Third-party login packages may not require either. Adjust this schema as necessary for your usage.
optional: true,
},
'emails.$': {
type: Object,
},
'emails.$.address': {
type: String,
regEx: SimpleSchema.RegEx.Email,
},
'emails.$.verified': {
type: Boolean,
},
// Use this registered_emails field if you are using splendido:meteor-accounts-emails-field / splendido:meteor-accounts-meld
registered_emails: {
type: Array,
optional: true,
},
'registered_emails.$': {
type: Object,
blackbox: true,
},
createdAt: {
type: Date,
},
profile: {
type: Schema.UserProfile,
optional: true,
},
// Make sure this services field is in your schema if you're using any of the accounts packages
services: {
type: Object,
optional: true,
blackbox: true,
},
// DISCLAIMER: This only applies to the first and second version of meteor-roles package.
// https://github.com/Meteor-Community-Packages/meteor-collection2/issues/399
// Add `roles` to your schema if you use the meteor-roles package.
// Option 1: Object type
// If you specify that type as Object, you must also specify the
// `Roles.GLOBAL_GROUP` group whenever you add a user to a role.
// Example:
// Roles.addUsersToRoles(userId, ["admin"], Roles.GLOBAL_GROUP);
// You can't mix and match adding with and without a group since
// you will fail validation in some cases.
roles: {
type: Object,
optional: true,
blackbox: true,
},
// Option 2: [String] type
// If you are sure you will never need to use role groups, then
// you can specify [String] as the type
roles: {
type: Array,
optional: true,
},
'roles.$': {
type: String,
},
// In order to avoid an 'Exception in setInterval callback' from Meteor
heartbeat: {
type: Date,
optional: true,
},
});
const someOtherSchema = new SimpleSchema({
useDocument: {
type: userSchema
},
});

Add accountStatus to new users on app startup

I'm trying to add accountStatus to the users I create when I first run the application however it keeps crashing. accountStatus is not part of user.profile.
Can someone please look at my code and tell me what I'm doing wrong.
Thanks for any help.
Path: server.js
// run at Meteor app startup
Meteor.startup(function(options, user) {
// if users database is empty, seed these values
if(Meteor.users.find().count() < 1) {
// users array
var users = [
{firstName: 'Sam', lastName: 'Smith', email: 'sam#gmail.com', roles: ['is_student']},
];
// user creation
_.each(users, function(userData) {
// return id for use in roles assignment below
var userId = Accounts.createUser({
email: userData.email,
password: 'password',
profile: {
firstName: userData.firstName,
lastName: userData.lastName,
}
});
// verify user email
Meteor.users.update({ _id: userId }, { $set: { 'emails.0.verified': true } });
// add roles to user
Roles.addUsersToRoles(userId, userData.roles);
// add accountStatus and set to true
_.extend(userId, { accountStatus: true });
});
console.log('New users created!');
}
});
Look at this line:
_.extend(userId, { accountStatus: true });
And look at _.extend definition:
Copy all of the properties in the source objects over to the destination object, and return the destination object. It's in-order, so the last source will override properties of the same name in previous arguments.
What this line is supposed to do?

How to get user ID during user creation in Meteor?

I am creating default users on the server with a Meteor startup function. I want to create a user and also verify his/her email on startup (I'm assuming you can only do this after creating the account).
Here's what I have:
Meteor.startup(function() {
// Creates default accounts if there no user accounts
if(!Meteor.users.find().count()) {
// Set default account details here
var barry = {
username: 'barrydoyle18',
password: '123456',
email: 'myemail#gmail.com',
profile: {
firstName: 'Barry',
lastName: 'Doyle'
},
roles: ['webmaster', 'admin']
};
// Create default account details here
Accounts.createUser(barry);
Meteor.users.update(<user Id goes here>, {$set: {"emails.0.verified": true}});
}
});
As I said, I assume the user has to be created first before setting the the verified flag as true (if this statement is false please show a solution to making the flag true in the creation of the user).
In order to set the email verified flag to be true I know I can update the user after creation using Meteor.users.update(userId, {$set: {"emails.0.verified": true}});.
My problem is, I don't know how to get the userID of my newly created user, how do I do that?
You should be able to access the user id that is returned from the Accounts.createUser() function:
var userId = Accounts.createUser(barry);
Meteor.users.update(userId, {
$set: { "emails.0.verified": true}
});
Alternatively you can access newly created users via the Accounts.onCreateUser() function:
var barry = {
username: 'barrydoyle18',
password: '123456',
email: 'myemail#gmail.com',
profile: {
firstName: 'Barry',
lastName: 'Doyle'
},
isDefault: true, //Add this field to notify the onCreateUser callback that this is default
roles: ['webmaster', 'admin']
};
Accounts.onCreateUser(function(options, user) {
if (user.isDefault) {
Meteor.users.update(user._id, {
$set: { "emails.0.verified": true}
});
}
});

Meteor simpleSchema prevent field updates

Is it possible to specify that a field is not updateable using the schema itself rather than defining it in an allow/deny rule?
I am wondering because I use a quickform to allow users to edit their user details based on the users document (accounts package) and I want to prevent them from being able to change the verified state for their email address.
A rule based on user roles would be great to only allow admins and meteor itself to change the state of this field.
I'd be hoping for something like this:
emails: {
type: Array,
optional: true
},
"emails.$": {
type: Object
},
"emails.$.address": {
type: String,
regEx: SimpleSchema.RegEx.Email
},
"emails.$.verified": {
type: Boolean
allowRoles: ['admin','system'] // this does not exist
},
regards, Chris
You have a few different options.
To prevent anyone from updating a field, you can set the denyUpdate field in the flag definition (requires aldeed:collection2)
"emails.$.verified": {
type: Boolean
denyUpdate: true
},
To allow it to be updated by admin's only, you could try a custom validator that checks the userId to see if it is an admin (example requires aldeed:collection2 and alanning:roles)
"emails.$.verified": {
type: Boolean
custom: function() {
if ( this.isSet && this.isUpdate && !Roles.userIsInRole(this.userId, "admin") ) {
return "unauthorized";
}
}
},
You'd probably also want to define a message for the "unauthorized" validation error.
SimpleSchema.messages({
"unauthorized" : "You do not have permission to update this field"
})
This will display an error to the user if they try to change the field.
Alternately, you could simply unset the value provided by non-admin users and allow the rest of the update to go ahead.
"emails.$.verified": {
type: Boolean
autoValue: function() {
if ( !Roles.userIsInRole(this.userId, "admin") ) {
this.unset();
}
}
},

Recording username with meteror autoform

I'm creating a form using cfs:autoform to capture a photo and caption from submitted on the client like this:
Photos = new Mongo.Collection("photos");
Photos.attachSchema(new SimpleSchema({
userId:{
type: String,
autoValue:function(){return this.userId},
},
userName:{
type: String,
autoValue:function(){return Meteor.users.find({_id: this.userId}).username},
},
groupMembers: {
type: String
},
comments: {
type: String
},
fileId: {
type: String
}
}));
I've gotten the code to successfully capture and fill in the userId, as well as the comment and uploaded photo, but I can't seem to get it to capture the username.
It's most likely because you're using find instead of findOne. Since find returns a cursor and not a single document you can't access the username value, because it's not a property of the cursor. If you change it to findOne it should work.
userName:{
type: String,
autoValue:function(){return Meteor.users.findOne({_id: this.userId}).username},
}

Resources