Changing tenant id to object setting storage
MODIFY
src/client/oicp/OICPClient.ts
src/client/oicp/OICPClient.ts
@@ -149,7 +149,7 @@ export default abstract class OICPClient {
module: MODULE_NAME, method: 'getPrivateKey',
});
}
- return await Cypher.decrypt(this.tenant.id, this.settings[this.role].key);
+ return await Cypher.decrypt(this.tenant, this.settings[this.role].key);
}
private async getClientCertificate(action: ServerAction): Promise<string> {
@@ -165,7 +165,7 @@ export default abstract class OICPClient {
module: MODULE_NAME, method: 'getClientCertificate',
});
}
- return await Cypher.decrypt(this.tenant.id, this.settings[this.role].cert);
+ return await Cypher.decrypt(this.tenant, this.settings[this.role].cert);
}
private getAxiosConfig(): AxiosRequestConfig {

MODIFY
src/integration/asset/greencom/GreencomAssetIntegration.ts
src/integration/asset/greencom/GreencomAssetIntegration.ts
@@ -180,7 +180,7 @@ export default class GreencomAssetIntegration extends AssetIntegration<AssetSett
return {
'grant_type': 'client_credentials',
'client_id': this.connection.greencomConnection.clientId,
- 'client_secret': await Cypher.decrypt(this.tenant.id, this.connection.greencomConnection.clientSecret)
+ 'client_secret': await Cypher.decrypt(this.tenant, this.connection.greencomConnection.clientSecret)
};
}

MODIFY
src/integration/asset/iothink/IothinkAssetIntegration.ts
src/integration/asset/iothink/IothinkAssetIntegration.ts
@@ -170,7 +170,7 @@ export default class IothinkAssetIntegration extends AssetIntegration<AssetSetti
const params = new URLSearchParams();
params.append('grant_type', 'password');
params.append('username', this.connection.iothinkConnection.user);
- params.append('password', await Cypher.decrypt(this.tenant.id, this.connection.iothinkConnection.password));
+ params.append('password', await Cypher.decrypt(this.tenant, this.connection.iothinkConnection.password));
return params;
}

MODIFY
src/integration/asset/lacroix/LacroixAssetIntegration.ts
src/integration/asset/lacroix/LacroixAssetIntegration.ts
@@ -59,7 +59,7 @@ export default class LacroixAssetIntegration extends AssetIntegration<AssetSetti
{
auth: {
username: this.connection.lacroixConnection.user,
- password: await Cypher.decrypt(this.tenant.id, this.connection.lacroixConnection.password)
+ password: await Cypher.decrypt(this.tenant, this.connection.lacroixConnection.password)
}
}
);
@@ -194,7 +194,7 @@ export default class LacroixAssetIntegration extends AssetIntegration<AssetSetti
private async getCredentialParams(): Promise<URLSearchParams> {
const params = new URLSearchParams();
params.append('email', this.connection.lacroixConnection.user);
- params.append('plainPassword', await Cypher.decrypt(this.tenant.id, this.connection.lacroixConnection.password));
+ params.append('plainPassword', await Cypher.decrypt(this.tenant, this.connection.lacroixConnection.password));
return params;
}
}

MODIFY
src/integration/asset/schneider/SchneiderAssetIntegration.ts
src/integration/asset/schneider/SchneiderAssetIntegration.ts
@@ -129,7 +129,7 @@ export default class SchneiderAssetIntegration extends AssetIntegration<AssetSet
const params = new URLSearchParams();
params.append('grant_type', 'password');
params.append('username', this.connection.schneiderConnection.user);
- params.append('password', await Cypher.decrypt(this.tenant.id, this.connection.schneiderConnection.password));
+ params.append('password', await Cypher.decrypt(this.tenant, this.connection.schneiderConnection.password));
return params;
}

MODIFY
src/integration/asset/wit/WitAssetIntegration.ts
src/integration/asset/wit/WitAssetIntegration.ts
@@ -127,10 +127,10 @@ export default class WitAssetIntegration extends AssetIntegration<AssetSetting>
private async getCredentialURLParams(): Promise<URLSearchParams> {
const params = new URLSearchParams();
params.append('client_id', this.connection.witConnection.clientId);
- params.append('client_secret', await Cypher.decrypt(this.tenant.id, this.connection.witConnection.clientSecret));
+ params.append('client_secret', await Cypher.decrypt(this.tenant, this.connection.witConnection.clientSecret));
params.append('grant_type', 'password');
params.append('username', this.connection.witConnection.user);
- params.append('password', await Cypher.decrypt(this.tenant.id, this.connection.witConnection.password));
+ params.append('password', await Cypher.decrypt(this.tenant, this.connection.witConnection.password));
params.append('scope', 'https://api.wit-datacenter.com');
return params;
}

MODIFY
src/integration/billing/stripe/StripeBillingIntegration.ts
src/integration/billing/stripe/StripeBillingIntegration.ts
@@ -58,7 +58,7 @@ export default class StripeBillingIntegration extends BillingIntegration {
// Initialize Stripe
if (!this.stripe) {
try {
- const secretKey = await Cypher.decrypt(this.tenant.id, this.settings.stripe.secretKey);
+ const secretKey = await Cypher.decrypt(this.tenant, this.settings.stripe.secretKey);
this.stripe = new Stripe(secretKey, {
apiVersion: '2020-08-27',
});
@@ -126,7 +126,7 @@ export default class StripeBillingIntegration extends BillingIntegration {
// Make sure the STRIPE account is not live
let secretKey: string, publicKey: string;
try {
- secretKey = await Cypher.decrypt(this.tenant.id, this.settings.stripe.secretKey);
+ secretKey = await Cypher.decrypt(this.tenant, this.settings.stripe.secretKey);
publicKey = this.settings.stripe.publicKey;
} catch (error) {
// Ignore error

MODIFY
src/integration/car-connector/CarConnectorFactory.ts
src/integration/car-connector/CarConnectorFactory.ts
@@ -11,7 +11,7 @@ export default class CarConnectorFactory {
static async getCarConnectorImpl(tenant: Tenant, connectorId: string): Promise<CarConnectorIntegration<CarConnectorSetting>> {
// Check if car connector component is active
if (Utils.isTenantComponentActive(tenant, TenantComponents.CAR_CONNECTOR)) {
- const settings = await SettingStorage.getCarConnectorSettings(tenant.id);
+ const settings = await SettingStorage.getCarConnectorSettings(tenant);
if (settings?.carConnector?.connections) {
// Find connection
const foundConnection = settings.carConnector.connections.find((connection) => connection.type === connectorId);

MODIFY
src/integration/car-connector/mercedes-connector/MercedesCarConnectorIntegration.ts
src/integration/car-connector/mercedes-connector/MercedesCarConnectorIntegration.ts
@@ -95,7 +95,7 @@ export default class MercedesCarConnectorIntegration extends CarConnectorIntegra
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
- 'Authorization': `Basic ${Buffer.from(this.connection.mercedesConnection.clientId + ':' + await Cypher.decrypt(this.tenant.id, this.connection.mercedesConnection.clientSecret)).toString('base64')}`
+ 'Authorization': `Basic ${Buffer.from(this.connection.mercedesConnection.clientId + ':' + await Cypher.decrypt(this.tenant, this.connection.mercedesConnection.clientSecret)).toString('base64')}`
},
});
await Logging.logDebug({
@@ -175,7 +175,7 @@ export default class MercedesCarConnectorIntegration extends CarConnectorIntegra
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
- 'Authorization': `Basic ${Buffer.from(this.connection.mercedesConnection.clientId + ':' + await Cypher.decrypt(this.tenant.id, this.connection.mercedesConnection.clientSecret)).toString('base64')}`
+ 'Authorization': `Basic ${Buffer.from(this.connection.mercedesConnection.clientId + ':' + await Cypher.decrypt(this.tenant, this.connection.mercedesConnection.clientSecret)).toString('base64')}`
}
});
await Logging.logDebug({

MODIFY
src/server/rest/v1/service/BillingService.ts
src/server/rest/v1/service/BillingService.ts
@@ -777,7 +777,7 @@ export default class BillingService {
// Load previous settings
const billingSettings = await SettingStorage.getBillingSetting(req.tenant);
UtilsService.assertObjectExists(action, billingSettings, 'Failed to load billing settings', MODULE_NAME, 'handleUpdateBillingSetting', req.user);
- await UtilsService.processSensitiveData(req.user.tenantID, billingSettings, newBillingProperties);
+ await UtilsService.processSensitiveData(req.tenant, billingSettings, newBillingProperties);
// Billing properties to preserve
const { usersLastSynchronizedOn } = billingSettings.billing;
const previousTransactionBillingState = !!billingSettings.billing.isTransactionBillingActivated;

MODIFY
src/server/rest/v1/service/SettingService.ts
src/server/rest/v1/service/SettingService.ts
@@ -156,7 +156,7 @@ export default class SettingService {
// Filter
const filteredRequest = SettingSecurity.filterSettingCreateRequest(req.body);
// Process the sensitive data if any
- await Cypher.encryptSensitiveDataInJSON(req.user.tenantID, filteredRequest);
+ await Cypher.encryptSensitiveDataInJSON(req.tenant, filteredRequest);
// Update timestamp
filteredRequest.createdBy = { 'id': req.user.id };
filteredRequest.createdOn = new Date();
@@ -217,14 +217,14 @@ export default class SettingService {
const hashedValueInDB = Cypher.hash(valueInDb);
if (valueInRequest !== hashedValueInDB) {
// Yes: Encrypt
- _.set(settingUpdate, property, await Cypher.encrypt(req.user.tenantID, valueInRequest));
+ _.set(settingUpdate, property, await Cypher.encrypt(req.tenant, valueInRequest));
} else {
// No: Put back the encrypted value
_.set(settingUpdate, property, valueInDb);
}
} else {
// Value in db is empty then encrypt
- _.set(settingUpdate, property, await Cypher.encrypt(req.user.tenantID, valueInRequest));
+ _.set(settingUpdate, property, await Cypher.encrypt(req.tenant, valueInRequest));
}
}
}
@@ -291,7 +291,7 @@ export default class SettingService {
// Crypto Setting handling
if (settingUpdate.identifier === TechnicalSettings.CRYPTO) {
if (settingUpdate.content.crypto.migrationToBeDone) {
- await Cypher.handleCryptoSettingsChange(req.user.tenantID);
+ await Cypher.handleCryptoSettingsChange(req.tenant);
}
}
// Log

MODIFY
src/server/rest/v1/service/TenantService.ts
src/server/rest/v1/service/TenantService.ts
@@ -179,14 +179,14 @@ export default class TenantService {
next();
}
- public static async createInitialSettingsForTenant(tenantID: string): Promise<void> {
- await this.createInitialCryptoSettings(tenantID);
- await this.createInitialUserSettings(tenantID);
+ public static async createInitialSettingsForTenant(tenant: Tenant): Promise<void> {
+ await this.createInitialCryptoSettings(tenant);
+ await this.createInitialUserSettings(tenant);
}
- public static async createInitialCryptoSettings(tenantID: string): Promise<void> {
+ public static async createInitialCryptoSettings(tenant: Tenant): Promise<void> {
// Check for settings in db
- const keySettings = await SettingStorage.getCryptoSettings(tenantID);
+ const keySettings = await SettingStorage.getCryptoSettings(tenant);
// Create Crypto Key Settings
if (!keySettings) {
const keySettingToSave: CryptoSettings = {
@@ -198,13 +198,13 @@ export default class TenantService {
}
} as CryptoSettings;
// Save Crypto Key Settings
- await SettingStorage.saveCryptoSettings(tenantID, keySettingToSave);
+ await SettingStorage.saveCryptoSettings(tenant, keySettingToSave);
}
}
- public static async createInitialUserSettings(tenantID: string): Promise<void> {
+ public static async createInitialUserSettings(tenant: Tenant): Promise<void> {
// Check for settings in db
- const userSettings = await SettingStorage.getUserSettings(tenantID);
+ const userSettings = await SettingStorage.getUserSettings(tenant);
// Create new user settings
if (!userSettings) {
const settingsToSave: UserSettings = {
@@ -215,7 +215,7 @@ export default class TenantService {
},
createdOn: new Date(),
};
- await SettingStorage.saveUserSettings(tenantID, settingsToSave);
+ await SettingStorage.saveUserSettings(tenant, settingsToSave);
}
}
@@ -393,12 +393,12 @@ export default class TenantService {
// Create settings
for (const componentName in tenant.components) {
// Get the settings
- const currentSetting = await SettingStorage.getSettingByIdentifier(tenant.id, componentName);
+ const currentSetting = await SettingStorage.getSettingByIdentifier(tenant, componentName);
// Check if Component is active
if (!tenant.components[componentName] || !tenant.components[componentName].active) {
// Delete settings
if (currentSetting) {
- await SettingStorage.deleteSetting(tenant.id, currentSetting.id);
+ await SettingStorage.deleteSetting(tenant, currentSetting.id);
}
continue;
}

MODIFY
src/server/rest/v1/service/UtilsService.ts
src/server/rest/v1/service/UtilsService.ts
@@ -1710,7 +1710,7 @@ export default class UtilsService {
}
// eslint-disable-next-line @typescript-eslint/ban-types
- public static async processSensitiveData(tenantID: string, currentProperties: object, newProperties: object): Promise<void> {
+ public static async processSensitiveData(tenant: Tenant, currentProperties: object, newProperties: object): Promise<void> {
// Process the sensitive data (if any)
const sensitivePropertyNames: string [] = _.get(currentProperties, 'sensitiveData');
if (sensitivePropertyNames) {
@@ -1734,14 +1734,14 @@ export default class UtilsService {
const currentHash = Cypher.hash(currentValue);
if (newValue !== currentHash) {
// Yes: Encrypt
- _.set(newProperties, propertyName, await Cypher.encrypt(tenantID, newValue));
+ _.set(newProperties, propertyName, await Cypher.encrypt(tenant, newValue));
} else {
// No: Put back the encrypted value
_.set(newProperties, propertyName, currentValue);
}
} else {
// Value in db is empty then encrypt
- _.set(newProperties, propertyName, await Cypher.encrypt(tenantID, newValue));
+ _.set(newProperties, propertyName, await Cypher.encrypt(tenant, newValue));
}
} else {
throw new AppError({

MODIFY
src/utils/Cypher.ts
src/utils/Cypher.ts
@@ -6,6 +6,7 @@ import Constants from './Constants';
import { LockEntity } from '../types/Locking';
import LockingManager from '../locking/LockingManager';
import SettingStorage from '../storage/mongodb/SettingStorage';
+import Tenant from '../types/Tenant';
import { TransformOptions } from 'stream';
import Utils from './Utils';
import _ from 'lodash';
@@ -17,9 +18,9 @@ interface CipherOptions extends TransformOptions {
}
export default class Cypher {
- public static async encrypt(tenantID: string, data: string, useFormerKey = false, cryptoSetting?: CryptoSetting): Promise<string> {
+ public static async encrypt(tenant: Tenant, data: string, useFormerKey = false, cryptoSetting?: CryptoSetting): Promise<string> {
if (!cryptoSetting) {
- cryptoSetting = (await Cypher.getCryptoSettings(tenantID)).crypto;
+ cryptoSetting = (await Cypher.getCryptoSettings(tenant)).crypto;
}
const algo = useFormerKey ? Utils.buildCryptoAlgorithm(cryptoSetting.formerKeyProperties) : Utils.buildCryptoAlgorithm(cryptoSetting.keyProperties);
const iv = crypto.randomBytes(Cypher.getIVLength(algo));
@@ -36,7 +37,7 @@ export default class Cypher {
return iv.toString('hex') + ':' + encryptedData.toString('hex');
}
- public static async decrypt(tenantID: string, data: string, useFormerKey = false, cryptoSetting?: CryptoSetting): Promise<string> {
+ public static async decrypt(tenant: Tenant, data: string, useFormerKey = false, cryptoSetting?: CryptoSetting): Promise<string> {
const [ivStr, encryptedDataStr, authTagStr] = data.split(':');
const iv = Buffer.from(ivStr, 'hex');
const encryptedData = Buffer.from(encryptedDataStr, 'hex');
@@ -45,7 +46,7 @@ export default class Cypher {
authTag = Buffer.from(authTagStr, 'hex');
}
if (!cryptoSetting) {
- cryptoSetting = (await Cypher.getCryptoSettings(tenantID)).crypto;
+ cryptoSetting = (await Cypher.getCryptoSettings(tenant)).crypto;
}
const algo: string | CipherGCMTypes = useFormerKey ? Utils.buildCryptoAlgorithm(cryptoSetting.formerKeyProperties) : Utils.buildCryptoAlgorithm(cryptoSetting.keyProperties);
const key = useFormerKey ? Buffer.from(cryptoSetting.formerKey) : Buffer.from(cryptoSetting.key);
@@ -78,7 +79,7 @@ export default class Cypher {
}
}
- public static async encryptSensitiveDataInJSON(tenantID: string, data: Record<string, any>, useFormerKey = false, cryptoSetting?: CryptoSetting): Promise<void> {
+ public static async encryptSensitiveDataInJSON(tenant: Tenant, data: Record<string, any>, useFormerKey = false, cryptoSetting?: CryptoSetting): Promise<void> {
if (typeof data !== 'object') {
throw new BackendError({
source: Constants.CENTRAL_SERVER,
@@ -96,13 +97,13 @@ export default class Cypher {
const value = _.get(data, property);
// If the value is undefined, null or empty then do nothing and skip to the next property
if (value && value.length > 0) {
- _.set(data, property, await Cypher.encrypt(tenantID, value, useFormerKey, cryptoSetting));
+ _.set(data, property, await Cypher.encrypt(tenant, value, useFormerKey, cryptoSetting));
}
}
}
}
- public static async decryptSensitiveDataInJSON(tenantID: string, data: Record<string, any>, useFormerKey = false, cryptoSetting?: CryptoSetting): Promise<void> {
+ public static async decryptSensitiveDataInJSON(tenant: Tenant, data: Record<string, any>, useFormerKey = false, cryptoSetting?: CryptoSetting): Promise<void> {
if (typeof data !== 'object') {
throw new BackendError({
source: Constants.CENTRAL_SERVER,
@@ -118,7 +119,7 @@ export default class Cypher {
const value = _.get(data, property);
// If the value is undefined, null or empty then do nothing and skip to the next property
if (value && value.length > 0) {
- _.set(data, property, await Cypher.decrypt(tenantID, value, useFormerKey, cryptoSetting));
+ _.set(data, property, await Cypher.decrypt(tenant, value, useFormerKey, cryptoSetting));
}
}
}
@@ -158,25 +159,25 @@ export default class Cypher {
}
// This method will be reused in a Scheduler task that resumes migration
- public static async handleCryptoSettingsChange(tenantID: string): Promise<void> {
- const createDatabaseLock = LockingManager.createExclusiveLock(tenantID, LockEntity.DATABASE, 'migrate-settings-sensitive-data');
+ public static async handleCryptoSettingsChange(tenant: Tenant): Promise<void> {
+ const createDatabaseLock = LockingManager.createExclusiveLock(tenant.id, LockEntity.DATABASE, 'migrate-settings-sensitive-data');
if (await LockingManager.acquire(createDatabaseLock)) {
try {
// Get the crypto key
- const cryptoSettings = await Cypher.getCryptoSettings(tenantID);
+ const cryptoSettings = await Cypher.getCryptoSettings(tenant);
// Migrate Settings
- await Cypher.migrateSettings(tenantID, cryptoSettings.crypto);
+ await Cypher.migrateSettings(tenant, cryptoSettings.crypto);
// Cleanup
- await Cypher.cleanupBackupSensitiveData(tenantID);
+ await Cypher.cleanupBackupSensitiveData(tenant);
// Flag the migration as done
cryptoSettings.crypto.migrationToBeDone = false;
- await Cypher.saveCryptoSetting(tenantID, cryptoSettings);
+ await Cypher.saveCryptoSetting(tenant, cryptoSettings);
} catch (err) {
throw new BackendError({
source: Constants.CENTRAL_SERVER,
module: MODULE_NAME,
method: 'handleCryptoSettingsChange',
- message: `Sensitive Data migration for tenant with ID: ${tenantID} failed.`
+ message: `Sensitive Data migration for tenant with ID: ${tenant.id} failed.`
});
} finally {
// Release the database Lock
@@ -187,12 +188,12 @@ export default class Cypher {
source: Constants.CENTRAL_SERVER,
module: MODULE_NAME,
method: 'handleCryptoSettingsChange',
- message: `Sensitive Data migration is in progress for tenant with ID: ${tenantID}.`
+ message: `Sensitive Data migration is in progress for tenant with ID: ${tenant.id}.`
});
}
}
- public static async saveCryptoSetting(tenantID: string, cryptoSettingToSave: CryptoSettings): Promise<void> {
+ public static async saveCryptoSetting(tenant: Tenant, cryptoSettingToSave: CryptoSettings): Promise<void> {
// Build internal structure
const settingsToSave = {
id: cryptoSettingToSave.id,
@@ -203,25 +204,25 @@ export default class Cypher {
},
} as SettingDB;
// Save
- await SettingStorage.saveSettings(tenantID, settingsToSave);
+ await SettingStorage.saveSettings(tenant, settingsToSave);
}
- private static async getCryptoSettings(tenantID: string): Promise<CryptoSettings> {
- const cryptoSettings = await SettingStorage.getCryptoSettings(tenantID);
+ private static async getCryptoSettings(tenant: Tenant): Promise<CryptoSettings> {
+ const cryptoSettings = await SettingStorage.getCryptoSettings(tenant);
if (!cryptoSettings || !cryptoSettings.crypto) {
throw new BackendError({
source: Constants.CENTRAL_SERVER,
module: MODULE_NAME,
method: 'getCryptoSetting',
- message: `Tenant ID '${tenantID}' does not have crypto settings.`
+ message: `Tenant ID '${tenant.id}' does not have crypto settings.`
});
}
return cryptoSettings;
}
- private static async getSettingsWithSensitiveData(tenantID: string): Promise<SettingDB[]> {
+ private static async getSettingsWithSensitiveData(tenant: Tenant): Promise<SettingDB[]> {
// Get all settings per tenant
- const settings = await SettingStorage.getSettings(tenantID, {},
+ const settings = await SettingStorage.getSettings(tenant, {},
Constants.DB_PARAMS_MAX_LIMIT);
// Filter settings with sensitiveData
return settings.result.filter((value: SettingDB) => {
@@ -231,8 +232,8 @@ export default class Cypher {
});
}
- private static async migrateSettings(tenantID: string, cryptoSetting: CryptoSetting): Promise<void> {
- const settingsToMigrate = await Cypher.getSettingsWithSensitiveData(tenantID);
+ private static async migrateSettings(tenant: Tenant, cryptoSetting: CryptoSetting): Promise<void> {
+ const settingsToMigrate = await Cypher.getSettingsWithSensitiveData(tenant);
// If tenant has settings with sensitive data, migrate them
if (!Utils.isEmptyArray(settingsToMigrate)) {
// Migrate
@@ -242,11 +243,11 @@ export default class Cypher {
// Save former sensitive data in setting
settingToMigrate.backupSensitiveData = Cypher.prepareBackupSensitiveData(settingToMigrate);
// Decrypt sensitive data with former key and key properties
- await Cypher.decryptSensitiveDataInJSON(tenantID, settingToMigrate, true, cryptoSetting);
+ await Cypher.decryptSensitiveDataInJSON(tenant, settingToMigrate, true, cryptoSetting);
// Encrypt sensitive data with new key and key properties
- await Cypher.encryptSensitiveDataInJSON(tenantID, settingToMigrate, false, cryptoSetting);
+ await Cypher.encryptSensitiveDataInJSON(tenant, settingToMigrate, false, cryptoSetting);
// Save setting with sensitive data encrypted with new key
- await SettingStorage.saveSettings(tenantID, settingToMigrate);
+ await SettingStorage.saveSettings(tenant, settingToMigrate);
}
}
}
@@ -290,16 +291,16 @@ export default class Cypher {
return {};
}
- private static async cleanupBackupSensitiveData(tenantID: string): Promise<void> {
+ private static async cleanupBackupSensitiveData(tenant: Tenant): Promise<void> {
// Cleanup former encrypted data
- const settingsToCleanup = await Cypher.getSettingsWithSensitiveData(tenantID);
+ const settingsToCleanup = await Cypher.getSettingsWithSensitiveData(tenant);
// If tenant has settings with sensitive data, clean them
if (!Utils.isEmptyArray(settingsToCleanup)) {
// Cleanup
for (const setting of settingsToCleanup) {
if (Utils.objectHasProperty(setting, 'backupSensitiveData')) {
delete setting.backupSensitiveData;
- await SettingStorage.saveSettings(tenantID, setting);
+ await SettingStorage.saveSettings(tenant, setting);
}
}
}

Changing tenant id to object setting storage