|
1 | 1 | import Users from 'meteor/nova:users';
|
| 2 | +import { Utils, GraphQLSchema } from 'meteor/nova:core'; |
2 | 3 |
|
3 | 4 | /**
|
4 | 5 | * @summary Verify that the un/subscription can be performed
|
@@ -36,8 +37,8 @@ const prepareSubscription = (action, collection, itemId, user) => {
|
36 | 37 |
|
37 | 38 | // assign the right fields depending on the collection
|
38 | 39 | const fields = {
|
39 |
| - subscribers: collectionName === 'Users' ? 'subscribers' : 'subscribers', |
40 |
| - subscriberCount: collectionName === 'Users' ? 'subscriberCount' : 'subscriberCount', |
| 40 | + subscribers: 'subscribers', |
| 41 | + subscriberCount: 'subscriberCount', |
41 | 42 | };
|
42 | 43 |
|
43 | 44 | // return true if the item has the subscriber's id in its fields
|
@@ -82,7 +83,7 @@ const performSubscriptionAction = (action, collection, itemId, user) => {
|
82 | 83 | // - the action is subscribe but the user has already subscribed to this item
|
83 | 84 | // - the action is unsubscribe but the user hasn't subscribed to this item
|
84 | 85 | if (!subscription || (action === 'subscribe' && subscription.hasSubscribedItem) || (action === 'unsubscribe' && !subscription.hasSubscribedItem)) {
|
85 |
| - return false; // xxx: should return exploitable error |
| 86 | + throw Error({id: 'app.mutation_not_allowed', value: 'Already subscribed'}) |
86 | 87 | }
|
87 | 88 |
|
88 | 89 | // shorthand for useful variables
|
@@ -122,58 +123,70 @@ const performSubscriptionAction = (action, collection, itemId, user) => {
|
122 | 123 | [updateOperator]: { [`subscribedItems.${collectionName}`]: loggedItem }
|
123 | 124 | });
|
124 | 125 |
|
125 |
| - return true; // action completed! ✅ |
| 126 | + const updatedUser = Users.findOne({_id: user._id}, {fields: {_id:1, subscribedItems: 1}}); |
| 127 | + |
| 128 | + return updatedUser; |
126 | 129 | } else {
|
127 |
| - return false; // xxx: should return exploitable error |
| 130 | + throw Error(Utils.encodeIntlError({id: 'app.something_bad_happened'})) |
128 | 131 | }
|
129 | 132 | };
|
130 | 133 |
|
131 | 134 | /**
|
132 |
| - * @summary Generate methods 'collection.subscribe' & 'collection.unsubscribe' automatically |
| 135 | + * @summary Generate mutations 'collection.subscribe' & 'collection.unsubscribe' automatically |
133 | 136 | * @params {Array[Collections]} collections
|
134 | 137 | */
|
135 |
| - let subscribeMethodsGenerator; |
136 |
| - export default subscribeMethodsGenerator = (collection) => { |
| 138 | + const subscribeMutationsGenerator = (collection) => { |
137 | 139 |
|
138 |
| - // generic method function calling the performSubscriptionAction |
139 |
| - const genericMethodFunction = (col, action) => { |
| 140 | + // generic mutation function calling the performSubscriptionAction |
| 141 | + const genericMutationFunction = (collectionName, action) => { |
140 | 142 | // return the method code
|
141 |
| - return function(docId, userId) { |
142 |
| - check(docId, String); |
143 |
| - check(userId, Match.Maybe(String)); |
144 |
| - |
145 |
| - const currentUser = Users.findOne({_id: this.userId}); // this refers to Meteor thanks to previous fat arrows when this function-builder is used |
146 |
| - const user = typeof userId !== "undefined" ? Users.findOne({_id: userId }) : currentUser; |
147 |
| - |
148 |
| - if (!Users.canDo(currentUser, `${col._name}.${action}`) || typeof userId !== "undefined" && !Users.canDo(currentUser, `${col._name}.${action}.all`)) { |
149 |
| - throw new Error(601, "You don't have the permission to do this"); |
| 143 | + return function(root, { documentId }, context) { |
| 144 | + |
| 145 | + // extract the current user & the relevant collection from the graphql server context |
| 146 | + const { currentUser, [Utils.capitalize(collectionName)]: collection } = context; |
| 147 | + |
| 148 | + // permission check |
| 149 | + if (!Users.canDo(context.currentUser, `${collectionName}.${action}`) || !Users.canDo(currentUser, `${collectionName}.${action}.all`)) { |
| 150 | + throw new Error(Utils.encodeIntlError({id: "app.noPermission"})); |
150 | 151 | }
|
151 |
| - |
152 |
| - return performSubscriptionAction(action, col, docId, user); |
| 152 | + |
| 153 | + // do the actual subscription action |
| 154 | + return performSubscriptionAction(action, collection, documentId, currentUser); |
153 | 155 | };
|
154 | 156 | };
|
155 | 157 |
|
156 | 158 | const collectionName = collection._name;
|
157 |
| - // return an object of the shape expected by Meteor.methods |
158 |
| - return { |
159 |
| - [`${collectionName}.subscribe`]: genericMethodFunction(collection, 'subscribe'), |
160 |
| - [`${collectionName}.unsubscribe`]: genericMethodFunction(collection, 'unsubscribe') |
161 |
| - }; |
| 159 | + |
| 160 | + // add mutations to the schema |
| 161 | + GraphQLSchema.addMutation(`${collectionName}Subscribe(documentId: String): User`), |
| 162 | + GraphQLSchema.addMutation(`${collectionName}Unsubscribe(documentId: String): User`); |
| 163 | + |
| 164 | + // create an object of the shape expected by mutations resolvers |
| 165 | + GraphQLSchema.addResolvers({ |
| 166 | + Mutation: { |
| 167 | + [`${collectionName}Subscribe`]: genericMutationFunction(collectionName, 'subscribe'), |
| 168 | + [`${collectionName}Unsubscribe`]: genericMutationFunction(collectionName, 'unsubscribe'), |
| 169 | + }, |
| 170 | + }); |
| 171 | + |
| 172 | + |
162 | 173 | };
|
163 | 174 |
|
164 |
| -// Finally. Add the methods to the Meteor namespace 🖖 |
| 175 | +// Finally. Add the mutations to the Meteor namespace 🖖 |
165 | 176 |
|
166 | 177 | // nova:users is a dependency of this package, it is alreay imported
|
167 |
| -Meteor.methods(subscribeMethodsGenerator(Users)); |
| 178 | +subscribeMutationsGenerator(Users); |
168 | 179 |
|
169 |
| -// check if nova:posts exists, if yes, add the methods to Posts |
| 180 | +// check if nova:posts exists, if yes, add the mutations to Posts |
170 | 181 | if (typeof Package['nova:posts'] !== 'undefined') {
|
171 | 182 | import Posts from 'meteor/nova:posts';
|
172 |
| - Meteor.methods(subscribeMethodsGenerator(Posts)); |
| 183 | + subscribeMutationsGenerator(Posts); |
173 | 184 | }
|
174 | 185 |
|
175 |
| -// check if nova:categories exists, if yes, add the methods to Categories |
| 186 | +// check if nova:categories exists, if yes, add the mutations to Categories |
176 | 187 | if (typeof Package['nova:categories'] !== "undefined") {
|
177 | 188 | import Categories from 'meteor/nova:categories';
|
178 |
| - Meteor.methods(subscribeMethodsGenerator(Categories)); |
| 189 | + subscribeMutationsGenerator(Categories); |
179 | 190 | }
|
| 191 | + |
| 192 | +export default subscribeMutationsGenerator; |
0 commit comments