diff --git a/wren-ui/src/apollo/server/adaptors/tests/ibisAdaptor.test.ts b/wren-ui/src/apollo/server/adaptors/tests/ibisAdaptor.test.ts index d1a6a8ec4..9f0e8e9a9 100644 --- a/wren-ui/src/apollo/server/adaptors/tests/ibisAdaptor.test.ts +++ b/wren-ui/src/apollo/server/adaptors/tests/ibisAdaptor.test.ts @@ -48,7 +48,7 @@ describe('IbisAdaptor', () => { }; const mockClickHouseConnectionInfo: CLICK_HOUSE_CONNECTION_INFO = { - host: 'localhost', + host: 'my-host', port: 8443, database: 'my-database', user: 'my-user', @@ -129,7 +129,7 @@ describe('IbisAdaptor', () => { expect(result).toEqual([]); expect(mockedAxios.post).toHaveBeenCalledWith( - `${ibisServerEndpoint}/v2/ibis/mssql/metadata/constraints`, + `${ibisServerEndpoint}/v2/connector/mssql/metadata/constraints`, { connectionInfo: expectConnectionInfo }, ); }); @@ -153,11 +153,61 @@ describe('IbisAdaptor', () => { expect(result).toEqual([]); expect(mockedAxios.post).toHaveBeenCalledWith( - `${ibisServerEndpoint}/v2/ibis/mysql/metadata/constraints`, + `${ibisServerEndpoint}/v2/connector/mysql/metadata/constraints`, { connectionInfo: expectConnectionInfo }, ); }); + // check clickhouse connection info + it.each([ + [ + { + host: 'my-host', + port: 8443, + database: 'my-database', + user: 'my-user', + password: 'my-password', + ssl: true, + }, + `clickhouse://my-user:my-password@my-host:8443/my-database?secure=1`, + ], + [ + { + host: 'my-host', + port: 8443, + database: 'my-database', + user: 'my-user', + password: 'my-password', + ssl: false, + }, + `clickhouse://my-user:my-password@my-host:8443/my-database?`, + ], + ])( + 'should get correct clickhouse connection info', + async (connectionInfo, expectConnectionUrl) => { + const mockResponse = { data: [] }; + mockedAxios.post.mockResolvedValue(mockResponse); + // mock decrypt method in Encryptor to return the same password + mockedEncryptor.prototype.decrypt.mockReturnValue( + JSON.stringify({ password: connectionInfo.password }), + ); + + const result = await ibisAdaptor.getConstraints( + DataSourceName.CLICK_HOUSE, + connectionInfo, + ); + const expectConnectionInfo = { + connectionUrl: expectConnectionUrl, + }; + + expect(result).toEqual([]); + expect(mockedAxios.post).toHaveBeenCalledWith( + `${ibisServerEndpoint}/v2/connector/clickhouse/metadata/constraints`, + { connectionInfo: expectConnectionInfo }, + ); + }, + ); + it('should get click house constraints', async () => { const mockResponse = { data: [] }; mockedAxios.post.mockResolvedValue(mockResponse); @@ -170,13 +220,15 @@ describe('IbisAdaptor', () => { DataSourceName.CLICK_HOUSE, mockClickHouseConnectionInfo, ); - const expectConnectionInfo = Object.entries( - mockClickHouseConnectionInfo, - ).reduce((acc, [key, value]) => ((acc[snakeCase(key)] = value), acc), {}); + const { user, password, host, port, database, ssl } = + mockClickHouseConnectionInfo; + const expectConnectionInfo = { + connectionUrl: `clickhouse://${user}:${password}@${host}:${port}/${database}${ssl ? '?secure=1' : ''}`, + }; expect(result).toEqual([]); expect(mockedAxios.post).toHaveBeenCalledWith( - `${ibisServerEndpoint}/v2/ibis/clickhouse/metadata/constraints`, + `${ibisServerEndpoint}/v2/connector/clickhouse/metadata/constraints`, { connectionInfo: expectConnectionInfo }, ); }); @@ -195,7 +247,7 @@ describe('IbisAdaptor', () => { expect(result).toEqual([]); expect(mockedAxios.post).toHaveBeenCalledWith( - `${ibisServerEndpoint}/v2/ibis/postgres/metadata/constraints`, + `${ibisServerEndpoint}/v2/connector/postgres/metadata/constraints`, { connectionInfo: { connectionUrl: postgresConnectionUrl, @@ -229,7 +281,7 @@ describe('IbisAdaptor', () => { expect(result).toEqual([]); expect(mockedAxios.post).toHaveBeenCalledWith( - `${ibisServerEndpoint}/v2/ibis/bigquery/metadata/constraints`, + `${ibisServerEndpoint}/v2/connector/bigquery/metadata/constraints`, { connectionInfo: expectConnectionInfo }, ); }); @@ -254,7 +306,7 @@ describe('IbisAdaptor', () => { expect(result).toEqual({ valid: true, message: null }); expect(mockedAxios.post).toHaveBeenCalledWith( - `${ibisServerEndpoint}/v2/ibis/postgres/validate/column_is_valid`, + `${ibisServerEndpoint}/v2/connector/postgres/validate/column_is_valid`, { connectionInfo: { connectionUrl: postgresConnectionUrl }, manifestStr: Buffer.from(JSON.stringify(mockManifest)).toString( @@ -286,7 +338,7 @@ describe('IbisAdaptor', () => { expect(result).toEqual({ valid: false, message: 'Error' }); expect(mockedAxios.post).toHaveBeenCalledWith( - `${ibisServerEndpoint}/v2/ibis/postgres/validate/column_is_valid`, + `${ibisServerEndpoint}/v2/connector/postgres/validate/column_is_valid`, { connectionInfo: { connectionUrl: postgresConnectionUrl }, manifestStr: Buffer.from(JSON.stringify(mockManifest)).toString( diff --git a/wren-ui/src/apollo/server/services/modelService.ts b/wren-ui/src/apollo/server/services/modelService.ts index 6466afb0f..64281f436 100644 --- a/wren-ui/src/apollo/server/services/modelService.ts +++ b/wren-ui/src/apollo/server/services/modelService.ts @@ -8,7 +8,12 @@ import { ModelColumn, Relation, } from '@server/repositories'; -import { getLogger } from '@server/utils'; +import { + getLogger, + parseJson, + replaceAllowableSyntax, + validateDisplayName, +} from '@server/utils'; import { RelationData, UpdateRelationData } from '@server/types'; import { IProjectService } from './projectService'; import { @@ -21,14 +26,10 @@ import { IMDLService } from './mdlService'; import { IWrenEngineAdaptor } from '../adaptors/wrenEngineAdaptor'; import { ValidationRules } from '@server/adaptors/ibisAdaptor'; import { isEmpty, capitalize } from 'lodash'; -import { - replaceAllowableSyntax, - validateDisplayName, -} from '@server/utils/regex'; +import {} from '@server/utils/regex'; import * as Errors from '@server/utils/error'; import { DataSourceName } from '@server/types'; import { IQueryService } from './queryService'; -import { canParseJson } from '@/utils/helper'; const logger = getLogger('ModelService'); logger.level = 'debug'; @@ -143,7 +144,7 @@ export class ModelService implements IModelService { } as CheckCalculatedFieldCanQueryData); logger.debug(`${logTitle} : checkCalculatedFieldCanQuery: ${canQuery}`); if (!canQuery) { - const parsedErrorMessage = canParseJson(errorMessage); + const parsedErrorMessage = parseJson(errorMessage); throw Errors.create(Errors.GeneralErrorCodes.INVALID_CALCULATED_FIELD, { customMessage: parsedErrorMessage?.message || errorMessage, originalError: parsedErrorMessage || null, diff --git a/wren-ui/src/apollo/server/utils/helper.ts b/wren-ui/src/apollo/server/utils/helper.ts new file mode 100644 index 000000000..4cb6bc2d0 --- /dev/null +++ b/wren-ui/src/apollo/server/utils/helper.ts @@ -0,0 +1,11 @@ +/** + * @function + * @description Retrieve json without error + */ +export const parseJson = (data) => { + try { + return JSON.parse(data); + } catch (_e) { + return false; + } +}; diff --git a/wren-ui/src/apollo/server/utils/index.ts b/wren-ui/src/apollo/server/utils/index.ts index b6ca2132d..8db524806 100644 --- a/wren-ui/src/apollo/server/utils/index.ts +++ b/wren-ui/src/apollo/server/utils/index.ts @@ -4,3 +4,5 @@ export * from './encode'; export * from './string'; export * from './docker'; export * from './model'; +export * from './helper'; +export * from './regex'; diff --git a/wren-ui/src/utils/helper.ts b/wren-ui/src/utils/helper.ts index f44436199..c2e08ae11 100644 --- a/wren-ui/src/utils/helper.ts +++ b/wren-ui/src/utils/helper.ts @@ -19,11 +19,3 @@ export const parseJson = (data) => { return data; } }; - -export const canParseJson = (data) => { - try { - return JSON.parse(data); - } catch (_e) { - return false; - } -};