From 45b662a1ddb46a0f17fab7b2383c82aa1e1620ef Mon Sep 17 00:00:00 2001 From: Maxime Quandalle Date: Tue, 8 Sep 2015 20:19:42 +0200 Subject: Centralize all mutations at the model level This commit uses a new package that I need to document. It tries to solve the long-standing debate in the Meteor community about allow/deny rules versus methods (RPC). This approach gives us both the centralized security rules of allow/deny and the white-list of allowed mutations similarly to Meteor methods. The idea to have static mutation descriptions is also inspired by Facebook's Relay/GraphQL. This will allow the development of a REST API using the high-level methods instead of the MongoDB queries to do the mapping between the HTTP requests and our collections. --- models/lists.js | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 models/lists.js (limited to 'models/lists.js') diff --git a/models/lists.js b/models/lists.js new file mode 100644 index 00000000..4e4a1134 --- /dev/null +++ b/models/lists.js @@ -0,0 +1,110 @@ +Lists = new Mongo.Collection('lists'); + +Lists.attachSchema(new SimpleSchema({ + title: { + type: String, + }, + archived: { + type: Boolean, + }, + boardId: { + type: String, + }, + createdAt: { + type: Date, + denyUpdate: true, + }, + sort: { + type: Number, + decimal: true, + // XXX We should probably provide a default + optional: true, + }, + updatedAt: { + type: Date, + denyInsert: true, + optional: true, + }, +})); + +Lists.allow({ + insert(userId, doc) { + return allowIsBoardMember(userId, Boards.findOne(doc.boardId)); + }, + update(userId, doc) { + return allowIsBoardMember(userId, Boards.findOne(doc.boardId)); + }, + remove(userId, doc) { + return allowIsBoardMember(userId, Boards.findOne(doc.boardId)); + }, + fetch: ['boardId'], +}); + +Lists.helpers({ + cards() { + return Cards.find(Filter.mongoSelector({ + listId: this._id, + archived: false, + }), { sort: ['sort'] }); + }, + + allCards() { + return Cards.find({ listId: this._id }); + }, + + board() { + return Boards.findOne(this.boardId); + }, +}); + +Lists.mutations({ + rename(title) { + return { $set: { title }}; + }, + + archive() { + return { $set: { archived: true }}; + }, + + restore() { + return { $set: { archived: false }}; + }, +}); + +Lists.hookOptions.after.update = { fetchPrevious: false }; + +Lists.before.insert((userId, doc) => { + doc.createdAt = new Date(); + doc.archived = false; + if (!doc.userId) + doc.userId = userId; +}); + +Lists.before.update((userId, doc, fieldNames, modifier) => { + modifier.$set = modifier.$set || {}; + modifier.$set.modifiedAt = new Date(); +}); + +if (Meteor.isServer) { + Lists.after.insert((userId, doc) => { + Activities.insert({ + userId, + type: 'list', + activityType: 'createList', + boardId: doc.boardId, + listId: doc._id, + }); + }); + + Lists.after.update((userId, doc) => { + if (doc.archived) { + Activities.insert({ + userId, + type: 'list', + activityType: 'archivedList', + listId: doc._id, + boardId: doc.boardId, + }); + } + }); +} -- cgit v1.2.3-1-g7c22