Multi-tenancy with mongoose and express

Viewed 348

I am working on a MERN SaaS application and I have read all manner of documents on multi-tenancy, where the goal is to create a layer of data isolation above the level of the user. putting all the info together I came about this solution which suggests making use of "continous-local-storage" However, after implementing it, I can't really get it to work, all I have seems logically right, I really can't figure out the issue. After implementation, my application refuses to load data from the database...

//lib/storage.js

const createNamespace = require('continuation-local-storage').createNamespace;

const namespaceName = ('request');
const ns = createNamespace(namespaceName);

const bindCurrentNamespace=function(req, res, next){
  ns.bindEmitter(req);
  ns.bindEmitter(res);

  ns.run(() => {
    next();
  });
}

const setCurrentTenantId=function(tenantId){
  return ns.set('tenantId', tenantId);
}

const  getCurrentTenantId=function(){
  return ns.get('tenantId');
}

module.exports ={
  bindCurrentNamespace:function(){},
  setCurrentTenantId:function(){},
  getCurrentTenantId:function(){}
}

Sever.js

**********
// some code above
const storage= require('./lib/storage')

// multitenant logic
const BindCurrentNamespace = storage.bindCurrentNamespace
app.use(BindCurrentNamespace);
app.use((req, res, next) => {
  // Get current user from session or token
  const user = req.user

  // Get current tenant from user here
  // Make sure its a string
  const tenantId = user.organization._id.toString()

  setCurrentTenantId(tenantId);
  next();
});


/lib/multiTenant.js

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const storage = require('./storage');
const GetCurrentTenantId = storage.getCurrentTenantId

const tenantModel = function (name, schema, options) {
  return (props = {}) => {
    schema.add({ tenantId: String });
    const Model = mongoose.model(name, schema, options);

    const { skipTenant } = props;
    if (skipTenant) return Model;

    Model.schema.set('discriminatorKey', 'tenantId');

    const tenantId = GetCurrentTenantId;
    const discriminatorName = `${Model.modelName}-${tenantId}`;
    const existingDiscriminator = (Model.discriminators || {})[discriminatorName];
    return existingDiscriminator || Model.discriminator(discriminatorName, new Schema({}));
  };
}
const tenantlessModel = function (name, schema, options) {
  return () => mongoose.model(name, schema, options);
}

module.exports={
    tenantModel:function(){},
    tenantlessModel:function(){}
}

Modified Schema



//  Employee schema

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const Tenant= require('../lib/multiTenant')
const TenantModel=Tenant.tenantModel;


//create Schema
const EmployeeSchema = new mongoose.Schema({

    name: String,
    department: String,
    origin: String,
    wages:Number,
  overtime:{type:Number,
      default:0},
    joinDate: String,
    attendances: Object
},{timestamps:true});

const Employee=TenantModel("Employee", EmployeeSchema,'employee001');

module.exports=Employee


Usage

// @desc Get all Employee
//@routes Get/api/v1/employee
//@acess  Public
exports.getAllEmployee =  asyncHandler(async (req, res, next) => {

    Employee().find({}, null, {sort: {name: 1}}, function(err, employees){

        if(err){
          res.status(500);
          res.send(err);
        } else {
          res.json(employees);
        }
      });
    });


0 Answers
Related