|
| 1 | +const { getByDot } = require('feathers-hooks-common'); |
| 2 | +const errors = require('feathers-errors'); |
| 3 | + |
| 4 | +module.exports = function restrictToOwnerOrModerator (query = {}) { // eslint-disable-line no-unused-vars |
| 5 | + return function (hook) { |
| 6 | + if (hook.type !== 'before') { |
| 7 | + throw new Error('The "restrictToOwnerOrModerator" hook should only be used as a "before" hook.'); |
| 8 | + } |
| 9 | + const isFindOrGet = ['find', 'get'].includes(hook.method); |
| 10 | + if (!isFindOrGet && !getByDot(hook, 'params.before')) { |
| 11 | + throw new Error('The "restrictToOwnerOrModerator" hook should be used after the "stashBefore()" hook'); |
| 12 | + } |
| 13 | + |
| 14 | + if (!hook.params || !hook.params.user) { |
| 15 | + return false; |
| 16 | + } |
| 17 | + |
| 18 | + const role = getByDot(hook, 'params.user.role'); |
| 19 | + const isModOrAdmin = role && ['admin', 'moderator'].includes(role); |
| 20 | + |
| 21 | + const userId = getByDot(hook, 'params.user._id'); |
| 22 | + const ownerId = getByDot(hook, 'params.before.userId'); |
| 23 | + const isOwner = userId && ownerId && ownerId.toString() === userId.toString(); |
| 24 | + |
| 25 | + // allow for mods or admins |
| 26 | + if (isModOrAdmin) { |
| 27 | + return hook; |
| 28 | + } |
| 29 | + |
| 30 | + // change the query if the method is find or get |
| 31 | + if (isFindOrGet) { |
| 32 | + // restrict to owner or given query |
| 33 | + const restrictedQuery = { |
| 34 | + $or: [ |
| 35 | + { userId }, |
| 36 | + { ...query } |
| 37 | + ] |
| 38 | + }; |
| 39 | + hook.params.query = Object.assign(hook.params.query, restrictedQuery); |
| 40 | + return hook; |
| 41 | + } |
| 42 | + |
| 43 | + let hasError = false; |
| 44 | + const keys = Object.keys(query); |
| 45 | + if (!isOwner && keys.length) { |
| 46 | + keys.forEach((key) => { |
| 47 | + if (query[key] !== getByDot(hook, `params.before.${key}`)) { |
| 48 | + hasError = true; |
| 49 | + } |
| 50 | + }); |
| 51 | + if (hasError) { |
| 52 | + // if any of the given query params is not identical with the current values this action is forbidden |
| 53 | + throw new errors.Forbidden('You can\'t alter this record!'); |
| 54 | + } |
| 55 | + } else if (!isOwner) { |
| 56 | + // his action is forbidden if its not the owner |
| 57 | + throw new errors.Forbidden('You can\'t alter this record!'); |
| 58 | + } |
| 59 | + |
| 60 | + return hook; |
| 61 | + }; |
| 62 | +}; |
| 63 | + |
0 commit comments