@mbc-cqrs-serverless/tenant
Version:
Multiple tenant management
237 lines • 9.89 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var TenantService_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TenantService = void 0;
const core_1 = require("@mbc-cqrs-serverless/core");
const common_1 = require("@nestjs/common");
const common_2 = require("@nestjs/common");
const tenant_constant_1 = require("../constants/tenant.constant");
const setting_enum_1 = require("../enums/setting.enum");
let TenantService = TenantService_1 = class TenantService {
constructor(commandService, dataService) {
this.commandService = commandService;
this.dataService = dataService;
this.logger = new common_2.Logger(TenantService_1.name);
}
async getTenant(key) {
return await this.dataService.getItem(key);
}
async createCommonTenant(dto, context) {
const { name, attributes } = dto;
const pk = `${tenant_constant_1.TENANT_SYSTEM_PREFIX}${core_1.KEY_SEPARATOR}${setting_enum_1.SettingTypeEnum.TENANT_COMMON}`;
const sk = tenant_constant_1.TENANT_SK;
const tenant = await this.dataService.getItem({
pk,
sk,
});
if (tenant && tenant.isDeleted === false) {
throw new common_1.BadRequestException(`Tenant already exists: ${setting_enum_1.SettingTypeEnum.TENANT_COMMON}`);
}
const command = {
pk: pk,
sk: sk,
code: sk,
id: (0, core_1.generateId)(pk, sk),
name: name,
tenantCode: setting_enum_1.SettingTypeEnum.TENANT_COMMON,
type: setting_enum_1.SettingTypeEnum.TENANT_COMMON,
version: tenant?.version ?? core_1.VERSION_FIRST,
attributes: attributes,
};
return await this.commandService.publishAsync(command, context);
}
async createTenant(dto, context) {
const { name, code, attributes } = dto;
const pk = `${tenant_constant_1.TENANT_SYSTEM_PREFIX}${core_1.KEY_SEPARATOR}${code}`;
const sk = tenant_constant_1.TENANT_SK;
const tenant = await this.dataService.getItem({
pk,
sk,
});
if (tenant && tenant.isDeleted === false) {
throw new common_1.BadRequestException(`Tenant already exists: ${setting_enum_1.SettingTypeEnum.TENANT_COMMON}`);
}
const command = {
pk: pk,
sk: sk,
code: sk,
id: (0, core_1.generateId)(pk, sk),
name: name,
tenantCode: code,
type: code,
version: tenant?.version ?? core_1.VERSION_FIRST,
attributes: attributes,
isDeleted: false,
};
return await this.commandService.publishAsync(command, context);
}
async updateTenant(key, dto, context) {
const { pk, sk } = key;
const data = await this.dataService.getItem(key);
if (!data) {
throw new common_1.BadRequestException(`Tenant not found for update: ${JSON.stringify(key)}`);
}
const item = await this.commandService.publishPartialUpdateAsync({
pk,
sk,
name: dto.name,
attributes: {
...data.attributes,
...dto.attributes,
},
version: data.version,
}, context);
return item;
}
async deleteTenant(key, context) {
const data = await this.dataService.getItem(key);
if (!data) {
throw new common_1.BadRequestException(`Tenant not found for delete: ${JSON.stringify(key)}`);
}
const { pk, sk } = key;
const item = await this.commandService.publishPartialUpdateAsync({
pk,
sk,
version: data.version,
isDeleted: true,
}, context);
return item;
}
async addTenantGroup(dto, context) {
const { role, groupId, tenantCode } = dto;
const tenant = await this.dataService.getItem({
pk: `${tenant_constant_1.TENANT_SYSTEM_PREFIX}${core_1.KEY_SEPARATOR}${tenantCode}`,
sk: tenant_constant_1.TENANT_SK,
});
if (!tenant) {
this.logger.error(`Tenant not found for addGroup: ${tenantCode}`);
throw new common_1.BadRequestException('Tenant not found');
}
// Helper to create a new attribute
const createNewAttribute = () => ({
tenantRole: role,
groups: [groupId],
setting_groups: [groupId],
setting_groups_mode: 'auto',
});
// Helper to update an existing attribute
const updateAttribute = (item) => {
if (item.groups.includes(groupId))
return item;
const newGroups = [...item.groups, groupId];
const newSettingGroups = item.setting_groups_mode === 'customized'
? [...item.setting_groups, groupId]
: this.sortGroups(newGroups);
return {
...item,
groups: newGroups,
setting_groups: newSettingGroups,
setting_groups_mode: item.setting_groups_mode || 'auto',
};
};
// If tenant exists and has attributes
if (Array.isArray(tenant?.attributes?.setting) &&
tenant.attributes.setting.length > 0) {
const existingRole = tenant.attributes.setting.find((i) => i.tenantRole === role);
const updatedAttributes = existingRole
? tenant.attributes.setting.map((item) => item.tenantRole === role ? updateAttribute(item) : item)
: [...tenant.attributes.setting, createNewAttribute()];
return await this.commandService.publishPartialUpdateAsync({
pk: tenant.pk,
sk: tenant.sk,
version: tenant.version,
attributes: {
setting: updatedAttributes,
},
}, context);
}
// If tenant does not exist or has no attributes
return await this.commandService.publishPartialUpdateAsync({
pk: tenant.pk,
sk: tenant.sk,
version: tenant.version,
attributes: {
setting: [createNewAttribute()],
},
}, context);
}
async customizeSettingGroups(dto, context) {
const { role, settingGroups, tenantCode } = dto;
const tenant = await this.dataService.getItem({
pk: `${tenant_constant_1.TENANT_SYSTEM_PREFIX}${core_1.KEY_SEPARATOR}${tenantCode}`,
sk: tenant_constant_1.TENANT_SK,
});
if (!tenant) {
this.logger.error(`Tenant not found for customizeSettingGroups: ${tenantCode}`);
throw new common_1.BadRequestException(`Tenant not found for key: ${JSON.stringify(tenantCode)}`);
}
const settings = tenant.attributes?.setting || [];
const updatedSettings = settings.map((item) => {
if (item.tenantRole !== role)
return item;
return {
...item,
groups: settingGroups,
setting_groups: settingGroups,
setting_groups_mode: 'customized',
};
});
return await this.commandService.publishPartialUpdateAsync({
pk: tenant.pk,
sk: tenant.sk,
version: tenant.version,
attributes: {
...tenant.attributes,
setting: updatedSettings,
},
}, context);
}
sortGroups(groups) {
return groups.sort((a, b) => {
const countA = a.split('#').length - 1;
const countB = b.split('#').length - 1;
return countB !== countA ? countB - countA : a.localeCompare(b);
});
}
async createTenantGroup(tenantGroupCode, dto, context) {
const { name, code, attributes } = dto;
const pk = `${tenant_constant_1.TENANT_SYSTEM_PREFIX}${core_1.KEY_SEPARATOR}${tenantGroupCode}`;
const sk = code;
const tenant = await this.dataService.getItem({
pk,
sk,
});
if (tenant && tenant.isDeleted === false) {
throw new common_1.BadRequestException(`Tenant already exists: ${setting_enum_1.SettingTypeEnum.TENANT} - sk: ${sk}`);
}
const command = {
pk: pk,
sk: sk,
id: (0, core_1.generateId)(pk, sk),
tenantCode: tenantGroupCode,
code: code,
type: setting_enum_1.SettingTypeEnum.TENANT,
name: name,
version: tenant?.version ?? core_1.VERSION_FIRST,
attributes: attributes,
isDeleted: false,
};
return await this.commandService.publishAsync(command, context);
}
};
exports.TenantService = TenantService;
exports.TenantService = TenantService = TenantService_1 = __decorate([
(0, common_2.Injectable)(),
__metadata("design:paramtypes", [core_1.CommandService,
core_1.DataService])
], TenantService);
//# sourceMappingURL=tenant.service.js.map