Is it possible to setup encryption for a certain MongoDB collection using Strapi?

System Information
  • Strapi Version: 3.6.8
  • Operating System: Windows 10
  • Database: MongoDB (mongoose connector)
  • Node Version: 12.22.1
  • NPM Version: 6.14.12
  • Yarn Version: N/A

Hi, I need help adding encryption to one of our MongoDB collections in compliance to HIPAA. I’m somehow able to encrypt the fields I need by overriding the model services and store them as a JSON-stringified data, and decrypt the fields when I’m getting them but only on string fields. But when it’s a type of integer or decimal in the schema, mongoose throws a cast error. Do I really have to set all the attributes to a string type for this? To attempt to not change anything in the model settings, I tried overriding the mongoose model in the bootstrap function using something like this:

// Encryption plugin for mongoose
const mongooseEncryption = require('mongoose-encryption');

// Get a reference to the mongoose model
const SampleModel = strapi.query('sample-collection').model;

// Apply mongoose-encryption plugin
SampleModel.schema.plugin(
  mongooseEncryption,
  { 
    excludeFromEncryption: [
      "fieldA",
      "fieldB"
    ],
    secret: process.env.ENCRYPTION_SECRET,
  }
);

// I wasn't able to make the plugin above work so I did something like this
// adding a setter and getter function which also did not work
// for (const key of fieldsToEncrypt) {
//   SampleModel.schema.obj[key].set = encryptFunction;
//   SampleModel.schema.obj[key].get = decryptFunction;
// }

// Recompile model after making modifications
SampleModel.compile(
  SampleModel.modelName,
  SampleModel.schema,
  SampleModel.collection.name,
  SampleModel.db,
  SampleModel.base
);

For some reason, nothing is still being encrypted when I insert with insertMany after the above code being applied. What I am I doing wrong when overriding the mongoose model? Maybe there is a better way suited for Strapi for encryption? I haven’t had any experience on encryption stuff and I’m out of my wits now. I hope someone can help point me in the right direction. Thanks!

I also tried the following snippet to try to make the added getters/setters work:

for (const key of fieldsToEncrypt) {
  SampleModel.schema.obj[key].set = encryptFunction;
  SampleModel.schema.obj[key].get = decryptFunction;
}

SampleModel.schema.toObject = { getters: true, setters: true }
SampleModel.schema.toJSON = { getters: true, setters: true }
SampleModel.schema.runSettersOnQuery = true;

Unfortunately, it still didn’t work.

Also, I belatedly realized another problem which will still exist after fixing the problem above. I added a unique index in one of the fields to avoid inserting duplicate rows. If the value is to be encrypted now, the unique index will not be of use because the value inserted will be unique every time due to the random IV.