UNPKG

soajs.multitenant

Version:
1,674 lines (1,599 loc) 53.6 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 uuid = require("uuid"); const async = require('async'); const request = require("request"); function computeErrorMessageFromService(body) { if (body && !body.result) { let error = ""; if (body.errors && body.errors && body.errors.details && body.errors.details.length > 0) { body.errors.details.forEach((detail) => { if (error === "") { error += " " + detail.message; } else { error += " - " + detail.message; } }); } return new Error(error); } else { return new Error(" Service not found"); } } function getRequestedSubElementsPositions(tenantRecord, inputmaskData) { let found = false; let position = []; //find the application if (tenantRecord.applications) { for (let i = 0; i < tenantRecord.applications.length; i++) { if (tenantRecord.applications[i] && tenantRecord.applications[i].appId && tenantRecord.applications[i].appId.toString() === inputmaskData.appId) { position.push(i); //application position found //if key is requested, go one level deeper if (inputmaskData.key) { //find the key for (let j = 0; j < tenantRecord.applications[i].keys.length; j++) { if (tenantRecord.applications[i].keys[j].key === inputmaskData.key) { position.push(j); //application key position found //if extKey is requested, go one level deeper if (inputmaskData.extKey && inputmaskData.extKeyEnv && tenantRecord.applications[i].keys[j] && tenantRecord.applications[i].keys[j].extKeys) { //find the ext key for (let k = 0; k < tenantRecord.applications[i].keys[j].extKeys.length; k++) { if (tenantRecord.applications[i].keys[j].extKeys[k].extKey === inputmaskData.extKey && tenantRecord.applications[i].keys[j].extKeys[k].env === inputmaskData.extKeyEnv) { position.push(k); //application extKey found //no need to go further, simply return found = true; break; } } } //else return what is found else { found = true; break; } } } } //else return what is found else { found = true; break; } } } } return {'found': found, 'position': position}; } let bl = { "modelObj": null, "model": null, "soajs_service": null, "localConfig": null, "handleError": (soajs, errCode, err) => { if (err) { soajs.log.error(err.message); } return ({ "code": errCode, "msg": bl.localConfig.errors[errCode] + ((err && errCode === 602) ? err.message : "") }); }, "mp": { "getModel": (soajs) => { let modelObj = bl.modelObj; if (soajs && soajs.tenant && soajs.tenant.type === "client" && soajs.tenant.dbConfig) { let options = { "dbConfig": soajs.tenant.dbConfig, "index": soajs.tenant.id }; modelObj = new bl.model(bl.soajs_service, options, null); } return modelObj; }, "closeModel": (soajs, modelObj) => { if (soajs && soajs.tenant && soajs.tenant.type === "client" && soajs.tenant.dbConfig) { modelObj.closeConnection(); } } }, /** * tenant */ "tenants_product_extKeys": (soajs, inputmaskData, cb) => { if (!inputmaskData || !inputmaskData.tenants || !inputmaskData.tenants.tenant || !inputmaskData.tenants.tenant.code || !inputmaskData.productCode || !inputmaskData.env) { return cb(bl.handleError(soajs, 400, null)); } let buildKeyObj = (record) => { let t_obj = { "code": record.code, "id": record._id, "extKeys": [] }; if (record.tenant) { t_obj.tenant = record.tenant; } if (inputmaskData.profile && record.profile) { t_obj.profile = record.profile; } for (let a = 0; a < record.applications.length; a++) { if (record.applications[a].product === inputmaskData.productCode) { t_obj.product = record.applications[a].product; t_obj.package = record.applications[a].package; if (record.applications[a].keys) { for (let k = 0; k < record.applications[a].keys.length; k++) { if (record.applications[a].keys[k].extKeys) { for (let ek = 0; ek < record.applications[a].keys[k].extKeys.length; ek++) { delete record.applications[a].keys[k].extKeys[ek].device; delete record.applications[a].keys[k].extKeys[ek].geo; delete record.applications[a].keys[k].extKeys[ek].dashboardAccess; if (record.applications[a].keys[k].extKeys[ek].env) { if (record.applications[a].keys[k].extKeys[ek].env.toLowerCase() === inputmaskData.env.toLowerCase()) { t_obj.extKeys.push(record.applications[a].keys[k].extKeys[ek]); } } else { t_obj.extKeys.push(record.applications[a].keys[k].extKeys[ek]); } } } } } } } return t_obj; }; let response = {}; let consoleTenant = !!inputmaskData.soajs; let data = { code: inputmaskData.tenants.tenant.code, soajs: consoleTenant }; let modelObj = bl.mp.getModel(soajs); modelObj.getTenant(data, (err, record) => { if (record) { response.tenant = buildKeyObj(record); } if (inputmaskData.tenants.allowedTenants) { let tenants_code_array = []; for (let i = 0; i < inputmaskData.tenants.allowedTenants.length; i++) { if (inputmaskData.tenants.allowedTenants[i].tenant && inputmaskData.tenants.allowedTenants[i].tenant.code) { tenants_code_array.push(inputmaskData.tenants.allowedTenants[i].tenant.code); } } if (tenants_code_array.length > 0) { let data = { codes: tenants_code_array, soajs: consoleTenant }; modelObj.getTenants(data, (err, records) => { if (records && records.length > 0) { response.allowedTenants = []; for (let t = 0; t < records.length; t++) { response.allowedTenants.push(buildKeyObj(records[t])); } } bl.mp.closeModel(soajs, modelObj); return cb(null, response); }); } else { bl.mp.closeModel(soajs, modelObj); return cb(null, response); } } else { bl.mp.closeModel(soajs, modelObj); return cb(null, response); } }); }, "get": (soajs, inputmaskData, cb) => { if (!inputmaskData) { return cb(bl.handleError(soajs, 400, null)); } let modelObj = bl.mp.getModel(soajs); let data = {}; data.id = inputmaskData.id; data.code = inputmaskData.code; data.name = inputmaskData.name; if (!data.id && !data.code && !data.name) { data.id = soajs.tenant.id; } data.soajs = !!inputmaskData.soajs; modelObj.getTenant(data, (err, record) => { bl.mp.closeModel(soajs, modelObj); if (err) { return cb(bl.handleError(soajs, 602, err)); } if (!record) { return cb(bl.handleError(soajs, 450, null)); } return cb(null, record); }); }, "getByIds": (soajs, inputmaskData, cb) => { if (!inputmaskData || !inputmaskData.ids) { return cb(bl.handleError(soajs, 400, null)); } let modelObj = bl.mp.getModel(soajs); let data = { ids: inputmaskData.ids }; modelObj.getTenantsById(data, (err, result) => { bl.mp.closeModel(soajs, modelObj); if (err) { return cb(bl.handleError(soajs, 602, err)); } return cb(null, result); }); }, "list": (soajs, inputmaskData, cb) => { if (!inputmaskData) { return cb(bl.handleError(soajs, 400, null)); } let modelObj = bl.mp.getModel(soajs); let data = {}; data.type = inputmaskData.type; data.keywords = inputmaskData.keywords; data.start = inputmaskData.start; data.limit = inputmaskData.limit; data.category = inputmaskData.category; modelObj.listTenants(data, (err, record) => { bl.mp.closeModel(soajs, modelObj); if (err) { return cb(bl.handleError(soajs, 602, err), null); } return cb(null, record ? record : []); }); }, "listTenantSubTenants": (soajs, inputmaskData, cb) => { if (!inputmaskData) { return cb(bl.handleError(soajs, 400, null)); } let modelObj = bl.mp.getModel(soajs); let data = {}; data.code = inputmaskData.code; data.keywords = inputmaskData.keywords; data.start = inputmaskData.start; data.limit = inputmaskData.limit; modelObj.listTenantSubTenants(data, (err, record) => { bl.mp.closeModel(soajs, modelObj); if (err) { return cb(bl.handleError(soajs, 602, err), null); } return cb(null, record ? record : []); }); }, "listConsole": (soajs, inputmaskData, cb) => { if (!inputmaskData) { return cb(bl.handleError(soajs, 400, null)); } let modelObj = bl.mp.getModel(soajs); let data = {}; data.scope = inputmaskData.scope || null; data.type = inputmaskData.type || null; data.keywords = inputmaskData.keywords; data.start = inputmaskData.start; data.limit = inputmaskData.limit; data.id = soajs.tenant.id; data.category = inputmaskData.category; modelObj.listConsoleTenants(data, (err, record) => { bl.mp.closeModel(soajs, modelObj); if (err) { return cb(bl.handleError(soajs, 602, err), null); } return cb(null, record ? record : []); }); }, "getApplication": (soajs, inputmaskData, cb) => { if (!inputmaskData) { return cb(bl.handleError(soajs, 400, null)); } let modelObj = bl.mp.getModel(soajs); let data = {}; data.id = inputmaskData.id; if (!data.id) { data.id = soajs.tenant.id; } data.soajs = !!inputmaskData.soajs; modelObj.getTenant(data, (err, tenantRecord) => { bl.mp.closeModel(soajs, modelObj); if (err) { return cb(bl.handleError(soajs, 602, err)); } if (!tenantRecord) { return cb(bl.handleError(soajs, 450, null)); } if (!tenantRecord.applications) { return cb(bl.handleError(soajs, 457, null)); } let application; for (let i = 0; i < tenantRecord.applications.length; i++) { if (!tenantRecord.applications[i] || !tenantRecord.applications[i].appId) { continue; } if (tenantRecord.applications[i].appId.toString() === inputmaskData.appId) { application = tenantRecord.applications[i]; break; } } if (application) { return cb(null, application); } else { return cb(bl.handleError(soajs, 457, null)); } }); }, "listApplications": (soajs, inputmaskData, cb) => { if (!inputmaskData) { return cb(bl.handleError(soajs, 400, null)); } let modelObj = bl.mp.getModel(soajs); let data = {}; data.id = inputmaskData.id; if (!data.id) { data.id = soajs.tenant.id; } data.soajs = !!inputmaskData.soajs; modelObj.getTenant(data, (err, record) => { bl.mp.closeModel(soajs, modelObj); if (err) { return cb(bl.handleError(soajs, 602, err), null); } if (!record) { return cb(bl.handleError(soajs, 450, err), null); } return cb(null, record.applications ? record.applications : []); }); }, "listApplicationKeys": (soajs, inputmaskData, cb) => { if (!inputmaskData) { return cb(bl.handleError(soajs, 400, null)); } let modelObj = bl.mp.getModel(soajs); let data = {}; data.id = inputmaskData.id; if (!data.id) { data.id = soajs.tenant.id; } data.soajs = !!inputmaskData.soajs; modelObj.getTenant(data, (err, record) => { bl.mp.closeModel(soajs, modelObj); if (err) { return cb(bl.handleError(soajs, 602, err), null); } if (!record) { return cb(bl.handleError(soajs, 450, err), null); } let keys = []; if (record.applications) { record.applications.forEach(function (oneApplication) { if (oneApplication.appId.toString() === inputmaskData.appId) { keys = oneApplication.keys; } }); } return cb(null, keys); }); }, "listApplicationExtKeys": (soajs, inputmaskData, cb) => { if (!inputmaskData) { return cb(bl.handleError(soajs, 400, null)); } let modelObj = bl.mp.getModel(soajs); let data = {}; data.id = inputmaskData.id; if (!data.id) { data.id = soajs.tenant.id; } data.soajs = !!inputmaskData.soajs; modelObj.getTenant(data, (err, tenantRecord) => { bl.mp.closeModel(soajs, modelObj); if (err) { return cb(bl.handleError(soajs, 602, err), null); } if (!tenantRecord) { return cb(bl.handleError(soajs, 450, err), null); } if (!tenantRecord.applications) { return cb(null, []); } let extKeys = []; for (let i = 0; i < tenantRecord.applications.length; i++) { if (!tenantRecord.applications[i] || !tenantRecord.applications[i].appId || !tenantRecord.applications[i].keys) { continue; } if (tenantRecord.applications[i].appId.toString() === inputmaskData.appId) { for (let j = 0; j < tenantRecord.applications[i].keys.length; j++) { if (tenantRecord.applications[i].keys[j].key === inputmaskData.key) { if (!tenantRecord.applications[i].keys[j].extKeys) { continue; } extKeys = tenantRecord.applications[i].keys[j].extKeys; break; } } } } return cb(null, extKeys); }); }, "listApplicationKeyConfig": (soajs, inputmaskData, cb) => { if (!inputmaskData) { return cb(bl.handleError(soajs, 400, null)); } let modelObj = bl.mp.getModel(soajs); let data = {}; data.id = inputmaskData.id; if (!data.id) { data.id = soajs.tenant.id; } data.soajs = !!inputmaskData.soajs; modelObj.getTenant(data, (err, record) => { bl.mp.closeModel(soajs, modelObj); if (err) { return cb(bl.handleError(soajs, 602, err), null); } if (!record) { return cb(bl.handleError(soajs, 450, err), null); } let x = getRequestedSubElementsPositions(record, inputmaskData); if (x.found && x.position.length === 2) { return cb(null, record.applications[x.position[0]].keys[x.position[1]].config); } else { return cb(null, {}); } }); }, "add": (soajs, inputmaskData, core, cb) => { const provision = core.provision; const soajsCore = core.core; if (!inputmaskData) { return cb(bl.handleError(soajs, 400, null)); } let modelObj = bl.mp.getModel(soajs); let record = { "_id": modelObj.generateId(), "type": inputmaskData.type, "name": inputmaskData.name, "description": inputmaskData.description, "oauth": { "secret": 'this is a secret', "redirectURI": 'http://domain.com', "grants": ["password", "refresh_token"], "disabled": 1, "type": 2, "loginMode": "urac" }, "console": !!inputmaskData.soajs, "applications": [] }; if (inputmaskData.code) { record.code = inputmaskData.code; } if (inputmaskData.oauth) { record.oauth = inputmaskData.oauth; if (!record.oauth.secret || record.oauth.secret === "") { record.oauth.secret = uuid.v4(); } } if (inputmaskData.profile) { record.profile = inputmaskData.profile; } if (inputmaskData.tag) { record.tag = inputmaskData.tag; } async.series({ checkIfExist: checkIfExist, checkSubTenant: checkSubTenant, checkApplication: checkApplication, checkCode: checkCode, insertRecord: insertRecord, }, (err, result) => { //err is handled and returned in each function above bl.mp.closeModel(soajs, modelObj); if (err) { return cb(err, null); } else { return cb(null, result.insertRecord); } }); function checkIfExist(callback) { let opts = {}; opts.name = inputmaskData.name; if (inputmaskData.code) { opts.code = inputmaskData.code; } modelObj.countTenants(opts, (err, count) => { if (err) { return callback(bl.handleError(soajs, 602, err)); } if (count > 0) { return callback(bl.handleError(soajs, 451, null)); } return callback(null); }); } function checkSubTenant(callback) { if (inputmaskData.type === "product") { return callback(null); } else { let opt = {}; if (inputmaskData.mainTenant) { opt.id = inputmaskData.mainTenant; } else { if (soajs.tenant.type === "client") { opt.id = soajs.tenant.main.id; } else { opt.id = soajs.tenant.id; } } opt.soajs = !!inputmaskData.soajs; modelObj.getTenant(opt, (err, mainTenant) => { if (err) { return callback(bl.handleError(soajs, 602, err)); } if (!mainTenant || !mainTenant.code) { return callback(bl.handleError(soajs, 453, null)); } record.tenant = { id: mainTenant._id.toString(), code: mainTenant.code }; //inherit form main tenant if oauth was not provided if (!inputmaskData.oauth && mainTenant.oauth) { record.oauth = mainTenant.oauth; } return callback(null); }); } } function checkCode(callback) { if (record.code) { return callback(null); } record.code = calculateCode(bl.localConfig.tenant.generatedCodeLength); return callback(null); } function calculateCode(length) { let code = ''; for (let i = 0; i < length; i++) { code += bl.localConfig.tenant.character.charAt(Math.floor(Math.random() * bl.localConfig.tenant.character.length)); } return code; } function checkApplication(callback) { if (!inputmaskData.application) { return callback(null); } else { if (!inputmaskData.application._TTL) { inputmaskData.application._TTL = 168; } let newApplication = { "product": inputmaskData.application.productCode, "package": inputmaskData.application.productCode + '_' + inputmaskData.application.packageCode, "appId": modelObj.generateId(), "description": inputmaskData.application.description || '', "_TTL": inputmaskData.application._TTL * 3600 * 1000, // 24 hours "keys": [] }; let oneKey = {}; createOrUseKey(function (error, internalKey) { if (error) { return callback(bl.handleError(soajs, 602, error)); } if (!internalKey) { record.applications.push(newApplication); return callback(null); } oneKey.key = internalKey; oneKey.config = inputmaskData.application.appKey.config ? inputmaskData.application.appKey.config : {}; oneKey.extKeys = []; newApplication.keys.push(oneKey); record.applications.push(newApplication); if (inputmaskData.application && inputmaskData.application.appKey && inputmaskData.application.appKey.extKey) { createExternalKey((error, extKey) => { if (error) { return callback(error); } else { if (extKey) { record.applications[0].keys[0].extKeys.push(extKey); } return callback(null); } }); } else { return callback(null); } }); } } function createOrUseKey(callback) { if (inputmaskData.application.appKey) { provision.generateInternalKey(callback); } else { return callback(null); } } function createExternalKey(callback) { if (inputmaskData.application && inputmaskData.application.appKey && inputmaskData.application.appKey.extKey) { soajs.awareness.connect("console", "1", (response) => { let options = { uri: 'http://' + response.host + "/registry/key", headers: response.headers, qs: {"env": inputmaskData.application.appKey.extKey.env.toLowerCase()}, json: true }; request.get(options, function (error, response, body) { if (error || !body.result) { return callback(bl.handleError(soajs, 503, computeErrorMessageFromService(body))); } let envKey = body.data; if (!envKey) { return callback(bl.handleError(soajs, 501, null)); } soajsCore.key.generateExternalKey( record.applications[0].keys[0].key, { id: record._id, "locked": false }, { "package": inputmaskData.application.productCode + '_' + inputmaskData.application.packageCode }, envKey, function (error, extKeyValue) { if (error) { return callback(bl.handleError(soajs, 502, error)); } let newExtKey = { "extKey": extKeyValue, "device": inputmaskData.application.appKey.extKey.device ? inputmaskData.application.appKey.extKey.device : null, "geo": inputmaskData.application.appKey.extKey.geo ? inputmaskData.application.appKey.extKey.geo : null, "env": inputmaskData.application.appKey.extKey.env.toUpperCase(), "label": inputmaskData.application.appKey.extKey.label, "expDate": (inputmaskData.application.appKey.extKey.expDate) ? new Date(inputmaskData.application.appKey.extKey.expDate).getTime() + bl.localConfig.tenant.expDateTTL : null }; return callback(null, newExtKey); } ); }); }); } else { return callback(null, null); } } function insertRecord(callback) { modelObj.addTenant(record, (err, response) => { if (err) { if (err.message && err.message.indexOf("code_1 dup key") !== -1 && !inputmaskData.code) { record.code = calculateCode(bl.localConfig.tenant.generatedCodeLength + 5); insertRecord(callback); } else { return callback(bl.handleError(soajs, 602, err), null); } } else { return callback(null, response); } }); } }, "addApplication": (soajs, inputmaskData, core, cb) => { const provision = core.provision; const soajsCore = core.core; if (!inputmaskData) { return cb(bl.handleError(soajs, 400, null)); } let modelObj = bl.mp.getModel(soajs); let data = {}; data.id = inputmaskData.id; if (!data.id) { data.id = soajs.tenant.id; } function createExternalKey(opt, callback) { if (inputmaskData.appKey.extKey) { soajs.awareness.connect("console", "1", (response) => { let options = { uri: 'http://' + response.host + "/registry/key", headers: response.headers, qs: {"env": inputmaskData.appKey.extKey.env.toLowerCase()}, json: true }; request.get(options, function (error, response, body) { if (error || !body.result) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 503, computeErrorMessageFromService(body))); } let envKey = body.data; if (!envKey) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 501, null)); } soajsCore.key.generateExternalKey(opt.key, { "id": opt.id, "code": opt.code, "locked": false }, { "product": opt.product, "package": opt.package, "appId": opt.appId, }, envKey, function (error, extKeyValue) { if (error) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 502, error)); } let newExtKey = { "extKey": extKeyValue, "device": inputmaskData.appKey.extKey.device ? inputmaskData.appKey.extKey.device : null, "geo": inputmaskData.appKey.extKey.geo ? inputmaskData.appKey.extKey.geo : null, "env": inputmaskData.appKey.extKey.env.toUpperCase(), "label": inputmaskData.appKey.extKey.label, "expDate": (inputmaskData.appKey.extKey.expDate) ? new Date(inputmaskData.appKey.extKey.expDate).getTime() + bl.localConfig.tenant.expDateTTL : null }; return callback(null, newExtKey); }); }); }); } else { return callback(null, null); } } function generateKey(app, tenantRecord, callback) { if (!inputmaskData.appKey) { return callback(); } provision.generateInternalKey(function (error, internalKey) { if (error) { return cb(bl.handleError(soajs, 602, error)); } let key = { key: internalKey, config: inputmaskData.appKey.config ? inputmaskData.appKey.config : {}, extKeys: [] }; let opt = { "code": tenantRecord.code, "id": tenantRecord._id, "appId": app.appId.toString(), "product": app.product, "package": app.package, "key": internalKey }; createExternalKey(opt, (error, extKey) => { let externalKey = null; if (extKey) { key.extKeys.push(extKey); externalKey = extKey.extKey; } app.keys.push(key); return callback(null, internalKey, externalKey); }); }); } data.soajs = !!inputmaskData.soajs; modelObj.getTenant(data, (err, tenantRecord) => { if (err) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 602, err)); } if (!tenantRecord) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 450, null)); } if (!soajs.tenant.locked && tenantRecord && tenantRecord.locked) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 500, null)); } if (!tenantRecord.applications) { tenantRecord.applications = []; } if (!inputmaskData._TTL) { inputmaskData._TTL = 168; } let newApplication = { "product": inputmaskData.productCode, "package": inputmaskData.productCode + '_' + inputmaskData.packageCode, "appId": modelObj.generateId(), "description": inputmaskData.description || '', "_TTL": inputmaskData._TTL * 3600 * 1000, // 24 hours "keys": [] }; if (inputmaskData.packageCode.indexOf(inputmaskData.productCode + "_") === 0) { newApplication.package = inputmaskData.packageCode; } generateKey(newApplication, tenantRecord, (err, internalKey, externalKey) => { tenantRecord.applications.push(newApplication); data = { _id: tenantRecord._id, applications: tenantRecord.applications }; modelObj.updateTenant(data, (err) => { bl.mp.closeModel(soajs, modelObj); if (err) { return cb(bl.handleError(soajs, 471, err)); } return cb(null, { intKey: internalKey ? internalKey : 1, extKey: externalKey ? externalKey : 1, appId: newApplication.appId } ); }); }); }); }, "addApplicationKey": (soajs, inputmaskData, core, cb) => { const provision = core.provision; const soajsCore = core.core; if (!inputmaskData) { return cb(bl.handleError(soajs, 400, null)); } let modelObj = bl.mp.getModel(soajs); let data = {}; data.id = inputmaskData.id; if (!data.id) { data.id = soajs.tenant.id; } function createExternalKey(opt, callback) { if (inputmaskData.extKey) { soajs.awareness.connect("console", "1", (response) => { let options = { uri: 'http://' + response.host + "/registry/key", headers: response.headers, qs: {"env": inputmaskData.extKey.env.toLowerCase()}, json: true }; request.get(options, function (error, response, body) { if (error || !body.result) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 503, computeErrorMessageFromService(body))); } let envKey = body.data; if (!envKey) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 501, null)); } soajsCore.key.generateExternalKey(opt.key, { "id": opt.id, "code": opt.code, "locked": false }, { "product": opt.product, "package": opt.package, "appId": opt.appId, }, envKey, function (error, extKeyValue) { if (error) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 502, error)); } let newExtKey = { "extKey": extKeyValue, "device": inputmaskData.extKey.device ? inputmaskData.extKey.device : null, "geo": inputmaskData.extKey.geo ? inputmaskData.extKey.geo : null, "env": inputmaskData.extKey.env.toUpperCase(), "label": inputmaskData.extKey.label, "expDate": (inputmaskData.extKey.expDate) ? new Date(inputmaskData.extKey.expDate).getTime() + bl.localConfig.tenant.expDateTTL : null }; return callback(null, newExtKey); }); }); }); } else { return callback(null, null); } } data.soajs = !!inputmaskData.soajs; modelObj.getTenant(data, (err, tenantRecord) => { if (err) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 602, err)); } if (!tenantRecord) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 450, null)); } if (!soajs.tenant.locked && tenantRecord && tenantRecord.locked) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 500, null)); } let found = false; if (!tenantRecord.applications) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 472, null)); } let key = {}; async.each(tenantRecord.applications, function (application, callback) { if (application.appId && application.appId.toString() === inputmaskData.appId) { found = true; provision.generateInternalKey(function (error, internalKey) { if (error) { return cb(bl.handleError(soajs, 602, error)); } key.key = internalKey; key.config = inputmaskData.config ? inputmaskData.config : {}; key.extKeys = []; let opt = { "code": tenantRecord.code, "id": tenantRecord._id, "appId": inputmaskData.appId, "product": application.product, "package": application.package, "key": internalKey }; createExternalKey(opt, (error, extKey) => { if (extKey) { key.extKeys.push(extKey); } application.keys.push(key); return callback(); }); }); } else { return callback(); } }, function () { if (!found) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 472, null)); } data = { _id: tenantRecord._id, applications: tenantRecord.applications }; modelObj.updateTenant(data, (err, response) => { bl.mp.closeModel(soajs, modelObj); if (err) { return cb(bl.handleError(soajs, 471, err)); } return cb(null, response); }); }); }); }, "addApplicationExtKey": (soajs, inputmaskData, core, cb) => { const soajsCore = core.core; if (!inputmaskData) { return cb(bl.handleError(soajs, 400, null)); } let modelObj = bl.mp.getModel(soajs); let data = {}; data.id = inputmaskData.id; if (!data.id) { data.id = soajs.tenant.id; } function createExternalKey(opt, callback) { soajs.awareness.connect("console", "1", (response) => { let options = { uri: 'http://' + response.host + "/registry/key", headers: response.headers, qs: {"env": inputmaskData.env.toLowerCase()}, json: true }; request.get(options, function (error, response, body) { if (error || !body.result) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 503, computeErrorMessageFromService(body))); } let envKey = body.data; if (!envKey) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 501, null)); } soajsCore.key.generateExternalKey(opt.key, { "id": opt.id, "code": opt.code, "locked": false }, { "product": opt.product, "package": opt.package, "appId": opt.appId, }, envKey, function (error, extKeyValue) { if (error) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 502, error)); } let newExtKey = { "extKey": extKeyValue, "device": inputmaskData.device ? inputmaskData.device : null, "geo": inputmaskData.geo ? inputmaskData.geo : null, "env": inputmaskData.env.toUpperCase(), "label": inputmaskData.label, "expDate": (inputmaskData.expDate) ? new Date(inputmaskData.expDate).getTime() + bl.localConfig.tenant.expDateTTL : null }; return callback(null, newExtKey); }); }); }); } data.soajs = !!inputmaskData.soajs; modelObj.getTenant(data, (err, tenantRecord) => { if (err) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 602, err)); } if (!tenantRecord) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 450, null)); } if (!soajs.tenant.locked && tenantRecord && tenantRecord.locked) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 500, null)); } let found = false; if (!tenantRecord.applications) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 472, null)); } async.each(tenantRecord.applications, function (application, callback) { if (application.appId && application.appId.toString() === inputmaskData.appId) { async.each(application.keys, function (oneKey, call) { if (oneKey.key === inputmaskData.key) { found = true; let opt = { "code": tenantRecord.code, "id": tenantRecord._id, "appId": inputmaskData.appId, "product": application.product, "package": application.package, "key": inputmaskData.key }; createExternalKey(opt, (error, extKey) => { if (extKey) { if (!oneKey.extKeys) { oneKey.extKeys = []; } oneKey.extKeys.push(extKey); } return call(); }); } else { return call(); } }, callback); } else { return callback(); } }, function () { if (!found) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 473, null)); } data = { _id: tenantRecord._id, applications: tenantRecord.applications }; modelObj.updateTenant(data, (err, response) => { bl.mp.closeModel(soajs, modelObj); if (err) { return cb(bl.handleError(soajs, 471, err)); } return cb(null, response); }); }); }); }, "updateTenant": (soajs, inputmaskData, cb) => { if (!inputmaskData) { return cb(bl.handleError(soajs, 400, null)); } let modelObj = bl.mp.getModel(soajs); let data = {}; data.id = inputmaskData.id; if (!data.id) { data.id = soajs.tenant.id; } data.soajs = !!inputmaskData.soajs; modelObj.getTenant(data, (err, record) => { if (err) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 602, err)); } if (!record) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 450, null)); } if (!soajs.tenant.locked && record && record.locked) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 500, null)); } data = { _id: record._id }; if (inputmaskData.tag) { data.tag = inputmaskData.tag; } if (inputmaskData.category) { data.category = inputmaskData.category; } if (inputmaskData.name) { data.name = inputmaskData.name; } if (inputmaskData.description) { data.description = inputmaskData.description; } if (inputmaskData.profile) { data.profile = inputmaskData.profile; } modelObj.updateTenant(data, (err, response) => { bl.mp.closeModel(soajs, modelObj); if (err) { return cb(bl.handleError(soajs, 471, err)); } return cb(null, response); }); }); }, "updateProfile": (soajs, inputmaskData, cb) => { if (!inputmaskData) { return cb(bl.handleError(soajs, 400, null)); } let modelObj = bl.mp.getModel(soajs); let data = {}; data.id = inputmaskData.id; if (!data.id) { data.id = soajs.tenant.id; } data.soajs = !!inputmaskData.soajs; modelObj.getTenant(data, (err, record) => { if (err) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 602, err)); } if (!record) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 450, null)); } if (!soajs.tenant.locked && record && record.locked) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 500, null)); } data = { _id: record._id, profile: inputmaskData.profile }; modelObj.updateTenant(data, (err, response) => { bl.mp.closeModel(soajs, modelObj); if (err) { return cb(bl.handleError(soajs, 471, err)); } return cb(null, response); }); }); }, "updateApplication": (soajs, inputmaskData, cb) => { if (!inputmaskData) { return cb(bl.handleError(soajs, 400, null)); } let modelObj = bl.mp.getModel(soajs); let data = {}; data.id = inputmaskData.id; if (!data.id) { data.id = soajs.tenant.id; } data.soajs = !!inputmaskData.soajs; modelObj.getTenant(data, (err, tenantRecord) => { if (err) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 602, err), null); } if (!tenantRecord) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 450, null), null); } if (!soajs.tenant.locked && tenantRecord && tenantRecord.locked) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 500, null)); } let found = false; if (!tenantRecord.applications) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 472, null)); } for (let i = 0; i < tenantRecord.applications.length; i++) { if (!tenantRecord.applications[i] || !tenantRecord.applications[i].appId) { continue; } if (tenantRecord.applications[i].appId.toString() === inputmaskData.appId) { if (inputmaskData.description) { tenantRecord.applications[i].description = inputmaskData.description; } if (inputmaskData.packageCode) { tenantRecord.applications[i].package = tenantRecord.applications[i].product + "_" + inputmaskData.packageCode; } if (inputmaskData._TTL) { tenantRecord.applications[i]._TTL = inputmaskData._TTL * 3600 * 1000; } found = true; break; } } if (!found) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 472, null)); } data = { _id: tenantRecord._id, applications: tenantRecord.applications }; modelObj.updateTenant(data, (err, response) => { bl.mp.closeModel(soajs, modelObj); if (err) { return cb(bl.handleError(soajs, 471, err)); } return cb(null, response); }); }); }, "updateApplicationKey": (soajs, inputmaskData, cb) => { if (!inputmaskData) { return cb(bl.handleError(soajs, 400, null)); } let modelObj = bl.mp.getModel(soajs); let data = {}; data.id = inputmaskData.id; if (!data.id) { data.id = soajs.tenant.id; } data.soajs = !!inputmaskData.soajs; modelObj.getTenant(data, (err, tenantRecord) => { if (err) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 602, err), null); } if (!tenantRecord) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 450, err), null); } if (!soajs.tenant.locked && tenantRecord && tenantRecord.locked) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 500, null)); } if (!tenantRecord.applications) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 472, null)); } let found = false; for (let i = 0; i < tenantRecord.applications.length; i++) { if (!tenantRecord.applications[i] || !tenantRecord.applications[i].appId || !tenantRecord.applications[i].keys) { continue; } if (tenantRecord.applications[i].appId.toString() === inputmaskData.appId) { for (let j = 0; j < tenantRecord.applications[i].keys.length; j++) { if (tenantRecord.applications[i].keys[j].key === inputmaskData.key) { tenantRecord.applications[i].keys[j].config = inputmaskData.config; found = true; break; } } } } if (!found) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 473, null)); } data = { _id: tenantRecord._id, applications: tenantRecord.applications }; modelObj.updateTenant(data, (err, response) => { bl.mp.closeModel(soajs, modelObj); if (err) { return cb(bl.handleError(soajs, 471, err)); } return cb(null, response); }); }); }, "updateApplicationExternalKey": (soajs, inputmaskData, cb) => { if (!inputmaskData) { return cb(bl.handleError(soajs, 400, null)); } let modelObj = bl.mp.getModel(soajs); let data = {}; data.id = inputmaskData.id; if (!data.id) { data.id = soajs.tenant.id; } data.soajs = !!inputmaskData.soajs; modelObj.getTenant(data, (err, tenantRecord) => { if (err) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 602, err), null); } if (!tenantRecord) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 450, err), null); } if (!soajs.tenant.locked && tenantRecord && tenantRecord.locked) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 500, null)); } let found = false; if (!tenantRecord.applications) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 472, null)); } for (let i = 0; i < tenantRecord.applications.length; i++) { if (!tenantRecord.applications[i] || !tenantRecord.applications[i].appId || !tenantRecord.applications[i].keys) { continue; } if (tenantRecord.applications[i].appId.toString() === inputmaskData.appId) { for (let j = 0; j < tenantRecord.applications[i].keys.length; j++) { if (tenantRecord.applications[i].keys[j].key === inputmaskData.key) { if (!tenantRecord.applications[i].keys[j].extKeys) { continue; } for (let x = 0; x < tenantRecord.applications[i].keys[j].extKeys.length; x++) { if (!tenantRecord.applications[i].keys[j].extKeys[x]) { continue; } if (tenantRecord.applications[i].keys[j].extKeys[x].extKey === inputmaskData.extKey) { if (inputmaskData.device) { tenantRecord.applications[i].keys[j].extKeys[x].device = inputmaskData.device; } if (inputmaskData.geo) { tenantRecord.applications[i].keys[j].extKeys[x].geo = inputmaskData.geo; } //if (inputmaskData.expDate) { tenantRecord.applications[i].keys[j].extKeys[x].expDate = inputmaskData.expDate || null; //} if (inputmaskData.extKeyEnv) { tenantRecord.applications[i].keys[j].extKeys[x].env = inputmaskData.extKeyEnv.toUpperCase(); } if (inputmaskData.label) { tenantRecord.applications[i].keys[j].extKeys[x].label = inputmaskData.label; } found = true; break; } } } } } } if (!found) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 473, null)); } data = { _id: tenantRecord._id, applications: tenantRecord.applications }; modelObj.updateTenant(data, (err, response) => { bl.mp.closeModel(soajs, modelObj); if (err) { return cb(bl.handleError(soajs, 471, err)); } return cb(null, response); }); }); }, "deleteMany": (soajs, inputmaskData, cb) => { if (!inputmaskData) { return cb(bl.handleError(soajs, 400, null)); } let modelObj = bl.mp.getModel(soajs); modelObj.deleteTenants(inputmaskData, (err, result) => { bl.mp.closeModel(soajs, modelObj); if (err) { return cb(bl.handleError(soajs, 602, err)); } return cb(null, result); }); }, "delete": (soajs, inputmaskData, cb) => { if (!inputmaskData) { return cb(bl.handleError(soajs, 400, null)); } let modelObj = bl.mp.getModel(soajs); let data = {}; data.code = inputmaskData.code; data.id = inputmaskData.id; data.soajs = !!inputmaskData.soajs; modelObj.getTenant(data, (err, record) => { if (err) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 602, err)); } if (!record) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 450, null)); } if (record._id && record._id.toString() === soajs.tenant.id) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 462, null)); } if (!soajs.tenant.locked && record && record.locked) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 500, null)); } data._id = record._id; modelObj.deleteTenant(data, (err, result) => { bl.mp.closeModel(soajs, modelObj); if (err) { return cb(bl.handleError(soajs, 602, err)); } return cb(null, result); }); }); }, "deleteApplication": (soajs, inputmaskData, cb) => { if (!inputmaskData) { return cb(bl.handleError(soajs, 400, null)); } let modelObj = bl.mp.getModel(soajs); let data = {}; data.code = inputmaskData.code; data.id = inputmaskData.id; data.soajs = !!inputmaskData.soajs; modelObj.getTenant(data, (err, record) => { if (err) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 602, err)); } if (!record) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 450, null)); } if (record._id && record._id.toString() === soajs.tenant.id) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 462, null)); } if (!soajs.tenant.locked && record && record.locked) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 500, null)); } data = { _id: record._id, appId: inputmaskData.appId }; modelObj.removeApplication(data, (err, response) => { bl.mp.closeModel(soajs, modelObj); if (err) { return cb(bl.handleError(soajs, 471, err)); } return cb(null, response); }); }); }, "deleteApplicationKey": (soajs, inputmaskData, cb) => { if (!inputmaskData) { return cb(bl.handleError(soajs, 400, null)); } let modelObj = bl.mp.getModel(soajs); let data = {}; data.code = inputmaskData.code; data.id = inputmaskData.id; data.soajs = !!inputmaskData.soajs; modelObj.getTenant(data, (err, record) => { if (err) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 602, err)); } if (!record) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 450, null)); } if (record._id && record._id.toString() === soajs.tenant.id) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 462, null)); } if (!soajs.tenant.locked && record && record.locked) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 500, null)); } data = { _id: record._id, appId: inputmaskData.appId, key: inputmaskData.key }; modelObj.removeApplicationKey(data, (err, response) => { bl.mp.closeModel(soajs, modelObj); if (err) { return cb(bl.handleError(soajs, 471, err)); } return cb(null, response); }); }); }, "deleteApplicationExternalKey": (soajs, inputmaskData, cb) => { if (!inputmaskData) { return cb(bl.handleError(soajs, 400, null)); } let modelObj = bl.mp.getModel(soajs); let data = {}; data.code = inputmaskData.code; data.id = inputmaskData.id; data.soajs = !!inputmaskData.soajs; modelObj.getTenant(data, (err, tenantRecord) => { if (err) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 602, err)); } if (!tenantRecord) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 450, null)); } if (tenantRecord._id && tenantRecord._id.toString() === soajs.tenant.id) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 462, null)); } if (!soajs.tenant.locked && tenantRecord && tenantRecord.locked) { bl.mp.closeModel(soajs, modelObj); return cb(bl.handleError(soajs, 500, null)); } let found = 0; if (!tenantRecord.applications) { return cb(null, found); } for (let i = 0; i < tenantRecord.applications.length; i++) { if (!tenantRecord.applications[i] || !tenantRecord.applications[i].appId || !tenantRecord.applications[i].keys) { continue; } if (tenantRecord.applications[i].appId.toString() === inputmaskData.appId) { for (let j = 0; j < tenantRecord.applications[i].keys.length; j++) { if (tenantRecord.applications[i].keys[j].key === inputmaskData.key) { if (!tenantRecord.applications[i].keys[j].extKeys) { continue; } for (let x = 0; x < tenantRecord.applications[i].keys[j].extKeys.length; x++) { if (!tenantRecord.applications[i].keys[j].extKeys[x]) { continue; } if (tenantRecord.applications[i].keys[j].extKeys[x].extKey === inputmaskData.extKey) { tenantRecord.applications[i].keys[j].extKeys.splice(x, 1); found = 1; break; } } } } } } if (found === 0) { return cb(null, found); } data = { _id: tenantRecord._id, applications: tenantRecord.applications }; modelObj.updateTenant(data, (err, response) => { bl.mp.closeModel(soajs, modelObj); if (err) { return cb(bl.handleError(soajs, 471, err)); } return cb(null, response); }); }); }, "updateApplicationKeyConfig": (soajs, inputmaskData, cb) => { if (!inputmaskData) { return cb(bl.handleError(soajs, 400, null)); } let modelObj = bl.mp.getModel(soajs); let data = {}; data.id = inputmaskData.id; if (!data.id) { data.id = soajs.tenant.id; } data.soajs = !!inputmaskData.soajs; modelObj.getTenant(data, (err, record) => { bl.mp.closeModel(soajs, modelObj); if (err) { return cb(bl.handleError(soajs, 602, err), null); } if (!record) { return cb(bl.handleError(soajs, 450, err), null); } let x = getRequestedSubElementsPositions(record, inputmaskData); //check config input for throttling null entries for (let service in inputmaskData.config) { if (service && inputmaskData.config.hasOwnProperty(service)) { if (inputmaskData.config[service] && inputmaskData.config.hasOwnProperty(service) && inputmaskData.config[service].SOAJS && inputmaskData.config[service].SOAJS.THROTTLING) { for (let strategy in