diff options
Diffstat (limited to 'models/users.js')
-rw-r--r-- | models/users.js | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/models/users.js b/models/users.js new file mode 100644 index 00000000..4260dc56 --- /dev/null +++ b/models/users.js @@ -0,0 +1,157 @@ +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); + }); + }); + }); +} |