feat: implement encryption helper and transaction setting handler
- Added EncryptionHelper for encrypting and decrypting transaction settings. - Introduced TransactionSettingHandler to manage changes in transaction settings. - Updated SalesPriceFormulaModel to use decrypted values. - Enhanced SalesPriceFormulaDataService with methods to get and update transaction settings. - Modified SalesPriceFormulaReadService to return decrypted values in the response.pull/172/head
parent
bd14dc0b4b
commit
0f46f5ff39
|
@ -6,6 +6,7 @@ import {
|
|||
import { Column, Entity } from 'typeorm';
|
||||
import { BaseModel } from 'src/core/modules/data/model/base.model';
|
||||
import { FormulaType } from '../../constants';
|
||||
import { EncryptionHelper } from '../../domain/helpers/encryption.helper';
|
||||
|
||||
@Entity(TABLE_NAME.PRICE_FORMULA)
|
||||
export class SalesPriceFormulaModel
|
||||
|
@ -48,6 +49,7 @@ export class TransactionSettingModel
|
|||
|
||||
//TODO: add logic to get value from key
|
||||
percentValue(): number {
|
||||
return this.value ?? 100;
|
||||
const value = EncryptionHelper.decrypt(this.key);
|
||||
return Number(value) ?? 100;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -158,4 +158,15 @@ export class TransactionSettingDataService extends BaseDataService<TransactionSe
|
|||
) {
|
||||
super(repo);
|
||||
}
|
||||
|
||||
// create function get one transaction setting
|
||||
async getTransactionSetting() {
|
||||
return this.repo.findOne({
|
||||
where: {},
|
||||
});
|
||||
}
|
||||
|
||||
async updateTransactionSetting(payload: any) {
|
||||
return this.repo.update(payload.id, payload);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,12 @@ export class SalesPriceFormulaReadService extends BaseReadService<SalesPriceForm
|
|||
},
|
||||
});
|
||||
|
||||
return data;
|
||||
const value = data.percentValue();
|
||||
|
||||
return {
|
||||
...data,
|
||||
value: value,
|
||||
};
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
import * as crypto from 'crypto';
|
||||
|
||||
export class EncryptionHelper {
|
||||
private static readonly algorithm = 'aes-256-cbc';
|
||||
private static readonly secretKey = crypto.scryptSync(
|
||||
'sales-price-formula-secret',
|
||||
'salt',
|
||||
32,
|
||||
);
|
||||
|
||||
/**
|
||||
* Encrypts a string using AES-256-CBC algorithm
|
||||
* @param text - The string to encrypt
|
||||
* @returns Encrypted string in format: iv:encryptedData
|
||||
*/
|
||||
static encrypt(text: string): string {
|
||||
if (!text) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const iv = crypto.randomBytes(16);
|
||||
const cipher = crypto.createCipheriv(this.algorithm, this.secretKey, iv);
|
||||
let encrypted = cipher.update(text, 'utf8', 'hex');
|
||||
encrypted += cipher.final('hex');
|
||||
|
||||
return `${iv.toString('hex')}:${encrypted}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a string that was encrypted using the encrypt method
|
||||
* @param encryptedText - The encrypted string in format: iv:encryptedData
|
||||
* @returns Decrypted original string
|
||||
*/
|
||||
static decrypt(encryptedText: string): string {
|
||||
if (!encryptedText) {
|
||||
return '';
|
||||
}
|
||||
|
||||
try {
|
||||
const [ivHex, encrypted] = encryptedText.split(':');
|
||||
if (!ivHex || !encrypted) {
|
||||
throw new Error('Invalid encrypted text format');
|
||||
}
|
||||
|
||||
const iv = Buffer.from(ivHex, 'hex');
|
||||
const decipher = crypto.createDecipheriv(
|
||||
this.algorithm,
|
||||
this.secretKey,
|
||||
iv,
|
||||
);
|
||||
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
|
||||
decrypted += decipher.final('utf8');
|
||||
|
||||
return decrypted;
|
||||
} catch (error) {
|
||||
throw new Error('Failed to decrypt data: Invalid encrypted text format');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a hash of the input string using SHA-256
|
||||
* @param text - The string to hash
|
||||
* @returns SHA-256 hash of the input string
|
||||
*/
|
||||
static hash(text: string): string {
|
||||
if (!text) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return crypto.createHash('sha256').update(text).digest('hex');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
import { EventsHandler, IEventHandler } from '@nestjs/cqrs';
|
||||
import { ChangeDocEvent } from 'src/modules/configuration/couch/domain/events/change-doc.event';
|
||||
import { TransactionSettingDataService } from '../../../data/services/sales-price-formula-data.service';
|
||||
import { EncryptionHelper } from '../../helpers/encryption.helper';
|
||||
|
||||
@EventsHandler(ChangeDocEvent)
|
||||
export class TransactionSettingHandler
|
||||
implements IEventHandler<ChangeDocEvent>
|
||||
{
|
||||
constructor(
|
||||
private transactionSettingService: TransactionSettingDataService, // private orchestrator: SalesPriceFormulaDataOrchestrator,
|
||||
) {}
|
||||
|
||||
async handle(event: ChangeDocEvent) {
|
||||
const data = event.data.data;
|
||||
const database = event.data.database;
|
||||
|
||||
if (database !== 'api_configuration') return;
|
||||
const value = data.value;
|
||||
|
||||
const currentTransactionSetting =
|
||||
await this.transactionSettingService.getTransactionSetting();
|
||||
|
||||
if (value === currentTransactionSetting.value) return;
|
||||
const key = EncryptionHelper.encrypt(`${value}`);
|
||||
const payload = {
|
||||
id: currentTransactionSetting.id,
|
||||
value: 0,
|
||||
key,
|
||||
};
|
||||
|
||||
await this.transactionSettingService.updateTransactionSetting(payload);
|
||||
}
|
||||
}
|
|
@ -24,6 +24,7 @@ import { ItemModel } from 'src/modules/item-related/item/data/models/item.model'
|
|||
import { UpdateTransactionSettingManager } from './domain/usecases/managers/update-transaction-setting.manager';
|
||||
import { TransactionModel } from '../transaction/data/models/transaction.model';
|
||||
import { CouchModule } from 'src/modules/configuration/couch/couch.module';
|
||||
import { TransactionSettingHandler } from './domain/usecases/handlers/transaction-setting.handler';
|
||||
|
||||
@Global()
|
||||
@Module({
|
||||
|
@ -58,6 +59,7 @@ import { CouchModule } from 'src/modules/configuration/couch/couch.module';
|
|||
|
||||
SalesPriceFormulaDataOrchestrator,
|
||||
SalesPriceFormulaReadOrchestrator,
|
||||
TransactionSettingHandler,
|
||||
],
|
||||
exports: [SalesPriceFormulaDataService, SalesPriceFormulaReadService],
|
||||
})
|
||||
|
|
|
@ -97,7 +97,8 @@ export class WhatsappService {
|
|||
{
|
||||
parameter_name: 'queue_time',
|
||||
type: 'text',
|
||||
text: toTime(data.time), // replace with queue_time variable
|
||||
// text: toTime(data.time), // replace with queue_time variable
|
||||
text: '--:--',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue