From 2e6f4510dd6fa8584aeb9aca8f5ea3d41cad9610 Mon Sep 17 00:00:00 2001 From: Anantshree Chandola Date: Tue, 21 May 2024 12:50:56 +0530 Subject: [PATCH 1/4] add validation for password length (#9798) --- server/src/dto/app-authentication.dto.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/src/dto/app-authentication.dto.ts b/server/src/dto/app-authentication.dto.ts index e911433578..45ad35af11 100644 --- a/server/src/dto/app-authentication.dto.ts +++ b/server/src/dto/app-authentication.dto.ts @@ -1,4 +1,4 @@ -import { IsEmail, IsNotEmpty, IsOptional, IsString, IsUUID, MinLength } from 'class-validator'; +import { IsEmail, IsNotEmpty, IsOptional, IsString, IsUUID, MinLength, MaxLength } from 'class-validator'; import { lowercaseString } from 'src/helpers/utils.helper'; import { Transform } from 'class-transformer'; @@ -31,6 +31,7 @@ export class AppSignupDto { @IsString() @IsNotEmpty() @MinLength(5, { message: 'Password should contain more than 5 letters' }) + @MaxLength(100, { message: 'Password length should not be more than 100 ' }) password: string; @IsOptional() From 7404968056b5c552a332d6d5cc3b3f00f385fd69 Mon Sep 17 00:00:00 2001 From: Akshay Sasidharan Date: Tue, 21 May 2024 19:53:56 +0530 Subject: [PATCH 2/4] remove json attribute added on request options --- plugins/packages/restapi/lib/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/packages/restapi/lib/index.ts b/plugins/packages/restapi/lib/index.ts index 4a8225f985..a36953b841 100644 --- a/plugins/packages/restapi/lib/index.ts +++ b/plugins/packages/restapi/lib/index.ts @@ -111,7 +111,6 @@ export default class RestapiQueryService implements QueryService { ...this.fetchHttpsCertsForCustomCA(sourceOptions), headers: sanitizeHeaders(sourceOptions, queryOptions, hasDataSource), searchParams, - ...(isUrlEncoded ? { form: json } : { json }), }; const hasFiles = (json) => { From 8a9cd790c1ff8ea0eda2a5441ea44a1f9747fbc1 Mon Sep 17 00:00:00 2001 From: Akshay Sasidharan Date: Tue, 21 May 2024 22:15:30 +0530 Subject: [PATCH 3/4] fix TJDB query with subpath setup --- server/src/services/tooljet_db_operations.service.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/server/src/services/tooljet_db_operations.service.ts b/server/src/services/tooljet_db_operations.service.ts index 40582e0d94..496c87cfe0 100644 --- a/server/src/services/tooljet_db_operations.service.ts +++ b/server/src/services/tooljet_db_operations.service.ts @@ -4,6 +4,7 @@ import { QueryService, QueryResult } from '@tooljet/plugins/dist/packages/common import { TooljetDbService } from './tooljet_db.service'; import { isEmpty } from 'lodash'; import { PostgrestProxyService } from './postgrest_proxy.service'; +import { maybeSetSubPath } from 'src/helpers/utils.helper'; @Injectable() export class TooljetDbOperationsService implements QueryService { @@ -74,7 +75,7 @@ export class TooljetDbOperationsService implements QueryService { !isEmpty(offset) && query.push(`offset=${offset}`); } const headers = { 'data-query-id': queryOptions.id, 'tj-workspace-id': queryOptions.organization_id }; - const url = `/api/tooljet-db/proxy/${tableId}` + `?${query}`; + const url = maybeSetSubPath(`/api/tooljet-db/proxy/${tableId}` + `?${query}`); return await this.proxyPostgrest(url, 'GET', headers); } @@ -87,7 +88,7 @@ export class TooljetDbOperationsService implements QueryService { const headers = { 'data-query-id': queryOptions.id, 'tj-workspace-id': queryOptions.organization_id }; - const url = `/api/tooljet-db/proxy/${queryOptions.table_id}`; + const url = maybeSetSubPath(`/api/tooljet-db/proxy/${queryOptions.table_id}`); return await this.proxyPostgrest(url, 'POST', headers, columns); } @@ -112,7 +113,7 @@ export class TooljetDbOperationsService implements QueryService { !isEmpty(whereQuery) && query.push(whereQuery); const headers = { 'data-query-id': queryOptions.id, 'tj-workspace-id': queryOptions.organization_id }; - const url = `/api/tooljet-db/proxy/${tableId}?` + query.join('&') + '&order=id'; + const url = maybeSetSubPath(`/api/tooljet-db/proxy/${tableId}?` + query.join('&') + '&order=id'); return await this.proxyPostgrest(url, 'PATCH', headers, body); } @@ -149,7 +150,7 @@ export class TooljetDbOperationsService implements QueryService { limit && limit !== '' && query.push(`limit=${limit}&order=id`); const headers = { 'data-query-id': queryOptions.id, 'tj-workspace-id': queryOptions.organization_id }; - const url = `/api/tooljet-db/proxy/${tableId}?` + query.join('&'); + const url = maybeSetSubPath(`/api/tooljet-db/proxy/${tableId}?` + query.join('&')); return await this.proxyPostgrest(url, 'DELETE', headers); } From 7c35c5fea0353cf49ad11230648e86ad8f796863 Mon Sep 17 00:00:00 2001 From: Anantshree Chandola Date: Thu, 23 May 2024 21:55:59 +0530 Subject: [PATCH 4/4] Revert masked constants (#9824) * revert masked constants * update * update * update * update * update * removed validation * bump version --------- Co-authored-by: gsmithun4 --- .version | 2 +- frontend/.version | 2 +- .../src/Editor/CodeBuilder/CodeHinter.jsx | 12 ++---- frontend/src/Editor/Editor.jsx | 5 +-- frontend/src/Editor/Viewer.jsx | 3 +- .../OrgConstantsVariablesPreviewBox.jsx | 20 +++------- frontend/src/_stores/currentStateStore.js | 1 + server/.version | 2 +- .../organization_constants.controller.ts | 26 +++---------- server/src/services/data_queries.service.ts | 2 +- .../organization_constants.service.ts | 38 ++++--------------- 11 files changed, 30 insertions(+), 83 deletions(-) diff --git a/.version b/.version index 5b9cd9afd5..3e197472e2 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -2.43.0 +2.44.0 diff --git a/frontend/.version b/frontend/.version index 5b9cd9afd5..3e197472e2 100644 --- a/frontend/.version +++ b/frontend/.version @@ -1 +1 @@ -2.43.0 +2.44.0 diff --git a/frontend/src/Editor/CodeBuilder/CodeHinter.jsx b/frontend/src/Editor/CodeBuilder/CodeHinter.jsx index c0fc187185..378cce3ce3 100644 --- a/frontend/src/Editor/CodeBuilder/CodeHinter.jsx +++ b/frontend/src/Editor/CodeBuilder/CodeHinter.jsx @@ -103,8 +103,6 @@ export function CodeHinter({ }) { const context = useContext(CodeHinterContext); - const hiddenWorkspaceConstantText = 'Workspace constant values are hidden'; - const darkMode = localStorage.getItem('darkMode') === 'true'; const options = { lineNumbers: lineNumbers ?? false, @@ -137,8 +135,6 @@ export function CodeHinter({ const isWorkspaceVariable = typeof currentValue === 'string' && (currentValue.includes('%%client') || currentValue.includes('%%server')); - const isWorkspaceConstant = typeof currentValue === 'string' && currentValue.includes('constants.'); - const constantRegex = /{{constants\.([a-zA-Z0-9_]+)}}/g; const slideInStyles = useSpring({ @@ -269,7 +265,7 @@ export function CodeHinter({ globalPreviewCopy = preview; globalErrorCopy = null; setResolvingError(null); - setResolvedValue(isWorkspaceConstant ? hiddenWorkspaceConstantText : preview); + setResolvedValue(preview); } return [globalPreviewCopy, globalErrorCopy]; @@ -281,7 +277,7 @@ export function CodeHinter({ return () => { if (enablePreview) { setPrevCurrentValue(null); - setResolvedValue(isWorkspaceConstant ? hiddenWorkspaceConstantText : globalPreviewCopy); + setResolvedValue(globalPreviewCopy); setResolvingError(globalErrorCopy); } }; @@ -377,9 +373,9 @@ export function CodeHinter({
- {!isWorkspaceConstant && previewType} + {previewType}
- {isFocused && !isWorkspaceConstant && ( + {isFocused && (
copyToClipboard(content)} icon="copy" tip="Copy to clipboard" />
diff --git a/frontend/src/Editor/Editor.jsx b/frontend/src/Editor/Editor.jsx index e2ee2bd600..318671f5a3 100644 --- a/frontend/src/Editor/Editor.jsx +++ b/frontend/src/Editor/Editor.jsx @@ -77,8 +77,6 @@ enablePatches(); const decimalToHex = (alpha) => (alpha === 0 ? '00' : Math.round(255 * alpha).toString(16)); -const maskedWorkspaceConstantStr = '**************'; - const EditorComponent = (props) => { const { socket } = createWebsocketConnection(props?.params?.id); const mounted = useMounted(); @@ -374,7 +372,8 @@ const EditorComponent = (props) => { orgEnvironmentConstantService.getAll().then(({ constants }) => { const orgConstants = {}; constants.map((constant) => { - orgConstants[constant.name] = maskedWorkspaceConstantStr; + const constantValue = constant.values.find((value) => value.environmentName === 'production')['value']; + orgConstants[constant.name] = constantValue; }); useCurrentStateStore.getState().actions.setCurrentState({ diff --git a/frontend/src/Editor/Viewer.jsx b/frontend/src/Editor/Viewer.jsx index 4c668e80e3..7f7ad0ec7b 100644 --- a/frontend/src/Editor/Viewer.jsx +++ b/frontend/src/Editor/Viewer.jsx @@ -48,7 +48,6 @@ import DesktopHeader from './Viewer/DesktopHeader'; import './Viewer/viewer.scss'; import useAppDarkMode from '@/_hooks/useAppDarkMode'; -const maskedWorkspaceConstantStr = '**************'; class ViewerComponent extends React.Component { constructor(props) { super(props); @@ -246,7 +245,7 @@ class ViewerComponent extends React.Component { if (variablesResult && Array.isArray(variablesResult)) { variablesResult.map((constant) => { const constantValue = constant.values.find((value) => value.environmentName === 'production')['value']; - orgConstants[constant.name] = maskedWorkspaceConstantStr; + orgConstants[constant.name] = constantValue; }); return { constants: orgConstants, diff --git a/frontend/src/_components/OrgConstantsVariablesResolver/OrgConstantsVariablesPreviewBox.jsx b/frontend/src/_components/OrgConstantsVariablesResolver/OrgConstantsVariablesPreviewBox.jsx index 4a297be32e..2e49f54559 100644 --- a/frontend/src/_components/OrgConstantsVariablesResolver/OrgConstantsVariablesPreviewBox.jsx +++ b/frontend/src/_components/OrgConstantsVariablesResolver/OrgConstantsVariablesPreviewBox.jsx @@ -61,19 +61,7 @@ const verifyConstant = (value, definedConstants) => { }; const ResolvedValue = ({ value, isFocused, state = {}, type }) => { - const isConstant = type === 'Workspace Constant'; - const hiddenWorkspaceConstantText = 'Workspace constant values are hidden'; - const invalidConstants = verifyConstant(value, state.constants); - let preview; - let error; - if (invalidConstants?.length) { - [preview, error] = [value, `Undefined constants: ${invalidConstants}`]; - } else { - [preview, error] = resolveReferences(value, state, null, {}, true, true); - if (isConstant) { - preview = hiddenWorkspaceConstantText; - } - } + const [preview, error] = resolveReferences(value, state, null, {}, true, true); const previewType = typeof preview; @@ -84,7 +72,7 @@ const ResolvedValue = ({ value, isFocused, state = {}, type }) => { : error?.toString(); const isValidError = error && errorMessage !== 'HiddenEnvironmentVariable'; - if (error && (!isValidError || error?.toString().includes('Undefined constants:'))) { + if (error && !isValidError) { resolvedValue = errorMessage; } @@ -109,6 +97,8 @@ const ResolvedValue = ({ value, isFocused, state = {}, type }) => { } }; + const isConstant = type === 'Workspace Constant'; + const [heightRef, currentHeight] = useHeight(); const slideInStyles = useSpring({ @@ -130,7 +120,7 @@ const ResolvedValue = ({ value, isFocused, state = {}, type }) => {
- {isValidError ? 'Error' : isConstant ? null : ` ${type} - ${previewType}`} + {isValidError ? 'Error' : ` ${type} - ${previewType}`}
{getPreviewContent(resolvedValue, previewType)} diff --git a/frontend/src/_stores/currentStateStore.js b/frontend/src/_stores/currentStateStore.js index 3aaacc404c..7775303bb0 100644 --- a/frontend/src/_stores/currentStateStore.js +++ b/frontend/src/_stores/currentStateStore.js @@ -17,6 +17,7 @@ const initialState = { variables: {}, }, succededQuery: {}, + constants: {}, }; export const useCurrentStateStore = create( diff --git a/server/.version b/server/.version index 5b9cd9afd5..3e197472e2 100644 --- a/server/.version +++ b/server/.version @@ -1 +1 @@ -2.43.0 +2.44.0 diff --git a/server/src/controllers/organization_constants.controller.ts b/server/src/controllers/organization_constants.controller.ts index 385467336a..9319531677 100644 --- a/server/src/controllers/organization_constants.controller.ts +++ b/server/src/controllers/organization_constants.controller.ts @@ -20,7 +20,6 @@ import { OrganizationConstantsAbilityFactory } from 'src/modules/casl/abilities/ import { AppDecorator as App } from 'src/decorators/app.decorator'; import { OrgEnvironmentVariablesAbilityFactory } from 'src/modules/casl/abilities/org-environment-variables-ability.factory'; import { OrgEnvironmentVariable } from 'src/entities/org_envirnoment_variable.entity'; -import { OrganizationConstant } from 'src/entities/organization_constants.entity'; @Controller('organization-constants') export class OrganizationConstantController { @@ -32,39 +31,24 @@ export class OrganizationConstantController { @UseGuards(JwtAuthGuard) @Get() - async get(@User() user, @Query('decryptValue') decryptValue) { - const ability = await this.organizationConstantsAbilityFactory.organizationConstantActions(user, null); - const decrypt = - decryptValue === 'true' && - (ability.can('createOrganizationConstant', OrganizationConstant) || - ability.can('deleteOrganizationConstant', OrganizationConstant)); - const result = await this.organizationConstantsService.allEnvironmentConstants(user.organizationId, decrypt); + async get(@User() user) { + const result = await this.organizationConstantsService.allEnvironmentConstants(user.organizationId); return { constants: result }; } @UseGuards(IsPublicGuard) @Get(':app_slug') async getConstantsFromApp(@App() app, @User() user) { - const result = await this.organizationConstantsService.allEnvironmentConstants(app.organizationId, false); + const result = await this.organizationConstantsService.allEnvironmentConstants(app.organizationId); return { constants: result }; } @UseGuards(JwtAuthGuard) @Get('/environment/:environmentId') - async getConstantsFromEnvironment( - @User() user, - @Param('environmentId') environmentId, - @Query('decryptValue') decryptValue - ) { - const ability = await this.organizationConstantsAbilityFactory.organizationConstantActions(user, null); - const decrypt = - decryptValue === 'true' && - (ability.can('createOrganizationConstant', OrganizationConstant) || - ability.can('deleteOrganizationConstant', OrganizationConstant)); + async getConstantsFromEnvironment(@User() user, @Param('environmentId') environmentId) { const result = await this.organizationConstantsService.getConstantsForEnvironment( user.organizationId, - environmentId, - decrypt + environmentId ); return { constants: result }; } diff --git a/server/src/services/data_queries.service.ts b/server/src/services/data_queries.service.ts index ed4feb44c5..7ff7977e42 100644 --- a/server/src/services/data_queries.service.ts +++ b/server/src/services/data_queries.service.ts @@ -605,7 +605,7 @@ export class DataQueriesService { if (variables?.length > 0) { for (const variable of variables) { - object = object.replace(variable, await this.resolveConstants(variable, organization_id, environmentId)); + object = object.replace(variable, options[variable]); } } return object; diff --git a/server/src/services/organization_constants.service.ts b/server/src/services/organization_constants.service.ts index a30c9bfe4a..ab49c597b4 100644 --- a/server/src/services/organization_constants.service.ts +++ b/server/src/services/organization_constants.service.ts @@ -17,7 +17,7 @@ export class OrganizationConstantsService { private appEnvironmentService: AppEnvironmentService ) {} - async allEnvironmentConstants(organizationId: string, decryptValue: boolean): Promise { + async allEnvironmentConstants(organizationId: string): Promise { return await dbTransactionWrap(async (manager: EntityManager) => { const query = manager .createQueryBuilder(OrganizationConstant, 'organization_constants') @@ -33,21 +33,11 @@ export class OrganizationConstantsService { appEnvironments.map(async (env) => { const value = constant.orgEnvironmentConstantValues.find((value) => value.environmentId === env.id); - const valueResult = { + return { environmentName: env.name, - id: value ? value.environmentId : undefined, // Safeguard for undefined 'value' + value: value && value.value.length > 0 ? await this.decryptSecret(organizationId, value.value) : '', + id: value.environmentId, }; - - if (value && value.value.length > 0) { - const decryptedOrRawValue = decryptValue - ? await this.decryptSecret(organizationId, value.value) - : value.value; - - if (decryptValue) { - valueResult['value'] = decryptedOrRawValue; - } - } - return valueResult; }) ); @@ -64,11 +54,7 @@ export class OrganizationConstantsService { }); } - async getConstantsForEnvironment( - organizationId: string, - environmentId: string, - decryptValue: boolean - ): Promise { + async getConstantsForEnvironment(organizationId: string, environmentId: string): Promise { return await dbTransactionWrap(async (manager: EntityManager) => { const query = manager .createQueryBuilder(OrganizationConstant, 'organization_constants') @@ -78,20 +64,12 @@ export class OrganizationConstantsService { const result = await query.getMany(); const constantsWithValues = result.map(async (constant) => { - const constantResult = { + const decryptedValue = await this.decryptSecret(organizationId, constant.orgEnvironmentConstantValues[0].value); + return { id: constant.id, name: constant.constantName, + value: decryptedValue, }; - - if (decryptValue && constant.orgEnvironmentConstantValues.length > 0) { - const decryptedValue = await this.decryptSecret( - organizationId, - constant.orgEnvironmentConstantValues[0].value - ); - constantResult['value'] = decryptedValue; - } - - return constantResult; }); return Promise.all(constantsWithValues);