How restrict access access to a subset of a resource exposed via Feathers.js?
For example, how would you restrict CRUD operations to a user's tenantId or groupId?
So far, I have this somewhat working with a service hook. The code below works for "get/find" but not for "put/update". Tracing the resulting mongo query, only "_id" is being queried during "update" scenario. It seems my query is being ignored or overwritten.
// my-resource.hooks.js
module.exports = {
before: {
all: [
function(hook) {
const userGroupId = hook.params.userGroupId;
// NOTE: userGroupId gets extracted via an Express js hook from auth/header
hook.params.query = {
...hook.params.query,
userGroupId
}
return hook;
}
]
}
}
So far, I've extended the feathers-mongoose service implementation and update this bit of code. Seems to do the trick, but I'm still wondering if I'm missing something.
_get(id, params = {}) {
params.query = params.query || {};
const discriminator = (params.query || {})[this.discriminatorKey] || this.discriminatorKey;
const model = this.discriminators[discriminator] || this.Model;
let modelQuery = model
.findOne({
[this.id]: id,
...params.query
});
In order to know if the user is allowed to modify an individual resource the best way is to retrieve it first, check the permissions and throw a Feathers error if they are not allowed:
const errors = require('feathers-errors');
// my-resource.hooks.js
module.exports = {
before: {
all: [
function(hook) {
// NOTE: userGroupId gets extracted via an Express js hook from auth/header
const userGroupId = hook.params.userGroupId;
// If there is an id, get the entry first to check the permission
if(hook.id !== undefined && hook.id !== null) {
return hook.service.get(hook.id).then(entry => {
if(entry.userGroupId !== userGroupId) {
throw new errors.Forbidden('You are not allowed to access this');
}
return hook;
});
}
// Otherwise just restrict the query
hook.params.query = {
...hook.params.query,
userGroupId
}
return Promise.resolve(hook);
}
]
}
}