Best way to create user profile


#1

hi i am extremely new to meteor, please help me about this.

I am using collection2 and trying to create user with profile, i have my schema here but i dont know how to make a insert method for it. I know that this question is already solved here but I am still confused how to start methods for this…

sorry for the stupid post, I just want to get rid of this… thanks

// Definition of the Tasks Collection

import { Mongo } from 'meteor/mongo';

import SimpleSchema from 'simpl-schema';

export const User = new Mongo.Collection('users');

// Schema
Schema.User = new SimpleSchema({
  username: {
    type: String,
    regEx: /^[a-z0-9A-Z_]{3,15}$/
  },
  emails: {
    type: Array,
    optional: true,
  },
  "emails.$": {
    type: Object
  },
  "emails.$.address": {
    type: String,
    regEx: SimpleSchema.RegEx.Email
  },
  "emails.$.verified": {
    type: Boolean
  },
  registered_emails: {
    type: Array,
    optional: true
  },
'registered_emails.$': {
    type: Object,
    blackbox: true
  },
  createdAt: {
    type: Date,
  },
  profile: {
    type: Schema.UserProfile,
    optional: true
  },
  services: {
    type: Object,
    optional: true,
    blackbox: true
  },
  roles: {
    type: Object,
    optional: true,
    blackbox: true
  }, 
  roles: {
    type: [String],
    optional: true,
  },
});
Meteor.users.attachSchema(Schema.User);



#2

Hi @arda,

welcome! :slight_smile:
Every one of us started sometime - I know only too well how lost one can get - so no question is stupid!

The profile, as you are creating it, it not a separate document. It is part of the user-document.
So you would set user.profile.value = “test”, and save the user.

Does that answer your question?

(BTW: I stopped using schema’s for almost everything, as I tend to change my database layout fairly often. I found it more cumbersome than helpfull to have a schema… You don’t actually need it, so… I would drop it, try to get done what you want to do, know your layout, and then maybe add the schema’s back again…)

regards,

Paul


#3

Just to extend on your use of schemas. I think the problem mainly comes from attaching schemas to collection. They can also be used as stand alone, for client input verification for exemple, using the verify([Object]) method. It doesn’t get in the way of your other interactions with the database, while keeping some benefits of using schemas. I found that I like that approach best, and I too grew to dislike attaching schemas to collections.


#4

To directly answer your question, your User object returned from new Mongo.Collection has the insert methods on it already.

So you can just call User.insert({ username: 'test', etc... })

It’s worth mentioning that Meteor already comes with a users collection at Meteor.users that you should look at using for users and then extend this built in collection.

Using Meteor’s user accounts system gives you loads of built in benefits, like being able to check Meteor.user() in methods and have it return the record of the user that is currently running that method


#5

hey Pwiegers, thanks for the help :grinning: I’ll dig in some more. and design my database layout carefully.


#6

coagmano this is the solution for what i am looking for! I am working on that right now and it works fine for me … thanks for the help :grinning:


#7

This is what we use:

import { Meteor } from 'meteor/meteor';
import SimpleSchema from 'simpl-schema';

Meteor.users.allow({
  insert: () => false,
  update: () => false,
  remove: () => false,
});

Meteor.users.deny({
  insert: () => true,
  update: () => true,
  remove: () => true,
});

export const UserUpdate = new SimpleSchema({
  userId: { type: String },
  userAction: { type: String },
  userInformation: { type: Object, blackbox: true },
});

const UserSchema = new SimpleSchema({
  emails: { type: Array, optional: true },
  'emails.$': { type: Object, optional: true },
  '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, optional: true },
  profile: { type: Object },
  'profile.name': { type: Object },
  'profile.name.first': { type: String },
  'profile.name.last': { type: String },
  services: { type: Object, optional: true, blackbox: true },
  roles: { type: Object, optional: true, blackbox: true },

  // your other stuff can go here
  
  'status': { type: Object, optional: true, blackbox: true } // to track user, so if away, can logout
});

Meteor.users.attachSchema(UserSchema);

And a method could look like so:

export const insertUser = new ValidatedMethod({
  name: 'user.insert',
  validate: new SimpleSchema({
    email: { type: String },
    password: { type: String },
    profile: { type: Object },
    'profile.name': { type: Object },
    'profile.name.first': { type: String },
    'profile.name.last': { type: String },
    roles: { type: Object, blackbox: true, optional: true },

    userEntitySettings: { type: Object, optional: true, blackbox: true },

    userPersonalSettings: { type: Object, optional: true, blackbox: true },

    'status': { type:Object, optional: true, blackbox: true },
  }).validator(),
  async run({ email, password, profile, roles, userEntitySettings, userPersonalSettings }) {
    if (Meteor.isServer) {
      const userId = await Accounts.createUser({ email, password, profile });

      if (userId) {
        // NOTE: set primary email so emails work properly
        Meteor.users.update({ _id: userId }, { $set: { 'emails.0.primary': true } });

        if (roles) {
          Roles.addUsersToRoles({ _id: userId }, roles.type, roles.group);
        }

        if (userEntitySettings) {
          Meteor.users.update({ _id: userId }, { $set: { userEntitySettings: userEntitySettings } });
        }

        if (userPersonalSettings) {
          Meteor.users.update({ _id: userId }, { $set: { userPersonalSettings: userPersonalSettings } });
        }
      }

      return userId;
    }
  },
});

In below method, i’m using the update to validate.

export const updateUserGeneralSettings = new ValidatedMethod({
  name: 'userGeneralSettings.update',
  validate: UserUpdate.validator(),
  async run ({ userId, userAction, userInformation }) {
    if (Meteor.isServer) {
      switch (userAction) {
        case ('setUGSprofile'): {
          let setModifier = { $set: {} };

          setModifier.$set[
            'profile.name.' + userInformation.option
          ] = userInformation.value;

          return await Meteor.users.update(userId, setModifier);
        }
        case ('updatePassword'): {
          return await Accounts.setPassword(userId, userInformation.password, { logout: false });
        }
        case ('addRole'): {
          return await Roles.addUsersToRoles(userId, userInformation.role, userInformation.group);
        }
        case ('subRole'): {
          return await Roles.removeUsersFromRoles(userId, userInformation.role, userInformation.group);
        }
        default:{
          throw new Meteor.Error(
            'userGeneralSettings.update.failure',
            `Method ${userAction} was not recognized...`,
          );
        }
      }
    }
  }
});

Hopefully this helps. Was super annoying for me to work it out originally too.