| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 | Users = Meteor.users;// Search a user in the complete server database by its name or username. This// is used for instance to add a new user to a board.const searchInFields = ['username', 'profile.name'];Users.initEasySearch(searchInFields, {  use: 'mongo-db',  returnFields: [...searchInFields, 'profile.avatarUrl'],});Users.helpers({  boards() {    return Boards.find({ userId: this._id });  },  starredBoards() {    const starredBoardIds = this.profile.starredBoards || [];    return Boards.find({archived: false, _id: {$in: starredBoardIds}});  },  hasStarred(boardId) {    const starredBoardIds = this.profile.starredBoards || [];    return _.contains(starredBoardIds, boardId);  },  isBoardMember() {    const board = Boards.findOne(Session.get('currentBoard'));    return board && _.contains(_.pluck(board.members, 'userId'), this._id) &&                         _.where(board.members, {userId: this._id})[0].isActive;  },  isBoardAdmin() {    const board = Boards.findOne(Session.get('currentBoard'));    return board && this.isBoardMember(board) &&                          _.where(board.members, {userId: this._id})[0].isAdmin;  },  getInitials() {    const profile = this.profile || {};    if (profile.initials)      return profile.initials;    else if (profile.fullname) {      return _.reduce(profile.fullname.split(/\s+/), (memo, word) => {        return memo + word[0];      }, '').toUpperCase();    } else {      return this.username[0].toUpperCase();    }  },});Users.mutations({  toggleBoardStar(boardId) {    const queryKind = this.hasStarred(boardId) ? '$pull' : '$addToSet';    return {      [queryKind]: {        'profile.starredBoards': boardId,      },    };  },  setAvatarUrl(avatarUrl) {    return { $set: { 'profile.avatarUrl': avatarUrl }};  },});Meteor.methods({  setUsername(username) {    check(username, String);    const nUsersWithUsername = Users.find({ username }).count();    if (nUsersWithUsername > 0) {      throw new Meteor.Error('username-already-taken');    } else {      Users.update(this.userId, {$set: { username }});    }  },});Users.before.insert((userId, doc) => {  doc.profile = doc.profile || {};  if (!doc.username && doc.profile.name) {    doc.username = doc.profile.name.toLowerCase().replace(/\s/g, '');  }});if (Meteor.isServer) {  // Let mongoDB ensure username unicity  Meteor.startup(() => {    Users._collection._ensureIndex({      username: 1,    }, { unique: true });  });  // Each board document contains the de-normalized number of users that have  // starred it. If the user star or unstar a board, we need to update this  // counter.  // We need to run this code on the server only, otherwise the incrementation  // will be done twice.  Users.after.update(function(userId, user, fieldNames) {    // The `starredBoards` list is hosted on the `profile` field. If this    // field hasn't been modificated we don't need to run this hook.    if (!_.contains(fieldNames, 'profile'))      return;    // To calculate a diff of board starred ids, we get both the previous    // and the newly board ids list    function getStarredBoardsIds(doc) {      return doc.profile && doc.profile.starredBoards;    }    const oldIds = getStarredBoardsIds(this.previous);    const newIds = getStarredBoardsIds(user);    // The _.difference(a, b) method returns the values from a that are not in    // b. We use it to find deleted and newly inserted ids by using it in one    // direction and then in the other.    function incrementBoards(boardsIds, inc) {      _.forEach(boardsIds, (boardId) => {        Boards.update(boardId, {$inc: {stars: inc}});      });    }    incrementBoards(_.difference(oldIds, newIds), -1);    incrementBoards(_.difference(newIds, oldIds), +1);  });  // XXX i18n  Users.after.insert((userId, doc) => {    const ExampleBoard = {      title: 'Welcome Board',      userId: doc._id,      permission: 'private',    };    // Insert the Welcome Board    Boards.insert(ExampleBoard, (err, boardId) => {      _.forEach(['Basics', 'Advanced'], (title) => {        const list = {          title,          boardId,          userId: ExampleBoard.userId,          // XXX Not certain this is a bug, but we except these fields get          // inserted by the Lists.before.insert collection-hook. Since this          // hook is not called in this case, we have to dublicate the logic and          // set them here.          archived: false,          createdAt: new Date(),        };        Lists.insert(list);      });    });  });}
 |