From 75f23ccd2254ab09c11fc2f83b028c99ecb56776 Mon Sep 17 00:00:00 2001 From: Artem Niehrieiev Date: Mon, 17 Feb 2025 14:11:01 +0000 Subject: [PATCH] Enhance update-row use case by adding object empty checks and integrating binary data conversion --- .../use-cases/update-row-in-table.use.case.ts | 38 ++++++++++++------- .../data-access-object-dynamodb.ts | 10 +++++ 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/backend/src/entities/table/use-cases/update-row-in-table.use.case.ts b/backend/src/entities/table/use-cases/update-row-in-table.use.case.ts index 9739b5fee..5ef933ddb 100644 --- a/backend/src/entities/table/use-cases/update-row-in-table.use.case.ts +++ b/backend/src/entities/table/use-cases/update-row-in-table.use.case.ts @@ -1,37 +1,43 @@ /* eslint-disable prefer-const */ import { HttpException, HttpStatus, Inject, Injectable } from '@nestjs/common'; +import { getDataAccessObject } from '@rocketadmin/shared-code/dist/src/data-access-layer/shared/create-data-access-object.js'; +import { ForeignKeyWithAutocompleteColumnsDS } from '@rocketadmin/shared-code/dist/src/data-access-layer/shared/data-structures/foreign-key-with-autocomplete-columns.ds.js'; +import { ForeignKeyDS } from '@rocketadmin/shared-code/dist/src/data-access-layer/shared/data-structures/foreign-key.ds.js'; +import { ReferencedTableNamesAndColumnsDS } from '@rocketadmin/shared-code/dist/src/data-access-layer/shared/data-structures/referenced-table-names-columns.ds.js'; +import { IDataAccessObjectAgent } from '@rocketadmin/shared-code/dist/src/data-access-layer/shared/interfaces/data-access-object-agent.interface.js'; +import { IDataAccessObject } from '@rocketadmin/shared-code/dist/src/data-access-layer/shared/interfaces/data-access-object.interface.js'; +import JSON5 from 'json5'; import AbstractUseCase from '../../../common/abstract-use.case.js'; import { IGlobalDatabaseContext } from '../../../common/application/global-database-context.interface.js'; import { BaseType } from '../../../common/data-injection.tokens.js'; -import { getDataAccessObject } from '@rocketadmin/shared-code/dist/src/data-access-layer/shared/create-data-access-object.js'; import { AmplitudeEventTypeEnum, LogOperationTypeEnum, OperationResultStatusEnum, WidgetTypeEnum, } from '../../../enums/index.js'; +import { TableActionEventEnum } from '../../../enums/table-action-event-enum.js'; +import { ExceptionOperations } from '../../../exceptions/custom-exceptions/exception-operation.js'; +import { UnknownSQLException } from '../../../exceptions/custom-exceptions/unknown-sql-exception.js'; import { Messages } from '../../../exceptions/text/messages.js'; -import { compareArrayElements, isConnectionTypeAgent, toPrettyErrorsMsg } from '../../../helpers/index.js'; +import { + compareArrayElements, + isConnectionTypeAgent, + isObjectEmpty, + toPrettyErrorsMsg, +} from '../../../helpers/index.js'; import { AmplitudeService } from '../../amplitude/amplitude.service.js'; import { isTestConnectionUtil } from '../../connection/utils/is-test-connection-util.js'; +import { TableActionActivationService } from '../../table-actions/table-actions-module/table-action-activation.service.js'; import { TableLogsService } from '../../table-logs/table-logs.service.js'; import { UpdateRowInTableDs } from '../application/data-structures/update-row-in-table.ds.js'; import { ForeignKeyDSInfo, ReferencedTableNamesAndColumnsDs, TableRowRODs } from '../table-datastructures.js'; +import { convertBinaryDataInRowUtil } from '../utils/convert-binary-data-in-row.util.js'; import { formFullTableStructure } from '../utils/form-full-table-structure.js'; import { hashPasswordsInRowUtil } from '../utils/hash-passwords-in-row.util.js'; import { processUuidsInRowUtil } from '../utils/process-uuids-in-row-util.js'; import { removePasswordsFromRowsUtil } from '../utils/remove-password-from-row.util.js'; import { IUpdateRowInTable } from './table-use-cases.interface.js'; -import { IDataAccessObjectAgent } from '@rocketadmin/shared-code/dist/src/data-access-layer/shared/interfaces/data-access-object-agent.interface.js'; -import { IDataAccessObject } from '@rocketadmin/shared-code/dist/src/data-access-layer/shared/interfaces/data-access-object.interface.js'; -import { ForeignKeyWithAutocompleteColumnsDS } from '@rocketadmin/shared-code/dist/src/data-access-layer/shared/data-structures/foreign-key-with-autocomplete-columns.ds.js'; -import { ForeignKeyDS } from '@rocketadmin/shared-code/dist/src/data-access-layer/shared/data-structures/foreign-key.ds.js'; -import { UnknownSQLException } from '../../../exceptions/custom-exceptions/unknown-sql-exception.js'; -import { ExceptionOperations } from '../../../exceptions/custom-exceptions/exception-operation.js'; -import { ReferencedTableNamesAndColumnsDS } from '@rocketadmin/shared-code/dist/src/data-access-layer/shared/data-structures/referenced-table-names-columns.ds.js'; -import JSON5 from 'json5'; -import { TableActionEventEnum } from '../../../enums/table-action-event-enum.js'; -import { TableActionActivationService } from '../../table-actions/table-actions-module/table-action-activation.service.js'; @Injectable() export class UpdateRowInTableUseCase @@ -49,7 +55,6 @@ export class UpdateRowInTableUseCase } protected async implementation(inputData: UpdateRowInTableDs): Promise { - let { connectionId, masterPwd, primaryKey, row, tableName, userId } = inputData; let operationResult = OperationResultStatusEnum.unknown; @@ -245,10 +250,14 @@ export class UpdateRowInTableUseCase }; const futureRowData = Object.assign(oldRowData, row); - const futurePrimaryKey = {}; + let futurePrimaryKey = {}; for (const primaryColumn of tablePrimaryKeys) { futurePrimaryKey[primaryColumn.column_name] = futureRowData[primaryColumn.column_name]; } + if (isObjectEmpty(futurePrimaryKey)) { + futurePrimaryKey = primaryKey; + } + const formedTableStructure = formFullTableStructure(tableStructure, tableSettings); try { row = await hashPasswordsInRowUtil(row, tableWidgets); @@ -257,6 +266,7 @@ export class UpdateRowInTableUseCase operationResult = OperationResultStatusEnum.successfully; let updatedRow = await dao.getRowByPrimaryKey(tableName, futurePrimaryKey, tableSettings, userEmail); updatedRow = removePasswordsFromRowsUtil(updatedRow, tableWidgets); + updatedRow = convertBinaryDataInRowUtil(updatedRow, tableStructure); return { row: updatedRow, foreignKeys: foreignKeysWithAutocompleteColumns, diff --git a/shared-code/src/data-access-layer/data-access-objects/data-access-object-dynamodb.ts b/shared-code/src/data-access-layer/data-access-objects/data-access-object-dynamodb.ts index 2425e8273..e8994f2ca 100644 --- a/shared-code/src/data-access-layer/data-access-objects/data-access-object-dynamodb.ts +++ b/shared-code/src/data-access-layer/data-access-objects/data-access-object-dynamodb.ts @@ -30,6 +30,7 @@ import { FilterCriteriaEnum } from '../shared/enums/filter-criteria.enum.js'; import { QueryOrderingEnum } from '../shared/enums/query-ordering.enum.js'; import { IDataAccessObject } from '../shared/interfaces/data-access-object.interface.js'; import { BasicDataAccessObject } from './basic-data-access-object.js'; +import { isObjectEmpty } from '../../helpers/is-object-empty.js'; export type DdAndClient = { dynamoDb: DynamoDB; @@ -425,6 +426,10 @@ export class DataAccessObjectDynamoDB extends BasicDataAccessObject implements I primaryKeyColumns.forEach((key) => { responseObject[key.column_name] = row[key.column_name]; }); + + if (isObjectEmpty(responseObject)) { + return primaryKey; + } return responseObject; } catch (e) { e.message += '.'; @@ -633,6 +638,11 @@ export class DataAccessObjectDynamoDB extends BasicDataAccessObject implements I const valuesArray = transformedRow[key]; transformedRow[key] = valuesArray.map((value) => binaryToHex(value)); } + + if (fieldInfo?.dynamo_db_type === 'L') { + const valuesArray = transformedRow[key]; + transformedRow[key] = valuesArray.map((value) => Object.values(value)[0]); + } }); if (availableFields.length > 0) {