mblarsen / mongoose-hidden

A Mongoose schema plugin for filtering properties you usually do not want to sent client-side like passwords and IDs.
MIT License
89 stars 19 forks source link

feat: Also hide when using lean() on Query #58

Open franciscosucre opened 6 years ago

franciscosucre commented 6 years ago

I have the following model

const mongoose = require('mongoose');
let mongooseHidden = require('mongoose-hidden')({
    password: true,
    defaultHidden: {
        __v: true
    }

})

var userSchema = mongoose.Schema({
    name: String,
    email: String,
    password: {
        type: String,
        hide: true,
        hideObject:true,
        hideJSON:true,
        bcrypt: true
    }
});

userSchema.plugin(mongooseHidden);
userSchema.plugin(require('mongoose-bcrypt'));

When i use lean() on a query, i recieve this:

{
    "_id": "5b2049bb3ea609512f254868",
    "name": "Francisco",
    "email": "frank91frank@gmail.com",
    "password": "$2a$10$XPJn18iwtmTBUC2GBfnUDOO7YJ1p0TCXci2oN1oIcDoxqgYr.ShMC",
    "__v": 0
}

I would like to be able to use mongoose-hidden to hide the password but using lean()

mblarsen commented 6 years ago

This plugin extends the Mongoose API at the model layer, that is after the query has been hydrated into model objects. This is also where transformation functions live which is used to hide unwanted values.

To have hook into lean() would mean extending Query for which there is no API as far as I know. If you know of it please let me know.

I don't think monkey patching is the way to go.

Since you use lean and not toJSON or toObject could it be that you are streaming your content? In that case it would more sense to clean your data per object basis instead of the whole data set.

I'm open to PRs as well of course.

franciscosucre commented 6 years ago

Hi @mblarsen thanks for your response.

I understand, so when i use lean() the query is passed directly from mongo as objects. I was using lean because some people told me that it improves performance but if the price to pay is to bypass all the mongoose api then it is not worth it.

Is there any benefit from transforming the objects before sending them through the response? O should just let Mongoose and ExpressJS handle it?

Thanks!

mblarsen commented 6 years ago

Is there any benefit from transforming the objects before sending them through the response?

Well, when you call toJSON and toObject they are being transformed.

Surely there is a performance gain by using lean but that is mostly when you are dealing with big sums of data. Why not try it out, with and without. If you can live with the non-lean version then all is good :)

Closing issue now, but feel free to leave more comments and/or questions.

niftylettuce commented 4 years ago

I have a solution for us:

I created a package @ladjs/pick-original that makes this easy.

Here's a rundown on how it works:

const pickOriginal = require('@ladjs/pick-original');

// ...

// this is an example object from `lean()` query
const lean = { foo: 'bar' };

// basically re-create a new document and invoke `toObject` on it
const obj = new Model(lean).toObject();

// pick only the original fields (recursive and supports arrays/nested arrays/etc)
console.log(pickOriginal(obj, lean));

Ref: https://github.com/ladjs/pick-original

mblarsen commented 4 years ago

@niftylettuce it is a recursive intersection between the props on the the original (allowed) and the transformed (hidden + whatever Mongo adds)? So Mongo specific stuff is removed and whatever is supposed to be hidden stays hidden.

Would you be interested in writing a small unit test that uses your library? Then afterwards we can see how the API could be for hooking into lean(). Either as opt-in or -out.

niftylettuce commented 4 years ago

Hi @mblarsen and thanks for the quick reply!

RE: whatever is supposed to be hidden stays hidden - yes, precisely. you can see this in-depth usage here where I already integrated it: https://github.com/forwardemail/forwardemail.net/blob/master/app/controllers/api/v1/aliases.js#L16-L19

RE: tests - I have some here https://github.com/ladjs/pick-original/blob/master/test/test.js