feathers-hooks-common
feathers-hooks-common copied to clipboard
Using fastJoin with Mongoose lean:false
I spent quite a few hours looking into this, and after giving up, found the cause of the bug on accident.
Not sure if this affects more than just fastJoin.
Steps to reproduce
Say we have a posts mongoose service, that for one reason or another, lean is disabled:
const createService = require('feathers-mongoose');
const createModel = require('../../models/posts.model');
const hooks = require('./posts.hooks');
module.exports = function (app) {
const Model = createModel(app);
const paginate = app.get('paginate');
const options = {
Model,
paginate,
lean: false,
};
app.use('posts', createService(options));
const service = app.service('posts');
service.hooks(hooks);
};
and in the hooks we add a fastjoin: (in this case, populating the field "author" with the createdBy user)
const { fastJoin } = require('feathers-hooks-common');
const postResolvers = {
joins: {
createdBy: () => async (post, context) => {
post.author = (await context.app.service('users').find({
query: { _id: post.createdBy },
}))[0];
},
},
};
module.exports = {
before: {
...
},
after: {
all: [fastJoin(postResolvers)],
find: [],
get: [],
create: [],
update: [],
patch: [],
remove: []
},
...
};
Expected behavior
The client should receive a posts object with an "author" field.
Actual behavior
The client does not receive a posts object with an "author" field.
This is because modifying the mongoose Model object will not stick when toObject is called before sending. What should be given to the resolvers is either the object returned from toObject, or the _doc field of the Model.
i.e. this will fix the issue:
const postResolvers = {
joins: {
createdBy: () => async (post, context) => {
post._doc.author = (await context.app.service('users').find({
query: { _id: post.createdBy },
}))[0];
},
},
};
All common hooks, and the documentation, assume a disabled ORM, that is lean:true for Mongoose. You have to work around the the ORM otherwise, as you did.
Please feel free to comment or even to reopen this issue.
I've reopened the issue as information for others who may run into this issue.
Upon debugging a separate issue, I've found that this is also the case with discard, and I'm assuming anything that uses getItems.
Due to the common nature of the use case of hooks like discard (passwords), I feel like this is a rather large security vulnerability for those that unknowingly use lean: false to get their virtuals working...
Alternatively this is a feathersjs or feathers-mongoose issue, idk, but it wouldn't be that hard to code against though.
Feathers assumes lean: true is being used. You yourself have to handle any ramifications if you do otherwise.