
Security News
Axios Supply Chain Attack Reaches OpenAI macOS Signing Pipeline, Forces Certificate Rotation
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.
mongo-tenant
Advanced tools
There are 3 ways of implementing multi-tenancy in mongoDB:
The mongo tenant is a highly configurable mongoose plugin solving multi-tenancy problems on document level (for now...). It creates a tenant-reference field and takes care of unique indexes. Also it provides access to tenant-bound model-classes, that prohibit the exploid of the given tenant scope. Last but not least the "MAGIC" can be disabled so that shipping of the same code in single- and multi-tenancy environment (on premis vs. cloud hosted) is a question of a single line of config.
Mongo tenant is compatible with mongoose 4 and 5.
$ npm i -S mongo-tenant
// or
$ yarn add mongo-tenant
Register the plugin on the relevant mongoose schema.
const mongoose = require('mongoose');
const mongoTenant = require('mongo-tenant');
const MySchema = new mongoose.Schema({});
MySchema.plugin(mongoTenant);
const MyModel = mongoose.model('MyModel', MySchema);
Retrieve the model in tenant scope with static byTenant method. This will return
a new model subclass that has special tenant-scope guards.
It has the exactly same interface as any other mongoose model but prevents
the access to other tenant scopes.
const MyTenantBoundModel = MyModel.byTenant('some-tenant-id');
(new MyTenantBoundModel()).getTenantId() === 'some-tenant-id'; // true
// silently ignore other tenant scope
(new MyTenantBoundModel({
tenantId: 'some-other-tenant-id'
})).getTenantId() === 'some-tenant-id'; // true
You can check for tenant context of a model class or instance by checking
the hasTenantContext property. If this is truthy you may want to retrieve
the bound tenant scope with getTenantId() method.
// With enabled mongo-tenant on a schema, all tenant bound models
// and there instances provide the hasTenantContext flag
if (SomeModelClassOrInstance.hasTenantContext) {
const tenantId = SomeModelClassOrInstance.getTenantId();
...
}
The mongo-tenant takes care of the tenant-reference field, so that you will be able to use your existing schema definitions and just plugin the mongo-tenant without changing a single line of schema definition.
But under the hood the mongo-tenant creates an indexed field (tenantId by default) and includes this in all defined unique indexes. So by default, all unique fields (and compound indexes) are unique for a single tenant id.
You may have use-cases where you want to archive global uniqueness.
To skip the automatic unique key extension of mongo-tenant for a specific
index you can set the preserveUniqueKey config option to true.
const MySchema = new mongoose.Schema({
someField: {
unique: true,
preserveUniqueKey: true
},
anotherField: String,
yetAnotherField: String
});
MySchema.index({
anotherField: 1,
yetAnotherField: 1
}, {
unique: true,
preserveUniqueKey: true
});
Once a model with tenant context is created it will try to keep the context for other models created via it. Whenever it detects that a subsequent models tenant configuration is compatible to its own, it will return that model bound to the same tenant context.
const AuthorSchema = new mongoose.Schema({});
AuthorSchema.plugin(mongoTenant);
const AuthorModel = mongoose.model('author', AuthorSchema);
const BookSchema = new mongoose.Schema({
author: { type: mongoose.Schema.Types.ObjectId, ref: 'author' }
});
BookSchema.plugin(mongoTenant);
const BookModel = mongoose.model('book', BookSchema);
const BoundBookModel = BookModel.byTenant('some-tenant-id');
BoundBookModel.model('author'); // return author model bound to "some-tenant-id"
BoundBookModel.db.model('author'); // return author model bound to "some-tenant-id"
The mongo tenant works out of the box, so all config options are optional. But you have the ability to adjust the behavior and api of the mongo tenant to your needs.
const config = {
/**
* Whether the mongo tenant plugin MAGIC is enabled. Default: true
*/
enabled: false,
/**
* The name of the tenant id field. Default: tenantId
*/
tenantIdKey: 'customerId',
/**
* The type of the tenant id field. Default: String
*/
tenantIdType: Number,
/**
* The name of the tenant id getter method. Default: getTenantId
*/
tenantIdGetter: 'getCustomerId',
/**
* The name of the tenant bound model getter method. Default: byTenant
*/
accessorMethod: 'byCustomer',
/**
* Enforce tenantId field to be set. Default: false
* NOTE: this option will become enabled by default in mongo-tenant@2.0
*/
requireTenantId: true
};
SomeSchema.plugin(mongoTenant, config);
Some tests rely on a running mongoDB and by default the tests are performed against 'mongodb://localhost/mongo-tenant-test'. The tests can also be run against a custom mongoDB by passing the custom connection string to MONGO_URI environment variable.
# perform jshint on sources and tests
$ npm run hint
# run the tests and gather coverage report
$ npm run test-and-cover
# run tests with custom mongoDB uri
$ MONGO_URI='mongodb://user:password@xyz.mlab.com:23315/mongo-tenant-test' npm run test-and-cover
The files in this archive are released under MIT license. You can find a copy of this license in LICENSE.
FAQs
The mongo-tenant is a multi-tenancy plugin for mongoose.
We found that mongo-tenant demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.

Security News
Open source is under attack because of how much value it creates. It has been the foundation of every major software innovation for the last three decades. This is not the time to walk away from it.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.