From c067e370eee5276c734ca296fb21b7315dce390b Mon Sep 17 00:00:00 2001 From: Artem Niehrieiev Date: Thu, 13 Feb 2025 13:35:40 +0000 Subject: [PATCH] Add default_showing_table property to connection properties entity and related DTOs, controllers, and validation logic --- .../create-connection-properties.ds.ts | 1 + .../found-connection-properties.ds.ts | 3 +++ .../connection-properties.controller.ts | 6 +++-- .../connection-properties.entity.ts | 3 +++ .../dto/create-connection-properties.dto.ts | 26 ++++++++++++------- .../build-connection-properties-entity.ts | 1 + .../build-found-connection-properties-ds.ts | 1 + ...ild-update-connection-properties-object.ts | 3 +++ ...alidate-create-connection-properties-ds.ts | 6 ++++- ...wingTalbeIntoConnectionPropertiesEntity.ts | 13 ++++++++++ ...er-with-table-only-permissions-e2e.test.ts | 2 +- .../connection-properties-e2e.test.ts | 1 + backend/test/mock.factory.ts | 1 + 13 files changed, 53 insertions(+), 14 deletions(-) create mode 100644 backend/src/migrations/1739448612299-AddDefaultShowingTalbeIntoConnectionPropertiesEntity.ts diff --git a/backend/src/entities/connection-properties/application/data-structures/create-connection-properties.ds.ts b/backend/src/entities/connection-properties/application/data-structures/create-connection-properties.ds.ts index 7fa8f6e4d..3afce3205 100644 --- a/backend/src/entities/connection-properties/application/data-structures/create-connection-properties.ds.ts +++ b/backend/src/entities/connection-properties/application/data-structures/create-connection-properties.ds.ts @@ -11,4 +11,5 @@ export class CreateConnectionPropertiesDs { tables_audit: boolean; human_readable_table_names: boolean; allow_ai_requests: boolean; + default_showing_table: string; } diff --git a/backend/src/entities/connection-properties/application/data-structures/found-connection-properties.ds.ts b/backend/src/entities/connection-properties/application/data-structures/found-connection-properties.ds.ts index ad92863ef..f0f0d4665 100644 --- a/backend/src/entities/connection-properties/application/data-structures/found-connection-properties.ds.ts +++ b/backend/src/entities/connection-properties/application/data-structures/found-connection-properties.ds.ts @@ -33,4 +33,7 @@ export class FoundConnectionPropertiesDs { @ApiProperty() allow_ai_requests: boolean; + + @ApiProperty() + default_showing_table: string; } diff --git a/backend/src/entities/connection-properties/connection-properties.controller.ts b/backend/src/entities/connection-properties/connection-properties.controller.ts index ffe6dfa39..e06d4e69e 100644 --- a/backend/src/entities/connection-properties/connection-properties.controller.ts +++ b/backend/src/entities/connection-properties/connection-properties.controller.ts @@ -12,6 +12,7 @@ import { UseInterceptors, } from '@nestjs/common'; import { HttpException } from '@nestjs/common/exceptions/http.exception.js'; +import { ApiBearerAuth, ApiBody, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger'; import { UseCaseType } from '../../common/data-injection.tokens.js'; import { MasterPassword, SlugUuid, UserId } from '../../decorators/index.js'; import { InTransactionEnum } from '../../enums/index.js'; @@ -21,14 +22,13 @@ import { SentryInterceptor } from '../../interceptors/index.js'; import { CreateConnectionPropertiesDs } from './application/data-structures/create-connection-properties.ds.js'; import { FoundConnectionPropertiesDs } from './application/data-structures/found-connection-properties.ds.js'; import { IConnectionPropertiesRO } from './connection-properties.interface.js'; +import { CreateConnectionPropertiesDto } from './dto/create-connection-properties.dto.js'; import { ICreateConnectionProperties, IDeleteConnectionProperties, IFindConnectionProperties, IUpdateConnectionProperties, } from './use-cases/connection-properties-use.cases.interface.js'; -import { ApiBearerAuth, ApiBody, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger'; -import { CreateConnectionPropertiesDto } from './dto/create-connection-properties.dto.js'; @UseInterceptors(SentryInterceptor) @Controller() @@ -107,6 +107,7 @@ export class ConnectionPropertiesController { tables_audit: connectionPropertiesData.tables_audit, human_readable_table_names: connectionPropertiesData.human_readable_table_names, allow_ai_requests: connectionPropertiesData.allow_ai_requests, + default_showing_table: connectionPropertiesData.default_showing_table, }; return await this.createConnectionPropertiesUseCase.execute(createConnectionPropertiesDs, InTransactionEnum.ON); @@ -151,6 +152,7 @@ export class ConnectionPropertiesController { tables_audit: connectionPropertiesData.tables_audit, human_readable_table_names: connectionPropertiesData.human_readable_table_names, allow_ai_requests: connectionPropertiesData.allow_ai_requests, + default_showing_table: connectionPropertiesData.default_showing_table, }; return await this.updateConnectionPropertiesUseCase.execute(inputData, InTransactionEnum.ON); diff --git a/backend/src/entities/connection-properties/connection-properties.entity.ts b/backend/src/entities/connection-properties/connection-properties.entity.ts index 894fb3b94..085714472 100644 --- a/backend/src/entities/connection-properties/connection-properties.entity.ts +++ b/backend/src/entities/connection-properties/connection-properties.entity.ts @@ -33,6 +33,9 @@ export class ConnectionPropertiesEntity { @Column({ default: true }) allow_ai_requests: boolean; + @Column({ default: null }) + default_showing_table: string; + @OneToOne((_) => ConnectionEntity, (connection) => connection.connection_properties, { onDelete: 'CASCADE', }) diff --git a/backend/src/entities/connection-properties/dto/create-connection-properties.dto.ts b/backend/src/entities/connection-properties/dto/create-connection-properties.dto.ts index a7563892c..f5f1e9839 100644 --- a/backend/src/entities/connection-properties/dto/create-connection-properties.dto.ts +++ b/backend/src/entities/connection-properties/dto/create-connection-properties.dto.ts @@ -1,49 +1,55 @@ import { ApiProperty } from '@nestjs/swagger'; -import { IsArray, IsBoolean, IsOptional, IsString } from 'class-validator'; +import { IsArray, IsBoolean, IsOptional, IsString, MaxLength } from 'class-validator'; export class CreateConnectionPropertiesDto { @IsOptional() @IsArray() - @ApiProperty({ isArray: true, type: String }) + @ApiProperty({ isArray: true, type: String, required: false }) hidden_tables: Array; @IsOptional() @IsString() - @ApiProperty() + @ApiProperty({ required: false }) logo_url: string; @IsOptional() @IsString() - @ApiProperty() + @ApiProperty({ required: false }) primary_color: string; @IsOptional() @IsString() - @ApiProperty() + @ApiProperty({ required: false }) secondary_color: string; @IsOptional() @IsString() - @ApiProperty() + @ApiProperty({ required: false }) hostname: string; @IsOptional() @IsString() - @ApiProperty() + @ApiProperty({ required: false }) company_name: string; @IsOptional() @IsBoolean() - @ApiProperty() + @ApiProperty({ required: false }) tables_audit: boolean; @IsOptional() @IsBoolean() - @ApiProperty() + @ApiProperty({ required: false }) human_readable_table_names: boolean; @IsOptional() @IsBoolean() - @ApiProperty() + @ApiProperty({ required: false }) allow_ai_requests: boolean; + + @IsOptional() + @IsString() + @MaxLength(255) + @ApiProperty({ required: false }) + default_showing_table: string; } diff --git a/backend/src/entities/connection-properties/utils/build-connection-properties-entity.ts b/backend/src/entities/connection-properties/utils/build-connection-properties-entity.ts index f27ef9820..2e0b4ed93 100644 --- a/backend/src/entities/connection-properties/utils/build-connection-properties-entity.ts +++ b/backend/src/entities/connection-properties/utils/build-connection-properties-entity.ts @@ -18,5 +18,6 @@ export function buildConnectionPropertiesEntity( newConnectionProperties.tables_audit = propertiesInfo.tables_audit; newConnectionProperties.human_readable_table_names = propertiesInfo.human_readable_table_names; newConnectionProperties.allow_ai_requests = propertiesInfo.allow_ai_requests; + newConnectionProperties.default_showing_table = propertiesInfo.default_showing_table; return newConnectionProperties; } diff --git a/backend/src/entities/connection-properties/utils/build-found-connection-properties-ds.ts b/backend/src/entities/connection-properties/utils/build-found-connection-properties-ds.ts index ed2083391..53964965c 100644 --- a/backend/src/entities/connection-properties/utils/build-found-connection-properties-ds.ts +++ b/backend/src/entities/connection-properties/utils/build-found-connection-properties-ds.ts @@ -16,5 +16,6 @@ export function buildFoundConnectionPropertiesDs( tables_audit: connectionProperties.tables_audit, human_readable_table_names: connectionProperties.human_readable_table_names, allow_ai_requests: connectionProperties.allow_ai_requests, + default_showing_table: connectionProperties.default_showing_table, }; } diff --git a/backend/src/entities/connection-properties/utils/build-update-connection-properties-object.ts b/backend/src/entities/connection-properties/utils/build-update-connection-properties-object.ts index 79f685a85..071de698e 100644 --- a/backend/src/entities/connection-properties/utils/build-update-connection-properties-object.ts +++ b/backend/src/entities/connection-properties/utils/build-update-connection-properties-object.ts @@ -13,6 +13,7 @@ export function buildUpdateConnectionPropertiesObject( tables_audit, human_readable_table_names, allow_ai_requests, + default_showing_table, } = inputData; return { hidden_tables: hidden_tables, @@ -24,6 +25,7 @@ export function buildUpdateConnectionPropertiesObject( tables_audit: tables_audit, human_readable_table_names: human_readable_table_names, allow_ai_requests: allow_ai_requests, + default_showing_table: default_showing_table, }; } @@ -37,4 +39,5 @@ export interface IUpdateConnectionPropertiesObject { tables_audit: boolean; human_readable_table_names: boolean; allow_ai_requests: boolean; + default_showing_table: string; } diff --git a/backend/src/entities/connection-properties/utils/validate-create-connection-properties-ds.ts b/backend/src/entities/connection-properties/utils/validate-create-connection-properties-ds.ts index ead9a00b5..4705997e6 100644 --- a/backend/src/entities/connection-properties/utils/validate-create-connection-properties-ds.ts +++ b/backend/src/entities/connection-properties/utils/validate-create-connection-properties-ds.ts @@ -10,7 +10,7 @@ export async function validateCreateConnectionPropertiesDs( createConnectionProperties: CreateConnectionPropertiesDs, connection: ConnectionEntity, ): Promise { - const { hidden_tables } = createConnectionProperties; + const { hidden_tables, default_showing_table } = createConnectionProperties; const errors = []; const dao = getDataAccessObject(connection); const tablesInConnection = (await dao.getTablesFromDB()).map((table) => table.tableName); @@ -25,6 +25,10 @@ export async function validateCreateConnectionPropertiesDs( } } + if (default_showing_table && !tablesInConnection.includes(default_showing_table)) { + errors.push(Messages.TABLE_WITH_NAME_NOT_EXISTS(default_showing_table)); + } + if (errors.length > 0) { throw new HttpException( { diff --git a/backend/src/migrations/1739448612299-AddDefaultShowingTalbeIntoConnectionPropertiesEntity.ts b/backend/src/migrations/1739448612299-AddDefaultShowingTalbeIntoConnectionPropertiesEntity.ts new file mode 100644 index 000000000..d0417631b --- /dev/null +++ b/backend/src/migrations/1739448612299-AddDefaultShowingTalbeIntoConnectionPropertiesEntity.ts @@ -0,0 +1,13 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddDefaultShowingTalbeIntoConnectionPropertiesEntity1739448612299 implements MigrationInterface { + name = 'AddDefaultShowingTalbeIntoConnectionPropertiesEntity1739448612299'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "connectionProperties" ADD "default_showing_table" character varying`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "connectionProperties" DROP COLUMN "default_showing_table"`); + } +} diff --git a/backend/test/ava-tests/non-saas-tests/non-saas-user-with-table-only-permissions-e2e.test.ts b/backend/test/ava-tests/non-saas-tests/non-saas-user-with-table-only-permissions-e2e.test.ts index e31255b80..1a6bfea62 100644 --- a/backend/test/ava-tests/non-saas-tests/non-saas-user-with-table-only-permissions-e2e.test.ts +++ b/backend/test/ava-tests/non-saas-tests/non-saas-user-with-table-only-permissions-e2e.test.ts @@ -2138,7 +2138,7 @@ test.serial( t.is(updateConnectionResponse.status, 200); - const newConnectionProperties = mockFactory.generateConnectionPropertiesUserExcluded(null, false); + const newConnectionProperties = mockFactory.generateConnectionPropertiesUserExcluded(firstTableInfo.testTableName, false); newConnectionProperties.hidden_tables = []; newConnectionProperties.tables_audit = false; diff --git a/backend/test/ava-tests/saas-tests/connection-properties-e2e.test.ts b/backend/test/ava-tests/saas-tests/connection-properties-e2e.test.ts index c481b93dc..d2dcb4c23 100644 --- a/backend/test/ava-tests/saas-tests/connection-properties-e2e.test.ts +++ b/backend/test/ava-tests/saas-tests/connection-properties-e2e.test.ts @@ -139,6 +139,7 @@ test.serial(`${currentTest} should return created connection properties`, async t.is(createConnectionPropertiesRO.hidden_tables[0], newConnectionProperties.hidden_tables[0]); t.is(createConnectionPropertiesRO.connectionId, createConnectionRO.id); t.is(createConnectionPropertiesRO.allow_ai_requests, newConnectionProperties.allow_ai_requests); + t.is(createConnectionPropertiesRO.default_showing_table, newConnectionProperties.default_showing_table); } catch (e) { throw e; } diff --git a/backend/test/mock.factory.ts b/backend/test/mock.factory.ts index 8ac7b30ff..a22089c44 100644 --- a/backend/test/mock.factory.ts +++ b/backend/test/mock.factory.ts @@ -822,6 +822,7 @@ export class MockFactory { tables_audit: tables_audit, human_readable_table_names: faker.datatype.boolean(), allow_ai_requests: faker.datatype.boolean(), + default_showing_table: tableName, }; }