Я работаю над приложением MERN SaaS и прочитал всевозможные документы по мультитенантности, цель которых - создать уровень изоляции данных выше уровня пользователя. Собрав воедино всю информацию, я пришел к этому решению, которое предлагает использовать «непрерывное локальное хранилище». Однако после его реализации я не могу заставить его работать, все, что у меня есть, кажется логически правильным, я действительно не могу выяснить проблему. После реализации мое приложение отказывается загружать данные из базы данных ...
//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(){}
}
Север. 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(){}
}
Модифицированная схема
// 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
Использование
// @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);
}
});
});