UNPKG

soajs.multitenant

Version:
637 lines (572 loc) 14.3 kB
/** * @license * Copyright SOAJS All Rights Reserved. * * Use of this source code is governed by an Apache license that can be * found in the LICENSE file at the root of this repository */ "use strict"; const colName = "tenants"; const core = require("soajs"); const Mongo = core.mongo; let indexing = {}; function Tenant(service, options, mongoCore) { let __self = this; if (mongoCore) { __self.mongoCore = mongoCore; } if (!__self.mongoCore) { if (options && options.dbConfig) { __self.mongoCore = new Mongo(options.dbConfig); } else { let registry = service.registry.get(); __self.mongoCore = new Mongo(registry.coreDB.provision); } let index = "default"; if (options && options.index) { index = options.index; } if (indexing && !indexing[index]) { indexing[index] = true; __self.mongoCore.createIndex(colName, { 'code': 1 }, { unique: true }, () => { }); __self.mongoCore.createIndex(colName, { '_id': 1, 'locked': 1 }, {}, () => { }); __self.mongoCore.createIndex(colName, { 'name': 1 }, {}, () => { }); __self.mongoCore.createIndex(colName, { 'type': 1 }, {}, () => { }); __self.mongoCore.createIndex(colName, { 'console': 1, 'type': 1, 'tenant.code': 1, 'name': 1, 'code': 1 }, { partialFilterExpression: { "tenant.code": { "$exists": true } } }, () => { }); __self.mongoCore.createIndex(colName, { 'console': 1, 'type': 1, 'name': 1, 'code': 1 }, {}, () => { }); __self.mongoCore.createIndex(colName, { '_id': 1, 'console': 1 }, {}, () => { }); __self.mongoCore.createIndex(colName, { 'applications.keys.extKeys.env': 1 }, {}, () => { }); __self.mongoCore.createIndex(colName, { 'applications.keys.key': 1 }, {}, () => { }); service.log.debug("Tenant: Indexes for " + index + " Updated!"); } } } Tenant.prototype.validateId = function (id, cb) { let __self = this; if (!id) { let error = new Error("id is required."); return cb(error, null); } try { id = __self.mongoCore.ObjectId(id); return cb(null, id); } catch (e) { return cb(e, null); } }; Tenant.prototype.getTenants = function (data, cb) { let __self = this; if (!data || !data.codes || !Array.isArray(data.codes) || data.codes.length <= 0) { let error = new Error("Array of codes is required."); return cb(error, null); } let partial = [ { console: !!data.soajs } ]; if (!data.soajs) { partial.push({ console: null }); } let condition = { '$and': [{ "$or": partial }] }; condition.$and.push({ 'code': { '$in': data.codes } }); __self.mongoCore.find(colName, condition, null, cb); }; Tenant.prototype.getTenant = function (data, cb) { let __self = this; if (!data || !(data.id || data.code || data.name)) { let error = new Error("id, code, or name is required."); return cb(error, null); } let partial = [ { console: !!data.soajs } ]; if (!data.soajs) { partial.push({ console: null }); } let condition = { '$and': [{ "$or": partial }] }; if (data.id) { __self.validateId(data.id, (err, id) => { if (err) { return cb(err, null); } condition.$and.push({ '_id': id }); __self.mongoCore.findOne(colName, condition, null, cb); }); } else if (data.code) { condition.$and.push({ 'code': data.code }); __self.mongoCore.findOne(colName, condition, null, cb); } else { if (data.name) { data.name = data.name.trim(); // data.name = data.name.toLowerCase(); condition.$and.push({ 'name': data.name }); } __self.mongoCore.findOne(colName, condition, null, cb); } }; Tenant.prototype.listTenantSubTenants = function (data, cb) { let __self = this; if (!data || !data.code) { let error = new Error("code is required."); return cb(error, null); } let condition = { "$or": [ { console: false }, { console: null } ] }; let andCond = []; andCond.push({ 'type': "client" }); andCond.push({ 'tenant.code': data.code }); if (data.keywords) { let rePattern = new RegExp(data.keywords, 'i'); andCond.push({ "$or": [{ "name": { "$regex": rePattern } }, { "code": { "$regex": rePattern } }] }); } if (andCond.length > 0) { condition.$and = andCond; } let options = { "skip": 0, "limit": 50, "sort": { "name": 1 } }; if (data && data.limit) { options.limit = data.limit; } if (data && data.start) { options.skip = data.start; } __self.mongoCore.find(colName, condition, options, (error, response) => { if (error) { return cb(error); } else { let current_count = options.skip; if (response && response.length) { current_count = current_count + response.length; } if (current_count < options.limit) { return cb(null, { "limit": options.limit, "start": options.skip, "count": response.length, "items": response }); } else { __self.count(data, condition, (error, count) => { if (error) { return cb(error); } else { return cb(null, { "limit": options.limit, "start": options.skip, "count": count, "items": response }); } }); } } }); }; Tenant.prototype.listTenants = function (data, cb) { let __self = this; let condition = { "$or": [ { "console": false }, { "console": null } ] }; let andCond = []; if (data && data.type) { andCond.push({ "type": data.type }); } if (data.keywords) { let rePattern = new RegExp(data.keywords, 'i'); andCond.push({ "$or": [{ "name": { "$regex": rePattern } }, { "code": { "$regex": rePattern } }] }); } if (data.category) { if (data.category === "tenant") { andCond.push({ "$or": [ { "category": data.category }, { "category": null } ] }); } else { andCond.push({ "category": data.category }); } } if (andCond.length > 0) { condition.$and = andCond; } let options = { "skip": 0, "limit": 500, "sort": { "name": 1 } }; if (data && data.limit) { options.limit = data.limit; } if (data && data.start) { options.skip = data.start; } __self.mongoCore.find(colName, condition, options, (error, response) => { if (error) { return cb(error); } else { let current_count = options.skip; if (response && response.length) { current_count = current_count + response.length; } if (current_count < options.limit) { return cb(null, { "limit": options.limit, "start": options.skip, "count": response.length, "items": response }); } else { __self.count(data, condition, (error, count) => { if (error) { return cb(error); } else { return cb(null, { "limit": options.limit, "start": options.skip, "count": count, "items": response }); } }); } } }); }; Tenant.prototype.count = function (data, condition, cb) { let __self = this; let options = {}; __self.mongoCore.countDocuments(colName, condition, options, cb); }; Tenant.prototype.listConsoleTenants = function (data, cb) { let __self = this; let options = { "skip": 0, "limit": 500, "sort": { "name": 1 } }; if (data && data.limit) { options.limit = data.limit; } if (data && data.start) { options.skip = data.start; } let condition = { '$and': [{ console: true }] }; if (data.keywords) { let rePattern = new RegExp(data.keywords, 'i'); condition.$and.push({ "$or": [{ "name": { "$regex": rePattern } }, { "code": { "$regex": rePattern } }] }); } if (data && data.type) { condition.$and.push({ 'type': data.type }); } if (data.category) { if (data.category === "tenant") { condition.$and.push({ "$or": [ { "category": data.category }, { "category": null } ] }); } else { condition.$and.push({ "category": data.category }); } } let find = (condition) => { __self.mongoCore.find(colName, condition, options, (error, response) => { if (error) { return cb(error); } else { let current_count = options.skip; if (response && response.length) { current_count = current_count + response.length; } if (current_count < options.limit) { return cb(null, { "limit": options.limit, "start": options.skip, "count": response.length, "items": response }); } else { __self.count(data, condition, (error, count) => { if (error) { return cb(error); } else { return cb(null, { "limit": options.limit, "start": options.skip, "count": count, "items": response }); } }); } } }); }; if (data.scope === "other") { __self.validateId(data.id, (err, id) => { if (err) { return cb(err, null); } condition.$and.push({ "_id": { "$ne": id } }); find(condition); }); } else { find(condition); } }; Tenant.prototype.listAllTenants = function (data, cb) { let __self = this; let fields = null; if (data) { if (data.fields && Array.isArray(data.fields) && data.fields.length > 0) { fields = {}; data.fields.forEach((oneField) => { fields[oneField] = 1; }); } } __self.mongoCore.find(colName, {}, { "fields": fields }, cb); }; Tenant.prototype.countTenants = function (data, cb) { let __self = this; if (!data || !data.name) { let error = new Error("name is required."); return cb(error, null); } data.name = data.name.trim(); // data.name = data.name.toLowerCase(); let condition = { name: data.name }; if (data.code) { condition.code = data.code; } let options = {}; __self.mongoCore.countDocuments(colName, condition, options, cb); }; Tenant.prototype.generateId = function () { let __self = this; return __self.mongoCore.ObjectId(); }; Tenant.prototype.addTenant = function (data, cb) { let __self = this; if (!data || !data.code || !data.name) { let error = new Error("name and code are required."); return cb(error, null); } data.name = data.name.trim(); // data.name = data.name.toLowerCase(); __self.mongoCore.insertOne(colName, data, {}, (err, record) => { if (record && Array.isArray(record)) { record = record[0]; } return cb(err, record); }); }; Tenant.prototype.deleteTenants = function (data, cb) { let __self = this; if (!data || !data.ids) { let error = new Error("ids is required."); return cb(error, null); } const objectIdsArray = data.ids.map((id) => __self.mongoCore.ObjectId(id)); let condition = { "_id": { "$in": objectIdsArray } }; __self.mongoCore.deleteMany(colName, condition, {}, (err, result) => { return cb(err, result); }); }; Tenant.prototype.deleteTenant = function (data, cb) { let __self = this; if (!data || !(data._id || data.code)) { let error = new Error("id or code is required."); return cb(error, null); } let condition = {}; if (data._id) { condition._id = data._id; } else { condition.code = data.code; } __self.mongoCore.deleteOne(colName, condition, {}, (err, count) => { return cb(err, count); }); }; Tenant.prototype.updateTenant = function (data, cb) { let __self = this; if (!data || !data._id) { let error = new Error("_id is required."); return cb(error, null); } let condition = { '_id': data._id }; let options = { 'upsert': false, 'safe': true }; let fields = { '$set': {} }; if (data.description) { fields.$set.description = data.description; } if (data.name) { data.name = data.name.trim(); // data.name = data.name.toLowerCase(); fields.$set.name = data.name; } if (data.tag) { fields.$set.tag = data.tag; } if (data.category) { fields.$set.category = data.category; } if (data.profile) { fields.$set.profile = data.profile; } if (data.applications) { fields.$set.applications = data.applications; } if (data.oauth) { fields.$set.oauth = data.oauth; } if (Object.keys(fields.$set).length === 0) { //nothing to update return cb(null, 0); } __self.mongoCore.updateOne(colName, condition, fields, options, (err, result) => { if (err) { return cb(err); } else { if (result && result.nModified) { result = result.nModified; } else { if (result && result.ok && result.upserted && Array.isArray(result.upserted)) { result = result.upserted.length; } else { result = 0; } } return cb(err, result); } }); }; Tenant.prototype.removeApplication = function (data, cb) { let __self = this; if (!data || !data._id || !data.appId) { let error = new Error("_id and appId are required."); return cb(error, null); } let condition = { '_id': data._id }; let options = { 'upsert': false, 'safe': true }; try { data.appId = __self.mongoCore.ObjectId(data.appId); } catch (e) { return cb(e); } let fields = { '$pull': { 'applications': { "appId": __self.mongoCore.ObjectId(data.appId) } } }; __self.mongoCore.updateOne(colName, condition, fields, options, (err, result) => { if (err) { return cb(err); } else { if (result && result.nModified) { result = result.nModified; } else { if (result && result.ok && result.upserted && Array.isArray(result.upserted)) { result = result.upserted.length; } else { result = 0; } } return cb(err, result); } }); }; Tenant.prototype.removeApplicationKey = function (data, cb) { let __self = this; if (!data || !data._id || !data.appId || !data.key) { let error = new Error("_id, appId, and key are required."); return cb(error, null); } try { data.appId = __self.mongoCore.ObjectId(data.appId); } catch (e) { return cb(e); } let condition = { '_id': data._id, 'applications.appId': data.appId }; let options = { 'upsert': false, 'safe': true }; let fields = { '$pull': { 'applications.$.keys': { "key": data.key } } }; __self.mongoCore.updateOne(colName, condition, fields, options, (err, result) => { if (err) { return cb(err); } else { if (result && result.nModified) { result = result.nModified; } else { if (result && result.ok && result.upserted && Array.isArray(result.upserted)) { result = result.upserted.length; } else { result = 0; } } return cb(err, result); } }); }; Tenant.prototype.closeConnection = function () { let __self = this; __self.mongoCore.closeDb(); }; module.exports = Tenant;