diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index 7a95fb80a5..a443ae237a 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -15,6 +15,6 @@ "eslint-config-prettier": "^9.0.0", "eslint-plugin-unused-imports": "^3.0.0", "eslint-plugin-prefer-arrow": "^1.2.3", - "@stylistic/eslint-plugin": "^1.6.2" + "@stylistic/eslint-plugin-ts": "^1.6.2" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bfc4e6b978..27dfb45c67 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1245,7 +1245,7 @@ importers: packages/eslint-config: dependencies: - '@stylistic/eslint-plugin': + '@stylistic/eslint-plugin-ts': specifier: ^1.6.2 version: 1.6.2(eslint@8.53.0)(typescript@4.9.5) '@typescript-eslint/eslint-plugin': @@ -2518,7 +2518,7 @@ importers: specifier: ^1.0.6 version: link:../../packages/config '@ballerine/eslint-config': - specifier: ^1.0.6 + specifier: ^1.0.7 version: link:../../packages/eslint-config '@cspell/cspell-types': specifier: ^6.31.1 @@ -2908,7 +2908,7 @@ packages: dependencies: '@astrojs/markdown-remark': 3.5.0(astro@3.3.3) '@mdx-js/mdx': 2.3.0 - acorn: 8.11.2 + acorn: 8.11.3 astro: 3.3.3(@types/node@18.17.19)(typescript@4.9.5) es-module-lexer: 1.4.1 estree-util-visit: 1.2.1 @@ -13406,32 +13406,6 @@ packages: espree: 9.6.1 dev: false - /@stylistic/eslint-plugin-jsx@1.6.2(eslint@8.53.0): - resolution: {integrity: sha512-hbbouazSJbHD/fshBIOLh9JgtSphKNoTCfHLSNBjAkXLK+GR4i2jhEZZF9P0mtXrNuy2WWInmpq/g0pfWBmSBA==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: '>=8.40.0' - dependencies: - '@stylistic/eslint-plugin-js': 1.6.2(eslint@8.53.0) - '@types/eslint': 8.56.4 - eslint: 8.53.0 - estraverse: 5.3.0 - picomatch: 4.0.1 - dev: false - - /@stylistic/eslint-plugin-plus@1.6.2(eslint@8.53.0)(typescript@4.9.5): - resolution: {integrity: sha512-EDMwa6gzKw4bXRqdIAUvZDfIgwotbjJs8o+vYE22chAYtVAnA0Pcq+cPx0Uk35t2gvJWb5OaLDjqA6oy1tD0jg==} - peerDependencies: - eslint: '*' - dependencies: - '@types/eslint': 8.56.4 - '@typescript-eslint/utils': 6.21.0(eslint@8.53.0)(typescript@4.9.5) - eslint: 8.53.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: false - /@stylistic/eslint-plugin-ts@1.6.2(eslint@8.53.0)(typescript@4.9.5): resolution: {integrity: sha512-FizV58em0OjO/xFHRIy/LJJVqzxCNmYC/xVtKDf8aGDRgZpLo+lkaBKfBrbMkAGzhBKbYj+iLEFI4WEl6aVZGQ==} engines: {node: ^16.0.0 || >=18.0.0} @@ -13447,23 +13421,6 @@ packages: - typescript dev: false - /@stylistic/eslint-plugin@1.6.2(eslint@8.53.0)(typescript@4.9.5): - resolution: {integrity: sha512-EFnVcKOE5HTiMlVwisL9hHjz8a69yBbJRscWF/z+/vl6M4ew8NVrBlY8ea7KdV8QtyCY4Yapmsbg5ZDfhWlEgg==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: '>=8.40.0' - dependencies: - '@stylistic/eslint-plugin-js': 1.6.2(eslint@8.53.0) - '@stylistic/eslint-plugin-jsx': 1.6.2(eslint@8.53.0) - '@stylistic/eslint-plugin-plus': 1.6.2(eslint@8.53.0)(typescript@4.9.5) - '@stylistic/eslint-plugin-ts': 1.6.2(eslint@8.53.0)(typescript@4.9.5) - '@types/eslint': 8.56.4 - eslint: 8.53.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: false - /@sveltejs/vite-plugin-svelte-inspector@1.0.4(@sveltejs/vite-plugin-svelte@2.5.2)(svelte@3.59.2)(vite@4.5.0): resolution: {integrity: sha512-zjiuZ3yydBtwpF3bj0kQNV0YXe+iKE545QGZVTaylW3eAzFr+pJ/cwK8lZEaRp4JtaJXhD5DyWAV4AxLh6DgaQ==} engines: {node: ^14.18.0 || >= 16} @@ -14149,23 +14106,15 @@ packages: /@types/eslint-scope@3.7.7: resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} dependencies: - '@types/eslint': 8.44.7 + '@types/eslint': 8.56.4 '@types/estree': 1.0.5 dev: true - /@types/eslint@8.44.7: - resolution: {integrity: sha512-f5ORu2hcBbKei97U73mf+l9t4zTGl74IqZ0GQk4oVea/VS8tQZYkUveSYojk+frraAVYId0V2WC9O4PTNru2FQ==} - dependencies: - '@types/estree': 1.0.5 - '@types/json-schema': 7.0.15 - dev: true - /@types/eslint@8.56.4: resolution: {integrity: sha512-lG1GLUnL5vuRBGb3MgWUWLdGMH2Hps+pERuyQXCfWozuGKdnhf9Pbg4pkcrVUHjKrU7Rl+GCZ/299ObBXZFAxg==} dependencies: '@types/estree': 1.0.5 '@types/json-schema': 7.0.15 - dev: false /@types/estree-jsx@1.0.3: resolution: {integrity: sha512-pvQ+TKeRHeiUGRhvYwRrQ/ISnohKkSJR14fT2yqyZ4e9K5vqc7hrtY2Y1Dw0ZwAzQ6DQsxsaCUuSIIi8v0Cq6w==} @@ -27089,11 +27038,6 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - /picomatch@4.0.1: - resolution: {integrity: sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg==} - engines: {node: '>=12'} - dev: false - /pify@2.3.0: resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} engines: {node: '>=0.10.0'} @@ -29755,7 +29699,7 @@ packages: /strip-literal@0.4.2: resolution: {integrity: sha512-pv48ybn4iE1O9RLgCAN0iU4Xv7RlBTiit6DKmMiErbs9x1wH6vXBs45tWc0H5wUIF6TLTrKweqkmYF/iraQKNw==} dependencies: - acorn: 8.11.2 + acorn: 8.11.3 dev: true /strip-literal@1.3.0: @@ -30289,7 +30233,7 @@ packages: hasBin: true dependencies: '@jridgewell/source-map': 0.3.5 - acorn: 8.11.2 + acorn: 8.11.3 commander: 2.20.3 source-map-support: 0.5.21 dev: true @@ -30782,7 +30726,7 @@ packages: '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 '@types/node': 18.17.19 - acorn: 8.11.2 + acorn: 8.11.3 acorn-walk: 8.3.0 arg: 4.1.3 create-require: 1.1.1 @@ -30813,7 +30757,7 @@ packages: '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 '@types/node': 18.17.19 - acorn: 8.11.2 + acorn: 8.11.3 acorn-walk: 8.3.0 arg: 4.1.3 create-require: 1.1.1 diff --git a/sdks/workflow-browser-sdk/rollup.config.ts b/sdks/workflow-browser-sdk/rollup.config.ts index 1b3899a043..0138840383 100644 --- a/sdks/workflow-browser-sdk/rollup.config.ts +++ b/sdks/workflow-browser-sdk/rollup.config.ts @@ -10,6 +10,7 @@ import dts from 'rollup-plugin-dts'; import json from '@rollup/plugin-json'; import visualizer from 'rollup-plugin-visualizer'; + // eslint-disable-next-line @typescript-eslint/no-var-requires const size = require('rollup-plugin-size'); diff --git a/sdks/workflow-browser-sdk/src/lib/tests/msw.ts b/sdks/workflow-browser-sdk/src/lib/tests/msw.ts index ef47bea31c..c272bebe2b 100644 --- a/sdks/workflow-browser-sdk/src/lib/tests/msw.ts +++ b/sdks/workflow-browser-sdk/src/lib/tests/msw.ts @@ -2,6 +2,7 @@ import { sleep } from '@ballerine/common'; import { DefaultBodyType, PathParams, ResponseResolver, rest, RestContext, RestRequest } from 'msw'; import { setupServer } from 'msw/node'; import { backendOptions } from '../backend-options'; + export let response: | { method: string; diff --git a/services/workflows-service/package.json b/services/workflows-service/package.json index ab7f5c2362..f97fcddd65 100644 --- a/services/workflows-service/package.json +++ b/services/workflows-service/package.json @@ -102,7 +102,7 @@ }, "devDependencies": { "@ballerine/config": "^1.0.6", - "@ballerine/eslint-config": "^1.0.6", + "@ballerine/eslint-config": "^1.0.7", "@cspell/cspell-types": "^6.31.1", "@nestjs/cli": "9.3.0", "@nestjs/swagger": "6.2.1", diff --git a/services/workflows-service/plugins/verify-repository-project-scoped/verify-repository-project-scoped.rule.js b/services/workflows-service/plugins/verify-repository-project-scoped/verify-repository-project-scoped.rule.js index fd002be6b0..e1f7f6f469 100644 --- a/services/workflows-service/plugins/verify-repository-project-scoped/verify-repository-project-scoped.rule.js +++ b/services/workflows-service/plugins/verify-repository-project-scoped/verify-repository-project-scoped.rule.js @@ -16,9 +16,11 @@ module.exports = { ); const UNSCOPED_METHOD_NAMES = ['unscoped', 'create', 'update']; + return { MethodDefinition: node => { if (!isRepository || node.key.name === 'constructor') return; + const isUnscoped = UNSCOPED_METHOD_NAMES.some(name => node.key.name.toLowerCase().includes(name), ); diff --git a/services/workflows-service/src/auth/auth.service.ts b/services/workflows-service/src/auth/auth.service.ts index 302661f4cd..170d345023 100644 --- a/services/workflows-service/src/auth/auth.service.ts +++ b/services/workflows-service/src/auth/auth.service.ts @@ -19,8 +19,10 @@ export class AuthService { const { id, firstName, lastName, roles } = user; const roleList = roles as string[]; + return { id, email, firstName, lastName, roles: roleList }; } + return null; } } diff --git a/services/workflows-service/src/auth/auth.service.unit.test.ts b/services/workflows-service/src/auth/auth.service.unit.test.ts index 91795326f7..8a977aa916 100644 --- a/services/workflows-service/src/auth/auth.service.unit.test.ts +++ b/services/workflows-service/src/auth/auth.service.unit.test.ts @@ -27,6 +27,7 @@ const userService = { if (email === VALID_CREDENTIALS.email) { return USER; } + return null; }, getByEmailUnscoped(email: any) { diff --git a/services/workflows-service/src/auth/basic/basic.strategy.ts b/services/workflows-service/src/auth/basic/basic.strategy.ts index 31410bef80..6add88f526 100644 --- a/services/workflows-service/src/auth/basic/basic.strategy.ts +++ b/services/workflows-service/src/auth/basic/basic.strategy.ts @@ -13,9 +13,11 @@ export class BasicStrategy extends PassportStrategy(Strategy) implements IAuthSt async validate(email: string, password: string): Promise { const user = await this.authService.validateUser(email, password); + if (!user) { throw new UnauthorizedException(); } + return user; } } diff --git a/services/workflows-service/src/auth/basic/basic.strategy.unit.test.ts b/services/workflows-service/src/auth/basic/basic.strategy.unit.test.ts index 60b2d9c124..1955244fd2 100644 --- a/services/workflows-service/src/auth/basic/basic.strategy.unit.test.ts +++ b/services/workflows-service/src/auth/basic/basic.strategy.unit.test.ts @@ -28,6 +28,7 @@ describe('Testing the basicStrategyBase.validate()', () => { authService.validateUser.mockReturnValue(Promise.resolve(null)); //ACT const result = basicStrategy.validate('noUsername', TEST_PASSWORD); + //ASSERT return expect(result).rejects.toThrowError(UnauthorizedException); }); diff --git a/services/workflows-service/src/auth/local/local.strategy.ts b/services/workflows-service/src/auth/local/local.strategy.ts index a1352d2493..dc870d5d9a 100644 --- a/services/workflows-service/src/auth/local/local.strategy.ts +++ b/services/workflows-service/src/auth/local/local.strategy.ts @@ -15,6 +15,7 @@ export class LocalStrategy extends PassportStrategy(Strategy) implements IAuthSt async validate(email: string, password: string): Promise { const user = await this.authService.validateUser(email, password); + if (!user) { throw new UnauthorizedException(); } diff --git a/services/workflows-service/src/auth/local/local.strategy.unit.test.ts b/services/workflows-service/src/auth/local/local.strategy.unit.test.ts index 222d977661..a199e8faad 100644 --- a/services/workflows-service/src/auth/local/local.strategy.unit.test.ts +++ b/services/workflows-service/src/auth/local/local.strategy.unit.test.ts @@ -28,6 +28,7 @@ describe('Testing the localStrategyBase.validate()', () => { authService.validateUser.mockReturnValue(Promise.resolve(null)); //ACT const result = localStrategy.validate('noUsername', TEST_PASSWORD); + //ASSERT return expect(result).rejects.toThrowError(UnauthorizedException); }); diff --git a/services/workflows-service/src/business/business.controller.external.ts b/services/workflows-service/src/business/business.controller.external.ts index a7622d720d..de09aec4cf 100644 --- a/services/workflows-service/src/business/business.controller.external.ts +++ b/services/workflows-service/src/business/business.controller.external.ts @@ -66,6 +66,7 @@ export class BusinessControllerExternal { @ProjectIds() projectIds: TProjectIds, ): Promise { const args = plainToClass(BusinessFindManyArgs, request.query); + return this.service.list(args, projectIds); } diff --git a/services/workflows-service/src/business/business.controller.ts b/services/workflows-service/src/business/business.controller.ts index 95e7854823..58d7e064a5 100644 --- a/services/workflows-service/src/business/business.controller.ts +++ b/services/workflows-service/src/business/business.controller.ts @@ -59,6 +59,7 @@ export class BusinessControllerExternal { @ProjectIds() projectIds: TProjectIds, ): Promise { const args = plainToClass(BusinessFindManyArgs, request.query); + return this.service.list(args, projectIds); } diff --git a/services/workflows-service/src/collection-flow/collection-flow.service.ts b/services/workflows-service/src/collection-flow/collection-flow.service.ts index 8d7e43f8f3..299ce9b8bc 100644 --- a/services/workflows-service/src/collection-flow/collection-flow.service.ts +++ b/services/workflows-service/src/collection-flow/collection-flow.service.ts @@ -15,7 +15,7 @@ import { UiDefinitionService } from '@/ui-definition/ui-definition.service'; import { WorkflowDefinitionRepository } from '@/workflow-defintion/workflow-definition.repository'; import { WorkflowRuntimeDataRepository } from '@/workflow/workflow-runtime-data.repository'; import { WorkflowService } from '@/workflow/workflow.service'; -import { AnyRecord, DefaultContextSchema } from '@ballerine/common'; +import { AnyRecord } from '@ballerine/common'; import { Injectable } from '@nestjs/common'; import { Customer, EndUser, UiDefinitionContext, WorkflowRuntimeData } from '@prisma/client'; import { plainToClass } from 'class-transformer'; diff --git a/services/workflows-service/src/collection-flow/controllers/collection-flow.controller.ts b/services/workflows-service/src/collection-flow/controllers/collection-flow.controller.ts index 210cf94c23..1d43358e66 100644 --- a/services/workflows-service/src/collection-flow/controllers/collection-flow.controller.ts +++ b/services/workflows-service/src/collection-flow/controllers/collection-flow.controller.ts @@ -47,6 +47,7 @@ export class ColectionFlowController { try { const adapter = this.adapterManager.getAdapter(activeWorkflow.workflowDefinitionId); + return { result: activeWorkflow ? adapter.serialize(activeWorkflow) : null, }; @@ -56,6 +57,7 @@ export class ColectionFlowController { `${activeWorkflow.workflowDefinitionId as string} is not supported.`, ); } + throw error; } } diff --git a/services/workflows-service/src/collection-flow/controllers/collection-flow.files.controller.ts b/services/workflows-service/src/collection-flow/controllers/collection-flow.files.controller.ts index d7151d42ae..72100ca5fb 100644 --- a/services/workflows-service/src/collection-flow/controllers/collection-flow.files.controller.ts +++ b/services/workflows-service/src/collection-flow/controllers/collection-flow.files.controller.ts @@ -56,6 +56,7 @@ export class CollectionFlowFilesController { if (error.includes('expected size')) { throw new UnprocessableEntityException(FILE_SIZE_EXCEEDED_MSG); } + throw new UnprocessableEntityException(error); }, }), diff --git a/services/workflows-service/src/common/access-control/abac.util.ts b/services/workflows-service/src/common/access-control/abac.util.ts index 397db2a098..84f7d24cee 100644 --- a/services/workflows-service/src/common/access-control/abac.util.ts +++ b/services/workflows-service/src/common/access-control/abac.util.ts @@ -9,5 +9,6 @@ export const getInvalidAttributes = ( data: Record, ): string[] => { const filteredData = permission.filter(data) as Record; + return Object.keys(data).filter(key => !(key in filteredData)); }; diff --git a/services/workflows-service/src/common/ajv/ajv.validator.ts b/services/workflows-service/src/common/ajv/ajv.validator.ts index cfc4dccfe5..21f4ee3e7d 100644 --- a/services/workflows-service/src/common/ajv/ajv.validator.ts +++ b/services/workflows-service/src/common/ajv/ajv.validator.ts @@ -6,6 +6,7 @@ export const ajv = new Ajv({ strict: false, coerceTypes: true, }); + addFormats(ajv, { formats: ['email', 'uri', 'date', 'date-time'], keywords: true, diff --git a/services/workflows-service/src/common/app-logger/app-logger.service.ts b/services/workflows-service/src/common/app-logger/app-logger.service.ts index 17b66abb56..0df4e4c2ab 100644 --- a/services/workflows-service/src/common/app-logger/app-logger.service.ts +++ b/services/workflows-service/src/common/app-logger/app-logger.service.ts @@ -35,11 +35,13 @@ export class AppLoggerService implements LoggerService, OnModuleDestroy { }; const reqId = this.cls.get('requestId'); + if (reqId) { metadata.reqId = reqId; } const entity = this.cls.get('entity'); + if (entity && entity.type !== 'admin') { if (entity.type === 'customer') { // @ts-ignore @@ -49,6 +51,7 @@ export class AppLoggerService implements LoggerService, OnModuleDestroy { metadata.entity = entity.endUser; } } + return metadata; } } diff --git a/services/workflows-service/src/common/filters/AllExceptions.filter.ts b/services/workflows-service/src/common/filters/AllExceptions.filter.ts index 2abcf2f7bf..07db1a2a4c 100644 --- a/services/workflows-service/src/common/filters/AllExceptions.filter.ts +++ b/services/workflows-service/src/common/filters/AllExceptions.filter.ts @@ -88,6 +88,7 @@ export class AllExceptionsFilter extends BaseExceptionFilter { } else if (status >= 500) { message = message + ' - Server Error:'; } + return message; } } diff --git a/services/workflows-service/src/common/filters/HttpExceptions.filter.ts b/services/workflows-service/src/common/filters/HttpExceptions.filter.ts index ca8ca22daa..6de49ba935 100644 --- a/services/workflows-service/src/common/filters/HttpExceptions.filter.ts +++ b/services/workflows-service/src/common/filters/HttpExceptions.filter.ts @@ -40,6 +40,7 @@ export class HttpExceptionFilter extends BaseExceptionFilter { catch(exception: Prisma.PrismaClientKnownRequestError, host: ArgumentsHost) { const statusCode = this.errorCodesStatusMapping[exception.code] ?? 500; let message = ''; + if (host.getType() === 'http') { // for http requests (REST) // Todo : Add all other exception types and also add mapping @@ -50,12 +51,14 @@ export class HttpExceptionFilter extends BaseExceptionFilter { } else { message = `[${exception.code}]: ` + this.exceptionShortMessage(exception.message); } + if (!Object.keys(this.errorCodesStatusMapping).includes(exception.code)) { return super.catch(exception, host); } throw new HttpException(message, statusCode); } + throw new HttpException(message, statusCode); } @@ -65,6 +68,7 @@ export class HttpExceptionFilter extends BaseExceptionFilter { */ exceptionShortMessage(message: string): string { const shortMessage = message.substring(message.indexOf('→')); + return shortMessage.substring(shortMessage.indexOf('\n')).replace(/\n/g, '').trim(); } } diff --git a/services/workflows-service/src/common/filters/prisma-client-validation-filter/utils/parsers/invalid-argument-parser/invalid-argument.parser.ts b/services/workflows-service/src/common/filters/prisma-client-validation-filter/utils/parsers/invalid-argument-parser/invalid-argument.parser.ts index 99b1595840..67c590c7f4 100644 --- a/services/workflows-service/src/common/filters/prisma-client-validation-filter/utils/parsers/invalid-argument-parser/invalid-argument.parser.ts +++ b/services/workflows-service/src/common/filters/prisma-client-validation-filter/utils/parsers/invalid-argument-parser/invalid-argument.parser.ts @@ -11,6 +11,7 @@ export class InvalidArgumentParser extends IParser { parse(): IParserResult { const { message } = this; + if (!message) return {}; return this.execPattern(this.pattern, (result, match) => { diff --git a/services/workflows-service/src/common/filters/prisma-client-validation-filter/utils/parsers/unknown-argument-parser/unknown-argument.parser.unit.test.ts b/services/workflows-service/src/common/filters/prisma-client-validation-filter/utils/parsers/unknown-argument-parser/unknown-argument.parser.unit.test.ts index e47ca4274f..ca7ef5a402 100644 --- a/services/workflows-service/src/common/filters/prisma-client-validation-filter/utils/parsers/unknown-argument-parser/unknown-argument.parser.unit.test.ts +++ b/services/workflows-service/src/common/filters/prisma-client-validation-filter/utils/parsers/unknown-argument-parser/unknown-argument.parser.unit.test.ts @@ -41,6 +41,7 @@ describe('UnknownArgumentParser', () => { params.failedAtPath, params.type, ); + return result; }, {} as Record); }); diff --git a/services/workflows-service/src/common/guards/session-auth.guard.ts b/services/workflows-service/src/common/guards/session-auth.guard.ts index 2d3ca697f9..254cd9a32e 100644 --- a/services/workflows-service/src/common/guards/session-auth.guard.ts +++ b/services/workflows-service/src/common/guards/session-auth.guard.ts @@ -22,6 +22,7 @@ export class SessionAuthGuard implements CanActivate { const req = context.switchToHttp().getRequest(); const authenticatedEntity = req.user as AuthenticatedEntity | undefined; + if ( req.isAuthenticated() || !!authenticatedEntity?.customer || diff --git a/services/workflows-service/src/common/http-service/http-config.service.ts b/services/workflows-service/src/common/http-service/http-config.service.ts index 766aae0911..66efc83605 100644 --- a/services/workflows-service/src/common/http-service/http-config.service.ts +++ b/services/workflows-service/src/common/http-service/http-config.service.ts @@ -36,6 +36,7 @@ export const initHttpMoudle = () => }; const timeout = configService.get('HTTP_TIMEOUT_IN_MS', 10_000); + return { timeout, maxRedirects: configService.get('HTTP_MAX_REDIRECTS', 10), diff --git a/services/workflows-service/src/common/interceptors/remove-temp-file.interceptor.ts b/services/workflows-service/src/common/interceptors/remove-temp-file.interceptor.ts index d90e00df1f..6e3c6b452c 100644 --- a/services/workflows-service/src/common/interceptors/remove-temp-file.interceptor.ts +++ b/services/workflows-service/src/common/interceptors/remove-temp-file.interceptor.ts @@ -9,6 +9,7 @@ export class RemoveTempFileInterceptor implements NestInterceptor { constructor(private readonly logger: AppLoggerService) {} private deleteTempFile(req: Request) { const filePath = req?.file?.path; + if (filePath) { try { // Your logic to handle deletion (for example, using fs.unlink) diff --git a/services/workflows-service/src/common/middlewares/request-id.middleware.ts b/services/workflows-service/src/common/middlewares/request-id.middleware.ts index ea49e5b84f..daee1126d1 100644 --- a/services/workflows-service/src/common/middlewares/request-id.middleware.ts +++ b/services/workflows-service/src/common/middlewares/request-id.middleware.ts @@ -34,6 +34,7 @@ export class RequestIdMiddleware implements NestMiddleware { const logFn = () => { const endTime = new Date(); cleanup(); + if (isRelevantReq) { reqMetadata = { ...reqMetadata, diff --git a/services/workflows-service/src/common/middlewares/user-session-audit.middleware.ts b/services/workflows-service/src/common/middlewares/user-session-audit.middleware.ts index 44c4d7afe9..f580150094 100644 --- a/services/workflows-service/src/common/middlewares/user-session-audit.middleware.ts +++ b/services/workflows-service/src/common/middlewares/user-session-audit.middleware.ts @@ -18,6 +18,7 @@ export class UserSessionAuditMiddleware implements NestMiddleware { async use(req: Request, res: Response, next: (error?: any) => void) { const authenticatedEntity = req.user as unknown as AuthenticatedEntity; const user = authenticatedEntity?.user; + if (req.session && user) { if (this.isUpdateCanBePerformed(user.lastActiveAt!)) { await this.trackAuthorizedAction(user, new Date()); diff --git a/services/workflows-service/src/common/pipes/zod.pipe.ts b/services/workflows-service/src/common/pipes/zod.pipe.ts index c13b6615c9..18dc2dfbbd 100644 --- a/services/workflows-service/src/common/pipes/zod.pipe.ts +++ b/services/workflows-service/src/common/pipes/zod.pipe.ts @@ -1,4 +1,4 @@ -import { ArgumentMetadata, BadRequestException, Injectable, PipeTransform } from '@nestjs/common'; +import { ArgumentMetadata, Injectable, PipeTransform } from '@nestjs/common'; import { ZodSchema } from 'zod'; import type { Paramtype } from '@nestjs/common/interfaces/features/paramtype.interface'; import { ValidationError } from '@/errors'; diff --git a/services/workflows-service/src/common/utils/winston-logger/winston-logger.ts b/services/workflows-service/src/common/utils/winston-logger/winston-logger.ts index bf52a86999..48e35a3817 100644 --- a/services/workflows-service/src/common/utils/winston-logger/winston-logger.ts +++ b/services/workflows-service/src/common/utils/winston-logger/winston-logger.ts @@ -17,9 +17,11 @@ export class WinstonLogger implements IAppLogger { format.printf(({ timestamp, level, message, ...metadata }) => { // eslint-disable-next-line @typescript-eslint/restrict-template-expressions let msg = `${timestamp} [${level}] : ${message} `; + if (Object.keys(metadata).length > 0) { msg += JSON.stringify(metadata, null, 2); } + return msg; }), ); diff --git a/services/workflows-service/src/customer/customer.controller.external.intg.test.ts b/services/workflows-service/src/customer/customer.controller.external.intg.test.ts index 8ff166c9bf..eca8673477 100644 --- a/services/workflows-service/src/customer/customer.controller.external.intg.test.ts +++ b/services/workflows-service/src/customer/customer.controller.external.intg.test.ts @@ -36,9 +36,7 @@ import { CustomerService } from './customer.service'; import { CustomerControllerExternal } from './customer.controller.external'; import { CustomerRepository } from './customer.repository'; import { EndUserService } from '@/end-user/end-user.service'; -import { before } from 'lodash'; import { AllExceptionsFilter } from '@/common/filters/AllExceptions.filter'; -import { string } from 'zod'; describe.skip('#CustomerControllerExternal', () => { let app: INestApplication; diff --git a/services/workflows-service/src/customer/customer.controller.external.ts b/services/workflows-service/src/customer/customer.controller.external.ts index 037aa7970a..7ae80dbb13 100644 --- a/services/workflows-service/src/customer/customer.controller.external.ts +++ b/services/workflows-service/src/customer/customer.controller.external.ts @@ -29,6 +29,7 @@ export class CustomerControllerExternal { @swagger.ApiForbiddenResponse() async create(@common.Body() customerCreateModel: CustomerCreateDto) { const { projectName, ...customer } = customerCreateModel; + if (projectName) { (customer as Prisma.CustomerCreateInput).projects = { create: { name: customerCreateModel.projectName! }, diff --git a/services/workflows-service/src/customer/customer.controller.internal.ts b/services/workflows-service/src/customer/customer.controller.internal.ts index 88ed0eebfb..40d3b2f6f4 100644 --- a/services/workflows-service/src/customer/customer.controller.internal.ts +++ b/services/workflows-service/src/customer/customer.controller.internal.ts @@ -17,6 +17,7 @@ export class CustomerControllerInternal { @swagger.ApiForbiddenResponse() async find(@ProjectIds() projectIds: TProjectIds): Promise { const projectId = projectIds?.[0]; + if (!projectId) throw new NotFoundException('Customer not found'); return this.service.getByProjectId(projectId, { diff --git a/services/workflows-service/src/customer/customer.model.ts b/services/workflows-service/src/customer/customer.model.ts index 6447c21c23..cc3d78c9cd 100644 --- a/services/workflows-service/src/customer/customer.model.ts +++ b/services/workflows-service/src/customer/customer.model.ts @@ -1,6 +1,5 @@ -import { CustomerSubscriptionSchema } from './schemas/zod-schemas'; import { ApiProperty } from '@nestjs/swagger'; -import { IsString, ValidateNested } from 'class-validator'; +import { IsString } from 'class-validator'; export class CustomerModel { @ApiProperty({ diff --git a/services/workflows-service/src/customer/customer.repository.ts b/services/workflows-service/src/customer/customer.repository.ts index b103358b54..1fd4f6f106 100644 --- a/services/workflows-service/src/customer/customer.repository.ts +++ b/services/workflows-service/src/customer/customer.repository.ts @@ -22,6 +22,7 @@ export class CustomerRepository { if (apiKey.length < 4) throw new Error('Invalid API key'); const customerApiAlreadyExists = await this.findByApiKey(apiKey); + if (customerApiAlreadyExists) throw new Error('API key already exists'); } diff --git a/services/workflows-service/src/end-user/end-user.controller.external.ts b/services/workflows-service/src/end-user/end-user.controller.external.ts index 6bc1e0f553..768412137b 100644 --- a/services/workflows-service/src/end-user/end-user.controller.external.ts +++ b/services/workflows-service/src/end-user/end-user.controller.external.ts @@ -57,6 +57,7 @@ export class EndUserControllerExternal { avatarUrl: true, }, }); + return endUser; } @@ -90,6 +91,7 @@ export class EndUserControllerExternal { @ProjectIds() projectIds: TProjectIds, ): Promise { const args = plainToClass(EndUserFindManyArgs, request.query); + return this.service.list(args, projectIds); } diff --git a/services/workflows-service/src/errors.ts b/services/workflows-service/src/errors.ts index fa35f3e03c..4da813b73e 100644 --- a/services/workflows-service/src/errors.ts +++ b/services/workflows-service/src/errors.ts @@ -38,12 +38,12 @@ export class ValidationError extends common.BadRequestException { @ApiProperty() statusCode!: number; @ApiProperty() - static message: string = 'Validation error'; + static message = 'Validation error'; @ApiProperty({ type: DetailedValidationError }) - errors!: { message: string; path: string }[]; + errors!: Array<{ message: string; path: string }>; - constructor(errors: { message: string; path: string }[]) { + constructor(errors: Array<{ message: string; path: string }>) { super( { statusCode: common.HttpStatus.BAD_REQUEST, @@ -60,7 +60,7 @@ export class ValidationError extends common.BadRequestException { return this.errors; } - static fromAjvError(error: ErrorObject, unknown>[]) { + static fromAjvError(error: Array, unknown>>) { const errors = error.map(({ instancePath, message }) => ({ message: `${startCase(lowerCase(instancePath)).replace('/', '.')} ${message}.`, path: instancePath, diff --git a/services/workflows-service/src/events/document-changed-webhook-caller.ts b/services/workflows-service/src/events/document-changed-webhook-caller.ts index 6d72667a5e..4f09071dce 100644 --- a/services/workflows-service/src/events/document-changed-webhook-caller.ts +++ b/services/workflows-service/src/events/document-changed-webhook-caller.ts @@ -75,6 +75,7 @@ export class DocumentChangedWebhookCaller { idDoc: id, }); accumulator[id] = doc; + return accumulator; }, {}); @@ -84,6 +85,7 @@ export class DocumentChangedWebhookCaller { this.logger.log('handleWorkflowEvent::anyDocumentStatusChanged::getDocumentId:: ', { idDoc: id, }); + return ( (!oldDocument.decision && newDocumentsByIdentifier[id]?.decision) || (oldDocument.decision && @@ -97,6 +99,7 @@ export class DocumentChangedWebhookCaller { this.logger.log('handleWorkflowEvent:: Skipped, ', { anyDocumentStatusChanged, }); + return; } diff --git a/services/workflows-service/src/filter/filter.controller.external.ts b/services/workflows-service/src/filter/filter.controller.external.ts index 0d98ba1a22..f83e71ce27 100644 --- a/services/workflows-service/src/filter/filter.controller.external.ts +++ b/services/workflows-service/src/filter/filter.controller.external.ts @@ -38,6 +38,7 @@ export class FilterControllerExternal { @common.Req() request: Request, ): Promise { const args = plainToClass(FilterFindManyArgs, request.query); + return this.service.list(args, projectIds); } diff --git a/services/workflows-service/src/filter/filter.controller.internal.ts b/services/workflows-service/src/filter/filter.controller.internal.ts index 9c96c9a337..14186c9390 100644 --- a/services/workflows-service/src/filter/filter.controller.internal.ts +++ b/services/workflows-service/src/filter/filter.controller.internal.ts @@ -29,6 +29,7 @@ export class FilterControllerInternal { @common.Req() request: Request, ): Promise { const args = plainToClass(FilterFindManyArgs, request.query); + return this.service.list(args, projectIds); } diff --git a/services/workflows-service/src/global.d.ts b/services/workflows-service/src/global.d.ts index ca43e76544..3110c7be6a 100644 --- a/services/workflows-service/src/global.d.ts +++ b/services/workflows-service/src/global.d.ts @@ -2,7 +2,6 @@ declare module '@prisma/client' { import type { WorkflowRuntimeData as _WorkflowRuntimeData, WorkflowDefinition as _WorkflowDefinition, - Customer as Customer_, } from '@prisma/client/index'; export * from '@prisma/client/index'; diff --git a/services/workflows-service/src/health/health.controller.base.ts b/services/workflows-service/src/health/health.controller.base.ts index 2f86cd1d5c..e386f37eef 100644 --- a/services/workflows-service/src/health/health.controller.base.ts +++ b/services/workflows-service/src/health/health.controller.base.ts @@ -11,9 +11,11 @@ export class HealthControllerBase { @Get('ready') async healthReady(@Res() response: Response): Promise> { const dbConnection = await this.healthService.isDbReady(); + if (!dbConnection) { return response.status(HttpStatus.NOT_FOUND).send(); } + return response.status(HttpStatus.NO_CONTENT).send(); } } diff --git a/services/workflows-service/src/health/health.controller.ts b/services/workflows-service/src/health/health.controller.ts index f1e6173b12..20c1243f02 100644 --- a/services/workflows-service/src/health/health.controller.ts +++ b/services/workflows-service/src/health/health.controller.ts @@ -15,9 +15,11 @@ export class HealthController { @Get(ROUTES.READY) async healthReady(@Res() response: Response): Promise> { const dbConnection = await this.healthService.isDbReady(); + if (!dbConnection) { return response.status(HttpStatus.NOT_FOUND).send(); } + return response.status(HttpStatus.NO_CONTENT).send(); } } diff --git a/services/workflows-service/src/health/health.service.ts b/services/workflows-service/src/health/health.service.ts index 357d2b6a68..f7846bea4a 100644 --- a/services/workflows-service/src/health/health.service.ts +++ b/services/workflows-service/src/health/health.service.ts @@ -7,6 +7,7 @@ export class HealthService { async isDbReady(): Promise { try { await this.prisma.$queryRaw`SELECT 1`; + return true; } catch (error) { return false; diff --git a/services/workflows-service/src/main.ts b/services/workflows-service/src/main.ts index 11dd276ff3..11c3846ee2 100644 --- a/services/workflows-service/src/main.ts +++ b/services/workflows-service/src/main.ts @@ -91,12 +91,14 @@ const main = async () => { cb(); }; } + if (req.session && !req.session.save) { // eslint-disable-next-line @typescript-eslint/ban-types req.session.save = (cb: Function) => { cb(); }; } + next(); }); @@ -108,6 +110,7 @@ const main = async () => { ) { return next(); } + req.session.nowInMinutes = Math.floor(dayjs().unix() / 60); req.session.passport.user.expires = dayjs() .add(env.SESSION_EXPIRATION_IN_MINUTES, 'minute') diff --git a/services/workflows-service/src/prisma/prisma.util.ts b/services/workflows-service/src/prisma/prisma.util.ts index a2e49344ac..eebc3190b4 100644 --- a/services/workflows-service/src/prisma/prisma.util.ts +++ b/services/workflows-service/src/prisma/prisma.util.ts @@ -21,15 +21,19 @@ export const transformStringFieldUpdateInput = async < if (typeof input === 'object' && typeof input?.set === 'string') { return { set: await transform(input.set) } as T; } + if (typeof input === 'object') { if (typeof input.set === 'string') { return { set: await transform(input.set) } as T; } + return input; } + if (typeof input === 'string') { return (await transform(input)) as T; } + return input; }; diff --git a/services/workflows-service/src/project/project-scope.service.ts b/services/workflows-service/src/project/project-scope.service.ts index 6c43096791..2a75c84c6a 100644 --- a/services/workflows-service/src/project/project-scope.service.ts +++ b/services/workflows-service/src/project/project-scope.service.ts @@ -87,6 +87,7 @@ export class ProjectScopeService { } : {}), }; + return args; } diff --git a/services/workflows-service/src/providers/file/file-provider/aws-s3-file.service.ts b/services/workflows-service/src/providers/file/file-provider/aws-s3-file.service.ts index 178f416a50..6a28bcba1c 100644 --- a/services/workflows-service/src/providers/file/file-provider/aws-s3-file.service.ts +++ b/services/workflows-service/src/providers/file/file-provider/aws-s3-file.service.ts @@ -64,6 +64,7 @@ export class AwsS3FileService implements IStreamableFileProvider { try { const headObjectCommand = new HeadObjectCommand(getObjectParams); await this.client.send(headObjectCommand); + return Promise.resolve(true); } catch (error) { if ( @@ -72,6 +73,7 @@ export class AwsS3FileService implements IStreamableFileProvider { ) { return Promise.resolve(false); } + console.error('Error checking remote file existence:', error); throw error; } diff --git a/services/workflows-service/src/providers/file/file-provider/http-file.service.ts b/services/workflows-service/src/providers/file/file-provider/http-file.service.ts index 7e9e93ac37..d5f7dd1e4f 100644 --- a/services/workflows-service/src/providers/file/file-provider/http-file.service.ts +++ b/services/workflows-service/src/providers/file/file-provider/http-file.service.ts @@ -38,6 +38,7 @@ export class HttpFileService implements IStreamableFileProvider { method: response.config.method?.toUpperCase(), // TODO: should we add also response's headers? }); + return response; }); } @@ -65,11 +66,13 @@ export class HttpFileService implements IStreamableFileProvider { const fileBuffer = response.data; await fsPromises.writeFile(localFilePath, Buffer.from(fileBuffer)); + return localFilePath; } async isRemoteExists(remoteFileConfig: TRemoteUri): Promise { const response = await this.client.head(remoteFileConfig); + return response.status >= 200 && response.status < 300; } @@ -84,6 +87,7 @@ export class HttpFileService implements IStreamableFileProvider { const response: AxiosResponse = await axios.get(remoteUri, { responseType: 'stream', }); + return response.data; } diff --git a/services/workflows-service/src/providers/file/file-provider/local-file.service.ts b/services/workflows-service/src/providers/file/file-provider/local-file.service.ts index 7cb7e2e92c..0db29db44d 100644 --- a/services/workflows-service/src/providers/file/file-provider/local-file.service.ts +++ b/services/workflows-service/src/providers/file/file-provider/local-file.service.ts @@ -72,6 +72,7 @@ export class LocalFileService implements IFileProvider { const remotePath = path.join(os.homedir(), '.ballerine', desiredPath); const destDirectory = path.dirname(remotePath); + if (!fs.existsSync(destDirectory)) { fs.mkdirSync(destDirectory, { recursive: true }); } diff --git a/services/workflows-service/src/providers/file/file.service.ts b/services/workflows-service/src/providers/file/file.service.ts index 1297f77e4c..753fee3957 100644 --- a/services/workflows-service/src/providers/file/file.service.ts +++ b/services/workflows-service/src/providers/file/file.service.ts @@ -56,6 +56,7 @@ export class FileService { mimeType, }; } + const filePaths = await this.copyThroughFileSystem( sourceServiceProvider, sourceRemoteFileConfig, diff --git a/services/workflows-service/src/serve-static-options.service.ts b/services/workflows-service/src/serve-static-options.service.ts index 58fcdfb15c..553955c5fb 100644 --- a/services/workflows-service/src/serve-static-options.service.ts +++ b/services/workflows-service/src/serve-static-options.service.ts @@ -21,9 +21,11 @@ export class ServeStaticOptionsService implements ServeStaticModuleOptionsFactor createLoggerOptions(): ServeStaticModuleOptions[] { const serveStaticRootPath = this.configService.get(SERVE_STATIC_ROOT_PATH_VAR) as string; + if (serveStaticRootPath) { const resolvedPath = path.resolve(serveStaticRootPath); this.logger.log('Serving static files', { resolvedPath }); + return [ ...DEFAULT_STATIC_MODULE_OPTIONS_LIST, { @@ -32,6 +34,7 @@ export class ServeStaticOptionsService implements ServeStaticModuleOptionsFactor }, ]; } + return DEFAULT_STATIC_MODULE_OPTIONS_LIST; } } diff --git a/services/workflows-service/src/storage/file-filter.ts b/services/workflows-service/src/storage/file-filter.ts index 7b999cf67c..d7164ee39c 100644 --- a/services/workflows-service/src/storage/file-filter.ts +++ b/services/workflows-service/src/storage/file-filter.ts @@ -12,6 +12,7 @@ export const FILE_TYPE_NOT_SUPPORTED_MSG = 'File type not supported'; export const fileFilter: MulterOptions['fileFilter'] = (req, file, callback) => { const MAX_FILE_SIZE = FILE_MAX_SIZE_IN_KB; + if (file.size >= MAX_FILE_SIZE) { return callback(new UnprocessableEntityException(FILE_SIZE_EXCEEDED_MSG), false); } @@ -19,5 +20,6 @@ export const fileFilter: MulterOptions['fileFilter'] = (req, file, callback) => if (!file.originalname.match(SUPPORTED_FILE_EXT_REGEX)) { return callback(new UnprocessableEntityException(FILE_TYPE_NOT_SUPPORTED_MSG), false); } + callback(null, true); }; diff --git a/services/workflows-service/src/storage/get-file-storage-manager.ts b/services/workflows-service/src/storage/get-file-storage-manager.ts index 6f036488f9..67db1a1057 100644 --- a/services/workflows-service/src/storage/get-file-storage-manager.ts +++ b/services/workflows-service/src/storage/get-file-storage-manager.ts @@ -137,5 +137,6 @@ const decodeFromBase64 = (encodedPrivateKey?: string): string | undefined => { if (!encodedPrivateKey) { return; } + return Buffer.from(encodedPrivateKey, 'base64').toString('utf-8'); }; diff --git a/services/workflows-service/src/storage/storage.controller.external.ts b/services/workflows-service/src/storage/storage.controller.external.ts index 4c3bab03ab..56626752bd 100644 --- a/services/workflows-service/src/storage/storage.controller.external.ts +++ b/services/workflows-service/src/storage/storage.controller.external.ts @@ -122,10 +122,13 @@ export class StorageControllerExternal { if (!persistedFile) { throw new errors.NotFoundException('file not found'); } + let customer; + if (projectIds?.[0]) { customer = await this.customerService.getByProjectId(projectIds?.[0]); } + if (persistedFile.fileNameInBucket) { const localFilePath = await downloadFileFromS3( AwsS3FileConfig.getBucketName(process.env) as string, @@ -135,6 +138,7 @@ export class StorageControllerExternal { return res.sendFile(localFilePath, { root: '/' }); } else { const root = path.parse(os.homedir()).root; + return res.sendFile(persistedFile.fileNameOnDisk, { root: root }); } } diff --git a/services/workflows-service/src/storage/storage.controller.internal.ts b/services/workflows-service/src/storage/storage.controller.internal.ts index c99d72cabe..a342c2a6b8 100644 --- a/services/workflows-service/src/storage/storage.controller.internal.ts +++ b/services/workflows-service/src/storage/storage.controller.internal.ts @@ -131,6 +131,7 @@ export class StorageControllerInternal { fileNameInBucket: persistedFile.fileNameInBucket, mimeType, }); + return res.json({ signedUrl, mimeType }); } @@ -158,6 +159,7 @@ export class StorageControllerInternal { if (!path.isAbsolute(filePath)) return filePath; const rootDir = path.parse(os.homedir()).root; + return path.join(rootDir, filePath); } diff --git a/services/workflows-service/src/storage/storage.repository.ts b/services/workflows-service/src/storage/storage.repository.ts index e87cf3b3ee..6d8d6ec849 100644 --- a/services/workflows-service/src/storage/storage.repository.ts +++ b/services/workflows-service/src/storage/storage.repository.ts @@ -31,6 +31,7 @@ export class FileRepository { projectIds: TProjectIds, ): Promise { const { where, ...restArgs } = args; + return await this.prisma.file.findFirst( this.scopeService.scopeFindFirst( { diff --git a/services/workflows-service/src/test/helpers/database-helper.ts b/services/workflows-service/src/test/helpers/database-helper.ts index 3725699763..d7c8f96176 100644 --- a/services/workflows-service/src/test/helpers/database-helper.ts +++ b/services/workflows-service/src/test/helpers/database-helper.ts @@ -1,5 +1,6 @@ import { PrismaClient } from '@prisma/client'; import { z } from 'zod'; + const databaseHelper = new PrismaClient(); // should never be unset - default test in order not to delete default db const TEST_DATABASE_SCHEMA_NAME = z @@ -12,6 +13,7 @@ const __getTables = async (prisma: PrismaClient): Promise => { tablename: string; }> = await prisma.$queryRaw`SELECT tablename from pg_tables where schemaname = '${TEST_DATABASE_SCHEMA_NAME}';`; + return results.map(result => result.tablename); }; diff --git a/services/workflows-service/src/user/user-data.decorator.ts b/services/workflows-service/src/user/user-data.decorator.ts index 70d407481b..55ad0d18bf 100644 --- a/services/workflows-service/src/user/user-data.decorator.ts +++ b/services/workflows-service/src/user/user-data.decorator.ts @@ -6,9 +6,11 @@ import { User } from '@prisma/client'; */ const userFactory = (ctx: ExecutionContext): User & { projectIds: string[] } => { const contextType = ctx.getType(); + if (contextType === 'http') { // do something that is only important in the context of regular HTTP requests (REST) const { user } = ctx.switchToHttp().getRequest<{ user: User & { projectIds: string[] } }>(); + return user; } else if (contextType === 'rpc') { // do something that is only important in the context of Microservice requests diff --git a/services/workflows-service/src/workflow-defintion/workflow-definition.repository.ts b/services/workflows-service/src/workflow-defintion/workflow-definition.repository.ts index 8979398f41..acbdcf1de7 100644 --- a/services/workflows-service/src/workflow-defintion/workflow-definition.repository.ts +++ b/services/workflows-service/src/workflow-defintion/workflow-definition.repository.ts @@ -25,6 +25,7 @@ export class WorkflowDefinitionRepository { args: Prisma.SelectSubset, ): Promise { validateDefinitionLogic(args.data); + return await this.prisma.workflowDefinition.create(args); } @@ -73,6 +74,7 @@ export class WorkflowDefinitionRepository { }, ], }; + return await transaction.workflowDefinition.findFirstOrThrow(queryArgs); } diff --git a/services/workflows-service/src/workflow-defintion/workflow-definition.service.ts b/services/workflows-service/src/workflow-defintion/workflow-definition.service.ts index 22dbfe1da5..b90645b804 100644 --- a/services/workflows-service/src/workflow-defintion/workflow-definition.service.ts +++ b/services/workflows-service/src/workflow-defintion/workflow-definition.service.ts @@ -49,6 +49,7 @@ export class WorkflowDefinitionService { const { where: whereQuery } = filter.query as { where: { workflowDefinitionId: string | { in: string[] } }; }; + if (typeof whereQuery.workflowDefinitionId === 'string') { return whereQuery.workflowDefinitionId === id; } diff --git a/services/workflows-service/src/workflow/hook-callback-handler.service.ts b/services/workflows-service/src/workflow/hook-callback-handler.service.ts index ede2b1ebe7..2c85516685 100644 --- a/services/workflows-service/src/workflow/hook-callback-handler.service.ts +++ b/services/workflows-service/src/workflow/hook-callback-handler.service.ts @@ -129,6 +129,7 @@ export class HookCallbackHandlerService { private formatDecision(data: AnyRecord) { const insights = data.insights as AnyRecord[]; // Explicitly type 'insights' as 'AnyRecord[]' + return { status: data.decision, decisionReason: data.reason, @@ -186,6 +187,7 @@ export class HookCallbackHandlerService { // name: kycDocument['issuedBy'], city: (kycDocument['placeOfIssue'] as any)?.value, }; + return issuer; } @@ -225,6 +227,7 @@ export class HookCallbackHandlerService { validUntil: (kycDocument['validUntil'] as any)?.value, firstIssue: (kycDocument['firstIssue'] as any)?.value, }; + return properties; } diff --git a/services/workflows-service/src/workflow/types/params.ts b/services/workflows-service/src/workflow/types/params.ts index ce16e7ad97..e75b27cc61 100644 --- a/services/workflows-service/src/workflow/types/params.ts +++ b/services/workflows-service/src/workflow/types/params.ts @@ -1,5 +1,3 @@ -import type { TProjectIds } from '@/types'; - export interface FindLastActiveFlowParams { workflowDefinitionId: string; businessId: string; diff --git a/services/workflows-service/src/workflow/workflow-event-emitter.service.ts b/services/workflows-service/src/workflow/workflow-event-emitter.service.ts index b095d8f7af..e44a16b727 100644 --- a/services/workflows-service/src/workflow/workflow-event-emitter.service.ts +++ b/services/workflows-service/src/workflow/workflow-event-emitter.service.ts @@ -17,6 +17,7 @@ export class WorkflowEventEmitterService { config?: EventConfig, ) { config = { ...DEFAULT_CONFIG, ...(config || {}) }; + if (!eventName) { throw new Error('Event name is required'); } diff --git a/services/workflows-service/src/workflow/workflow.controller.external.ts b/services/workflows-service/src/workflow/workflow.controller.external.ts index 85d2a8a111..b2c7ad602c 100644 --- a/services/workflows-service/src/workflow/workflow.controller.external.ts +++ b/services/workflows-service/src/workflow/workflow.controller.external.ts @@ -96,6 +96,7 @@ export class WorkflowControllerExternal { {}, projectIds, ); + if (!workflowRuntimeData) { throw new NotFoundException(`No resource with id [${params.id}] was found`); } @@ -129,6 +130,7 @@ export class WorkflowControllerExternal { if (isRecordNotFoundError(error)) { throw new errors.NotFoundException(`No resource was found for ${JSON.stringify(params)}`); } + throw error; } } @@ -340,6 +342,7 @@ export class WorkflowControllerExternal { if (isRecordNotFoundError(error)) { throw new errors.NotFoundException(`No resource was found for ${JSON.stringify(params)}`); } + throw error; } diff --git a/services/workflows-service/src/workflow/workflow.controller.internal.ts b/services/workflows-service/src/workflow/workflow.controller.internal.ts index 93f535162b..e0e4b876a4 100644 --- a/services/workflows-service/src/workflow/workflow.controller.internal.ts +++ b/services/workflows-service/src/workflow/workflow.controller.internal.ts @@ -130,6 +130,7 @@ export class WorkflowControllerInternal { if (isRecordNotFoundError(error)) { throw new errors.NotFoundException(`No resource was found`); } + throw error; } } @@ -176,6 +177,7 @@ export class WorkflowControllerInternal { if (isRecordNotFoundError(error)) { throw new errors.NotFoundException(`No resource was found for ${JSON.stringify(params)}`); } + throw error; } } @@ -197,6 +199,7 @@ export class WorkflowControllerInternal { if (isRecordNotFoundError(error)) { throw new errors.NotFoundException(`No resource was found for ${JSON.stringify(params)}`); } + throw error; } } @@ -236,6 +239,7 @@ export class WorkflowControllerInternal { if (data.systemEventName !== 'workflow.context.changed') { throw new common.BadRequestException(`Invalid system event name: ${data.systemEventName}`); } + return await this.service.emitSystemWorkflowEvent({ workflowRuntimeId: params.id, projectId: data.projectId, @@ -274,6 +278,7 @@ export class WorkflowControllerInternal { if (isRecordNotFoundError(error)) { throw new errors.NotFoundException(`No resource was found for ${JSON.stringify(params)}`); } + throw error; } } @@ -299,6 +304,7 @@ export class WorkflowControllerInternal { if (isRecordNotFoundError(error)) { throw new errors.NotFoundException(`No resource was found for ${JSON.stringify(params)}`); } + throw error; } } @@ -340,6 +346,7 @@ export class WorkflowControllerInternal { if (isRecordNotFoundError(error)) { throw new errors.NotFoundException(`No resource was found for ${JSON.stringify(params)}`); } + throw error; } } diff --git a/services/workflows-service/src/workflow/workflow.service.ts b/services/workflows-service/src/workflow/workflow.service.ts index 6e08debead..028faaf4ec 100644 --- a/services/workflows-service/src/workflow/workflow.service.ts +++ b/services/workflows-service/src/workflow/workflow.service.ts @@ -56,8 +56,6 @@ import { } from '@nestjs/common'; import { ApprovalState, - Business, - EndUser, Prisma, PrismaClient, UiDefinitionContext, @@ -269,6 +267,7 @@ export class WorkflowService { }; let nextEvents; + if (addNextEvents) { const service = createWorkflow({ runtimeId: workflow.id, @@ -650,6 +649,7 @@ export class WorkflowService { persistStates: true, submitStates: true, }; + return await this.workflowDefinitionRepository.findMany({ ...args, select }, projectIds); } @@ -1089,6 +1089,7 @@ export class WorkflowService { ); let contextHasChanged; + if (data.context) { data.context.documents = assignIdToDocuments(data.context.documents); contextHasChanged = !isEqual(data.context, runtimeData.context); @@ -1246,6 +1247,7 @@ export class WorkflowService { projectIds: TProjectIds, ) { let correlationId: string; + if (runtimeData.businessId) { correlationId = (await this.businessRepository.getCorrelationIdById( runtimeData.businessId, @@ -1261,6 +1263,7 @@ export class WorkflowService { console.error('No entity Id found'); // throw new Error('No entity Id found'); } + return correlationId; } @@ -1720,6 +1723,7 @@ export class WorkflowService { project: { connect: { id: projectId } }, } as Prisma.EndUserCreateInput, }); + return id; } @@ -1757,6 +1761,7 @@ export class WorkflowService { {}, projectIds, ); + return res && res.id; } else { const res = await this.endUserRepository.findByCorrelationId( @@ -1764,6 +1769,7 @@ export class WorkflowService { {}, projectIds, ); + return res && res.id; } } @@ -2079,6 +2085,7 @@ export class WorkflowService { projectId: parentWorkflowRuntime.projectId, }); } + contextToPersist[childWorkflow.id] = { entityId: childWorkflow.context.entity.id, status: childWorkflow.status, @@ -2100,6 +2107,7 @@ export class WorkflowService { private initiateTransformer(transformer: SerializableTransformer): Transformer { if (transformer.transformer === 'jmespath') return new JmespathTransformer(transformer.mapping as string); + if (transformer.transformer === 'helper') return new HelpersTransformer(transformer.mapping as THelperFormatingLogic); @@ -2115,6 +2123,7 @@ export class WorkflowService { parentWorkflowContext['childWorkflows'][definitionId] ||= {}; parentWorkflowContext['childWorkflows'][definitionId] = contextToPersist; + return parentWorkflowContext; } diff --git a/services/workflows-service/src/workflow/workflow.service.unit.test.ts b/services/workflows-service/src/workflow/workflow.service.unit.test.ts index 50398331f9..a38ecc52ec 100644 --- a/services/workflows-service/src/workflow/workflow.service.unit.test.ts +++ b/services/workflows-service/src/workflow/workflow.service.unit.test.ts @@ -4,7 +4,6 @@ import { DocumentChangedWebhookCaller } from '../events/document-changed-webhook import { Test, TestingModule } from '@nestjs/testing'; import { commonTestingModules } from '@/test/helpers/nest-app-helper'; import { AppLoggerService } from '@/common/app-logger/app-logger.service'; -import packageJson from '../../package.json'; import { ConfigService } from '@nestjs/config'; class FakeWorkflowRuntimeDataRepo extends BaseFakeRepository { @@ -146,6 +145,7 @@ describe('WorkflowService', () => { axiosRef: { post: async (url, data, config) => { fakeHttpService.requests.push({ url, data }); + return { status: 200, data: { success: true },