Open caltuntas opened 4 years ago
After having a look at the closed issues I realized there was a similar issue https://github.com/wheresvic/mongoose-field-encryption/issues/1 (and merge request at the end) closed due to inactivity. It would be useful to add this feature.
@caltuntas I'll have a look at this again. The merge request you reference actually incorrectly mentioned the issue in question.
I cannot guarantee how fast I'll be able to develop this but let's say after the holidays would be a fair bet :)
Fair enough :) If I can find some time before you I may add this and make a pull request. Thanks
@caltuntas I had a look at this issue again and while implementing it would be possible, it would vastly complicate the code (and potentially break the current encrypted field naming convention).
I personally think that if you require nested field encryption, you could consider having sub-documents and apply the plugin on them and let mongoose itself handle the magic.
What do you think?
@wheresvic's suggestion on using subdocuments works perfectly. For those of you looking for a simple code example, consider the following.
const mongoose = require('mongoose');
const mongooseFieldEncryption = require("mongoose-field-encryption").fieldEncryption;
const CredentialSchema = new mongoose.Schema({
type: {
required: true,
type: String,
},
value: {
required: true,
type: String,
},
});
CredentialSchema.plugin(mongooseFieldEncryption, {
fields: ["value"],
secret: process.env.MONGOOSE_ENCRYPTION_KEY,
});
const accountSchema = new mongoose.Schema({
provider: {
type: String,
required: true,
lowercase: true,
trim: true,
},
credentials: [CredentialSchema],
owner: {
required: true,
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
});
module.exports = mongoose.model('Account', accountSchema);
That's a stripped down version of what I'm using to store OAuth credentials for multiple service providers for multiple users on an open source project I'm currently working on.
Hopefully this code helps someone.
const mongoose = require("mongoose");
const schema = new mongoose.Schema({
fieldA: { // 字段A
type: String
},
fieldBArrays: [new mongoose.Schema({ // 字段B嵌套文档
child: { // 子字段
type: String
}
})]
});
const mongooseFieldEncryption = require('mongoose-field-encryption').fieldEncryption;
schema.plugin(mongooseFieldEncryption, {
fields: ["fieldA","fieldBArrays.$.child"],
secret: "秘钥",
saltGenerator: function (secret) {
return "1234567890123456"; //理想情况下,应使用该机密返回长度为16的字符串
}
});
I did this
I experienced some issue with a similar structure like "Account schema has an array of Credential Schema, in which a field is marked as encrypted". After I use find()
findOne()
to get account(s), update some other fields but not the credentials
, I will get and error of
"Cannot create field '-1' in element in { credentials: [...] }"
when I call account.save()
It seems like only happens to Array type, and I found using `account.markModified('credentials') solves this problem.
I'm not sure if this behaviour is mentioned anywhere but since it is kind of related to the implementation described in this issue, I though I'd just post it here.
I tried following the suggestion proposed by @rickmacgillis but it's not working on my side.
I have an UserSchema where I need to encrypt the "name" and "surname" fields. Then this schema contains a field "extra" which is based on another schema (as it is a nested object). As suggested above, I have created the UserExtraSchema to allow nested fields encryption.
Unfortunately, I'm having some issues with this scenario. Therefore, the fields specified in the UserSchema are successfully encrypted, while the ones in the UserExtraSchema are not.
Below a snippet showing what I'm trying to do.
const UserExtraSchema: Schema = new Schema({
city: {type: String},
country: {type: String},
address: {type: String},
postalCode: {type: String}
});
UserExtraSchema.plugin(mongooseFieldEncryption.fieldEncryption, {
fields: ['address'],
secret: process.env.MY_SECRET,
saltGenerator(secret): string {
return bcrypt.hashSync(secret, 10).substring(0, 16);
}
});
const UserSchema: Schema = new Schema({
_id: {type: String, required: true},
name: {type: String, required: true},
surname: {type: String, required: true},
email: {type: String, required: true},
extra: UserExtraSchema,
}, {collection: 'users'}
);
UserSchema.plugin(mongooseFieldEncryption.fieldEncryption, {
fields: ['name', 'surname],
secret: process.env.MY_SECRET,
saltGenerator(secret): string {
return bcrypt.hashSync(secret, 10).substring(0, 16);
}
});
I tried following the suggestion proposed by @rickmacgillis but it's not working on my side.
I have an UserSchema where I need to encrypt the "name" and "surname" fields. Then this schema contains a field "extra" which is based on another schema (as it is a nested object). As suggested above, I have created the UserExtraSchema to allow nested fields encryption.
Unfortunately, I'm having some issues with this scenario. Therefore, the fields specified in the UserSchema are successfully encrypted, while the ones in the UserExtraSchema are not.
Below a snippet showing what I'm trying to do.
const UserExtraSchema: Schema = new Schema({ city: {type: String}, country: {type: String}, address: {type: String}, postalCode: {type: String} }); UserExtraSchema.plugin(mongooseFieldEncryption.fieldEncryption, { fields: ['address'], secret: process.env.MY_SECRET, saltGenerator(secret): string { return bcrypt.hashSync(secret, 10).substring(0, 16); } }); const UserSchema: Schema = new Schema({ _id: {type: String, required: true}, name: {type: String, required: true}, surname: {type: String, required: true}, email: {type: String, required: true}, extra: UserExtraSchema, }, {collection: 'users'} ); UserSchema.plugin(mongooseFieldEncryption.fieldEncryption, { fields: ['name', 'surname], secret: process.env.MY_SECRET, saltGenerator(secret): string { return bcrypt.hashSync(secret, 10).substring(0, 16); } });
I have the same issue
@mexusbg there is a test that uses exactly this example and it is working fine: https://github.com/wheresvic/mongoose-field-encryption/blob/036917d580e0d43c28f3331d0025af439d6ee18c/test/test-db.js#L212
the only difference I see from the example code is the way the saltGenerator
function is setup (although I do not see anything wrong with the one that you are using). Maybe try to change the function to that provided in the test and see if it works?
The other point is that I do not see how you save and retrieve the document. Are you saving the main user document?
@wheresvic I'm saving the main user document. User.create({}) User.findOneAndUpdate(findQuery,updateQuery)
I have the same problem with subschema encryption when I use findOneAndUpdate() on the parent record, but when I switched to save(), it works.
I'm encountering the same issue on Update/UpdateOne. Seems that mongoose only runs the hook on the top level schema.
I see that it's all over our project. I'll try to investigate. I think it's related to the way mongoose works
Hello,
Firstly I want to thank you for this nice library. At the moment, library supports only outer level field encryption like in the PostSchema example you added. It can only encrypt "references" field as whole. But when only one of the fields inside "references" should be encrypted, it doesn't work.
So It would be nice to support nested field encryption with "dot notation" used in mongoDB itself.
Query on Nested Field
For example , I should be able to define nested field as below
PostSchema.plugin(mongooseFieldEncyption, { fields: ["message", "references.author"], secret: "some secret key" });
and it should only encrypt "references.author" not whole "references" field