From 11d007cd9358d0172362712eaa7df12f946922a9 Mon Sep 17 00:00:00 2001 From: KulkarniShashank Date: Thu, 12 Oct 2023 17:56:37 +0530 Subject: [PATCH 1/2] fix: Added validation for the schema and cred-def request creation Signed-off-by: KulkarniShashank --- .../src/ecosystem/ecosystem.controller.ts | 32 ++--- .../interfaces/ecosystem.interfaces.ts | 3 + apps/ecosystem/src/ecosystem.repository.ts | 110 +++++++++++------- apps/ecosystem/src/ecosystem.service.ts | 65 +++++++---- libs/common/src/response-messages/index.ts | 2 + 5 files changed, 127 insertions(+), 85 deletions(-) diff --git a/apps/api-gateway/src/ecosystem/ecosystem.controller.ts b/apps/api-gateway/src/ecosystem/ecosystem.controller.ts index 2ef578338..24c7c48a6 100644 --- a/apps/api-gateway/src/ecosystem/ecosystem.controller.ts +++ b/apps/api-gateway/src/ecosystem/ecosystem.controller.ts @@ -273,10 +273,10 @@ export class EcosystemController { @Post('/:ecosystemId/:orgId/transaction/schema') @ApiOperation({ summary: 'Request new schema', description: 'Request new schema' }) @ApiResponse({ status: 201, description: 'Success', type: ApiResponseDto }) - @UseGuards(AuthGuard('jwt'), EcosystemRolesGuard, OrgRolesGuard) - @ApiBearerAuth() - @EcosystemsRoles(EcosystemRoles.ECOSYSTEM_MEMBER) - @Roles(OrgRoles.OWNER, OrgRoles.ADMIN, OrgRoles.ISSUER) + // @UseGuards(AuthGuard('jwt'), EcosystemRolesGuard, OrgRolesGuard) + // @ApiBearerAuth() + // @EcosystemsRoles(EcosystemRoles.ECOSYSTEM_MEMBER) + // @Roles(OrgRoles.OWNER, OrgRoles.ADMIN, OrgRoles.ISSUER) async requestSchemaTransaction(@Body() requestSchemaPayload: RequestSchemaDto, @Param('orgId') orgId: number, @Param('ecosystemId') ecosystemId: string, @Res() res: Response): Promise { await this.ecosystemService.schemaEndorsementRequest(requestSchemaPayload, orgId, ecosystemId); const finalResponse: IResponseType = { @@ -290,10 +290,10 @@ export class EcosystemController { @Post('/:ecosystemId/:orgId/transaction/cred-def') @ApiOperation({ summary: 'Request new credential-definition', description: 'Request new credential-definition' }) @ApiResponse({ status: 201, description: 'Success', type: ApiResponseDto }) - @UseGuards(AuthGuard('jwt'), EcosystemRolesGuard, OrgRolesGuard) - @ApiBearerAuth() - @EcosystemsRoles(EcosystemRoles.ECOSYSTEM_MEMBER) - @Roles(OrgRoles.OWNER, OrgRoles.ADMIN, OrgRoles.ISSUER) + // @UseGuards(AuthGuard('jwt'), EcosystemRolesGuard, OrgRolesGuard) + // @ApiBearerAuth() + // @EcosystemsRoles(EcosystemRoles.ECOSYSTEM_MEMBER) + // @Roles(OrgRoles.OWNER, OrgRoles.ADMIN, OrgRoles.ISSUER) async requestCredDefTransaction(@Body() requestCredDefPayload: RequestCredDefDto, @Param('orgId') orgId: number, @Param('ecosystemId') ecosystemId: string, @Res() res: Response): Promise { await this.ecosystemService.credDefEndorsementRequest(requestCredDefPayload, orgId, ecosystemId); const finalResponse: IResponseType = { @@ -306,10 +306,10 @@ export class EcosystemController { @Post('/:ecosystemId/:orgId/transaction/sign/:endorsementId') @ApiOperation({ summary: 'Sign transaction', description: 'Sign transaction' }) @ApiResponse({ status: 201, description: 'Success', type: ApiResponseDto }) - @UseGuards(AuthGuard('jwt'), EcosystemRolesGuard, OrgRolesGuard) - @ApiBearerAuth() - @EcosystemsRoles(EcosystemRoles.ECOSYSTEM_LEAD) - @Roles(OrgRoles.OWNER, OrgRoles.ADMIN) + // @UseGuards(AuthGuard('jwt'), EcosystemRolesGuard, OrgRolesGuard) + // @ApiBearerAuth() + // @EcosystemsRoles(EcosystemRoles.ECOSYSTEM_LEAD) + // @Roles(OrgRoles.OWNER, OrgRoles.ADMIN) async SignEndorsementRequests(@Param('endorsementId') endorsementId: string, @Param('ecosystemId') ecosystemId: string, @Param('orgId') orgId: number, @Res() res: Response): Promise { await this.ecosystemService.signTransaction(endorsementId, ecosystemId); const finalResponse: IResponseType = { @@ -322,10 +322,10 @@ export class EcosystemController { @Post('/:ecosystemId/:orgId/transaction/sumbit/:endorsementId') @ApiOperation({ summary: 'Sumbit transaction', description: 'Sumbit transaction' }) @ApiResponse({ status: 201, description: 'Success', type: ApiResponseDto }) - @UseGuards(AuthGuard('jwt'), EcosystemRolesGuard, OrgRolesGuard) - @ApiBearerAuth() - @EcosystemsRoles(EcosystemRoles.ECOSYSTEM_MEMBER) - @Roles(OrgRoles.OWNER, OrgRoles.ADMIN, OrgRoles.ISSUER) + // @UseGuards(AuthGuard('jwt'), EcosystemRolesGuard, OrgRolesGuard) + // @ApiBearerAuth() + // @EcosystemsRoles(EcosystemRoles.ECOSYSTEM_MEMBER) + // @Roles(OrgRoles.OWNER, OrgRoles.ADMIN, OrgRoles.ISSUER) async SumbitEndorsementRequests(@Param('endorsementId') endorsementId: string, @Param('ecosystemId') ecosystemId: string, @Param('orgId') orgId: number, @Res() res: Response): Promise { await this.ecosystemService.submitTransaction(endorsementId, ecosystemId); const finalResponse: IResponseType = { diff --git a/apps/ecosystem/interfaces/ecosystem.interfaces.ts b/apps/ecosystem/interfaces/ecosystem.interfaces.ts index 50040f120..0fc061f0a 100644 --- a/apps/ecosystem/interfaces/ecosystem.interfaces.ts +++ b/apps/ecosystem/interfaces/ecosystem.interfaces.ts @@ -66,6 +66,7 @@ export interface CredDefMessage { schemaId: string; schema: Record; credentialDefinitionRequest: string; + credentialDefinition: Record; }; registrationMetadata: Record; schemaMetadata: Record; @@ -116,6 +117,8 @@ interface CredentialDefinitionPayload { tag: string; issuerId: string; schemaId: string; + type: string; + value: Record; } export interface submitTransactionPayload { diff --git a/apps/ecosystem/src/ecosystem.repository.ts b/apps/ecosystem/src/ecosystem.repository.ts index 796d4a234..3808c7e34 100644 --- a/apps/ecosystem/src/ecosystem.repository.ts +++ b/apps/ecosystem/src/ecosystem.repository.ts @@ -108,19 +108,19 @@ export class EcosystemRepository { const ecosystemDetails = await this.prisma.ecosystem.findMany({ where: { ecosystemOrgs: { - some: { - orgId - } + some: { + orgId + } } }, - include:{ + include: { ecosystemOrgs: { - where: { - orgId - }, - include:{ - ecosystemRole: true - } + where: { + orgId + }, + include: { + ecosystemRole: true + } } } }); @@ -165,11 +165,11 @@ export class EcosystemRepository { } catch (error) { this.logger.error(`error: ${JSON.stringify(error)}`); throw new InternalServerErrorException(error); - } + } } - async getEcosystemMembersCount (ecosystemId: string): Promise { + async getEcosystemMembersCount(ecosystemId: string): Promise { try { const membersCount = await this.prisma.ecosystem_orgs.count( { @@ -178,24 +178,24 @@ export class EcosystemRepository { } } ); - return membersCount; + return membersCount; } catch (error) { this.logger.error(`error: ${JSON.stringify(error)}`); throw new InternalServerErrorException(error); } } - async getEcosystemEndorsementsCount (ecosystemId: string): Promise { + async getEcosystemEndorsementsCount(ecosystemId: string): Promise { try { const endorsementsCount = await this.prisma.endorsement_transaction.count({ where: { ecosystemOrgs: { ecosystemId - + } } }); - return endorsementsCount; + return endorsementsCount; } catch (error) { this.logger.error(`error: ${JSON.stringify(error)}`); throw new InternalServerErrorException(error); @@ -661,6 +661,26 @@ export class EcosystemRepository { } } + // eslint-disable-next-line camelcase + async findRecordsByNameAndVersion(name: string, version: string): Promise { + try { + return this.prisma.$queryRaw`SELECT * FROM endorsement_transaction WHERE "requestBody"->>'name' = ${name} AND "requestBody"->>'version' = ${version}`; + } catch (error) { + this.logger.error(`Error in getting ecosystem schema: ${error.message} `); + throw error; + } + } + + // eslint-disable-next-line camelcase + async findRecordsByCredDefTag(tag: string): Promise { + try { + return this.prisma.$queryRaw`SELECT * FROM endorsement_transaction WHERE "requestBody"->>'tag' = ${tag}`; + } catch (error) { + this.logger.error(`Error in getting ecosystem credential-definition: ${error.message} `); + throw error; + } + } + async updateTransactionDetails( endorsementId: string, schemaTransactionRequest: string @@ -767,35 +787,35 @@ export class EcosystemRepository { async updateEndorsementRequestStatus(ecosystemId: string, orgId: string, endorsementId: string): Promise { try { - - const endorsementTransaction = await this.prisma.endorsement_transaction.findUnique({ - where: { id: endorsementId, status: endorsementTransactionStatus.REQUESTED } - }); - - if (!endorsementTransaction) { - throw new NotFoundException(ResponseMessages.ecosystem.error.EndorsementTransactionNotFoundException); - } - const { ecosystemOrgId } = endorsementTransaction; - - const endorsementTransactionEcosystemOrg = await this.prisma.ecosystem_orgs.findUnique({ - where: { id: ecosystemOrgId } - }); - - if (endorsementTransactionEcosystemOrg.orgId === orgId && endorsementTransactionEcosystemOrg.ecosystemId === ecosystemId) { - const updatedEndorsementTransaction = await this.prisma.endorsement_transaction.update({ - where: { id: endorsementId }, - data: { - status: endorsementTransactionStatus.DECLINED - } - }); - - return updatedEndorsementTransaction; - } else { - throw new NotFoundException(ResponseMessages.ecosystem.error.OrgOrEcosystemNotFoundExceptionForEndorsementTransaction); - } + + const endorsementTransaction = await this.prisma.endorsement_transaction.findUnique({ + where: { id: endorsementId, status: endorsementTransactionStatus.REQUESTED } + }); + + if (!endorsementTransaction) { + throw new NotFoundException(ResponseMessages.ecosystem.error.EndorsementTransactionNotFoundException); + } + const { ecosystemOrgId } = endorsementTransaction; + + const endorsementTransactionEcosystemOrg = await this.prisma.ecosystem_orgs.findUnique({ + where: { id: ecosystemOrgId } + }); + + if (endorsementTransactionEcosystemOrg.orgId === orgId && endorsementTransactionEcosystemOrg.ecosystemId === ecosystemId) { + const updatedEndorsementTransaction = await this.prisma.endorsement_transaction.update({ + where: { id: endorsementId }, + data: { + status: endorsementTransactionStatus.DECLINED + } + }); + + return updatedEndorsementTransaction; + } else { + throw new NotFoundException(ResponseMessages.ecosystem.error.OrgOrEcosystemNotFoundExceptionForEndorsementTransaction); + } } catch (error) { - this.logger.error(`Error in updating endorsement transaction status: ${error.message}`); - throw error; - } + this.logger.error(`Error in updating endorsement transaction status: ${error.message}`); + throw error; } + } } diff --git a/apps/ecosystem/src/ecosystem.service.ts b/apps/ecosystem/src/ecosystem.service.ts index 2608ed291..a9c2d4212 100644 --- a/apps/ecosystem/src/ecosystem.service.ts +++ b/apps/ecosystem/src/ecosystem.service.ts @@ -69,8 +69,8 @@ export class EcosystemService { // eslint-disable-next-line camelcase async getAllEcosystem(payload: { orgId: string }): Promise { - const getAllEcosystemDetails = await this.ecosystemRepository.getAllEcosystemDetails(payload.orgId); - + const getAllEcosystemDetails = await this.ecosystemRepository.getAllEcosystemDetails(payload.orgId); + if (!getAllEcosystemDetails) { throw new NotFoundException(ResponseMessages.ecosystem.error.update); } @@ -82,15 +82,15 @@ export class EcosystemService { * * @returns ecosystem dashboard details */ - async getEcosystemDashboardDetails(ecosystemId: string): Promise { - try { - return await this.ecosystemRepository.getEcosystemDashboardDetails(ecosystemId); - } catch (error) { - this.logger.error(`In ecosystem dashboard details : ${JSON.stringify(error)}`); - throw new RpcException(error.response ? error.response : error); - } + async getEcosystemDashboardDetails(ecosystemId: string): Promise { + try { + return await this.ecosystemRepository.getEcosystemDashboardDetails(ecosystemId); + } catch (error) { + this.logger.error(`In ecosystem dashboard details : ${JSON.stringify(error)}`); + throw new RpcException(error.response ? error.response : error); } - + } + /** * Description: get an ecosystem invitation * @returns Get sent ecosystem invitation details @@ -157,7 +157,7 @@ export class EcosystemService { */ async acceptRejectEcosystemInvitations(acceptRejectInvitation: AcceptRejectEcosystemInvitationDto): Promise { try { - + const { orgId, status, invitationId, orgName, orgDid } = acceptRejectInvitation; const invitation = await this.ecosystemRepository.getEcosystemInvitationById(invitationId); @@ -286,6 +286,11 @@ export class EcosystemService { */ async requestSchemaEndorsement(requestSchemaPayload: RequestSchemaEndorsement, orgId: number, ecosystemId: string): Promise { try { + const schemaRequestExist = await this.ecosystemRepository.findRecordsByNameAndVersion(requestSchemaPayload?.name, requestSchemaPayload?.version); + + if (0 !== schemaRequestExist.length) { + throw new ConflictException(ResponseMessages.ecosystem.error.schemaAlreadyExist); + } const ecosystemMemberDetails = await this.ecosystemRepository.getAgentDetails(orgId); if (!ecosystemMemberDetails) { @@ -340,6 +345,13 @@ export class EcosystemService { async requestCredDeffEndorsement(requestCredDefPayload: RequestCredDeffEndorsement, orgId: number, ecosystemId: string): Promise { try { + + const credDefRequestExist = await this.ecosystemRepository.findRecordsByCredDefTag(requestCredDefPayload?.tag); + + if (0 !== credDefRequestExist.length) { + throw new ConflictException(ResponseMessages.ecosystem.error.credDefAlreadyExist); + } + const ecosystemMemberDetails = await this.ecosystemRepository.getAgentDetails(orgId); if (!ecosystemMemberDetails) { throw new InternalServerErrorException(ResponseMessages.ecosystem.error.notFound); @@ -383,7 +395,8 @@ export class EcosystemService { throw new InternalServerErrorException(ResponseMessages.ecosystem.error.requestCredDefTransaction); } - return this.ecosystemRepository.storeTransactionRequest(schemaTransactionResponse, requestCredDefPayload, endorsementTransactionType.CREDENTIAL_DEFINITION); + const requestBody = credDefTransactionRequest.message.credentialDefinitionState.credentialDefinition; + return this.ecosystemRepository.storeTransactionRequest(schemaTransactionResponse, requestBody, endorsementTransactionType.CREDENTIAL_DEFINITION); } catch (error) { this.logger.error(`In request cred-def endorsement : ${JSON.stringify(error)}`); @@ -562,7 +575,9 @@ export class EcosystemService { payload.credentialDefinition = { tag: parsedRequestPayload.operation.tag, issuerId: ecosystemMemberDetails.orgDid, - schemaId: endorsementTransactionPayload.requestBody['schemaId'] + schemaId: endorsementTransactionPayload.requestBody['schemaId'], + type: endorsementTransactionPayload.requestBody['type'], + value: endorsementTransactionPayload.requestBody['value'] }; } @@ -602,6 +617,7 @@ export class EcosystemService { } return saveSchemaDetails; } else if (endorsementTransactionPayload.type === endorsementTransactionType.CREDENTIAL_DEFINITION) { + const schemaDetails = await this.ecosystemRepository.getSchemaDetailsById(endorsementTransactionPayload.requestBody['schemaId']); const saveCredentialDefinition: saveCredDef = { schemaLedgerId: endorsementTransactionPayload.requestBody['schemaId'], @@ -612,6 +628,7 @@ export class EcosystemService { orgId: ecosystemMemberDetails.orgId, schemaId: schemaDetails.id }; + const saveCredDefDetails = await this.ecosystemRepository.saveCredDef(saveCredentialDefinition); if (!saveCredDefDetails) { throw new InternalServerErrorException(ResponseMessages.ecosystem.error.saveCredDef); @@ -741,12 +758,12 @@ export class EcosystemService { ] }; - const ecosystemOrgData = await this.ecosystemRepository.fetchEcosystemOrg(queryEcoOrgs); + const ecosystemOrgData = await this.ecosystemRepository.fetchEcosystemOrg(queryEcoOrgs); if (ecosystemOrgData['ecosystemRole']['name'] !== EcosystemRoles.ECOSYSTEM_LEAD) { query.ecosystemOrgs['orgId'] = orgId; } - + if (type) { query['type'] = type; } @@ -759,19 +776,19 @@ export class EcosystemService { } - /** - * - * @param ecosystemId - * @param endorsementId - * @param orgId - * @returns EndorsementTransactionRequest Status message - */ + /** + * + * @param ecosystemId + * @param endorsementId + * @param orgId + * @returns EndorsementTransactionRequest Status message + */ - async declineEndorsementRequestByLead(ecosystemId:string, endorsementId:string, orgId:string): Promise { + async declineEndorsementRequestByLead(ecosystemId: string, endorsementId: string, orgId: string): Promise { try { return await this.ecosystemRepository.updateEndorsementRequestStatus(ecosystemId, orgId, endorsementId); - } catch (error) { + } catch (error) { this.logger.error(`error in decline endorsement request: ${error}`); throw new InternalServerErrorException(error); } diff --git a/libs/common/src/response-messages/index.ts b/libs/common/src/response-messages/index.ts index 18564fbaa..001d51bdf 100644 --- a/libs/common/src/response-messages/index.ts +++ b/libs/common/src/response-messages/index.ts @@ -214,6 +214,8 @@ export const ResponseMessages = { requestCredDefTransaction: 'Error while submitting transaction', notFound: 'Organization not found', leadNotFound: 'Lead details not found', + schemaAlreadyExist: 'Schema name and schema version already exist', + credDefAlreadyExist: 'Credential definition already exist', saveSchema: 'Error while storing the schema details', saveCredDef: 'Error while storing the credential-definition details', invalidOrgId: 'Invalid organization Id', From 0eb300448c16753e3ea5e3097f92a33056d29788 Mon Sep 17 00:00:00 2001 From: KulkarniShashank Date: Thu, 12 Oct 2023 18:37:51 +0530 Subject: [PATCH 2/2] Remove commented code Signed-off-by: KulkarniShashank --- .../src/ecosystem/ecosystem.controller.ts | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/apps/api-gateway/src/ecosystem/ecosystem.controller.ts b/apps/api-gateway/src/ecosystem/ecosystem.controller.ts index 24c7c48a6..2ef578338 100644 --- a/apps/api-gateway/src/ecosystem/ecosystem.controller.ts +++ b/apps/api-gateway/src/ecosystem/ecosystem.controller.ts @@ -273,10 +273,10 @@ export class EcosystemController { @Post('/:ecosystemId/:orgId/transaction/schema') @ApiOperation({ summary: 'Request new schema', description: 'Request new schema' }) @ApiResponse({ status: 201, description: 'Success', type: ApiResponseDto }) - // @UseGuards(AuthGuard('jwt'), EcosystemRolesGuard, OrgRolesGuard) - // @ApiBearerAuth() - // @EcosystemsRoles(EcosystemRoles.ECOSYSTEM_MEMBER) - // @Roles(OrgRoles.OWNER, OrgRoles.ADMIN, OrgRoles.ISSUER) + @UseGuards(AuthGuard('jwt'), EcosystemRolesGuard, OrgRolesGuard) + @ApiBearerAuth() + @EcosystemsRoles(EcosystemRoles.ECOSYSTEM_MEMBER) + @Roles(OrgRoles.OWNER, OrgRoles.ADMIN, OrgRoles.ISSUER) async requestSchemaTransaction(@Body() requestSchemaPayload: RequestSchemaDto, @Param('orgId') orgId: number, @Param('ecosystemId') ecosystemId: string, @Res() res: Response): Promise { await this.ecosystemService.schemaEndorsementRequest(requestSchemaPayload, orgId, ecosystemId); const finalResponse: IResponseType = { @@ -290,10 +290,10 @@ export class EcosystemController { @Post('/:ecosystemId/:orgId/transaction/cred-def') @ApiOperation({ summary: 'Request new credential-definition', description: 'Request new credential-definition' }) @ApiResponse({ status: 201, description: 'Success', type: ApiResponseDto }) - // @UseGuards(AuthGuard('jwt'), EcosystemRolesGuard, OrgRolesGuard) - // @ApiBearerAuth() - // @EcosystemsRoles(EcosystemRoles.ECOSYSTEM_MEMBER) - // @Roles(OrgRoles.OWNER, OrgRoles.ADMIN, OrgRoles.ISSUER) + @UseGuards(AuthGuard('jwt'), EcosystemRolesGuard, OrgRolesGuard) + @ApiBearerAuth() + @EcosystemsRoles(EcosystemRoles.ECOSYSTEM_MEMBER) + @Roles(OrgRoles.OWNER, OrgRoles.ADMIN, OrgRoles.ISSUER) async requestCredDefTransaction(@Body() requestCredDefPayload: RequestCredDefDto, @Param('orgId') orgId: number, @Param('ecosystemId') ecosystemId: string, @Res() res: Response): Promise { await this.ecosystemService.credDefEndorsementRequest(requestCredDefPayload, orgId, ecosystemId); const finalResponse: IResponseType = { @@ -306,10 +306,10 @@ export class EcosystemController { @Post('/:ecosystemId/:orgId/transaction/sign/:endorsementId') @ApiOperation({ summary: 'Sign transaction', description: 'Sign transaction' }) @ApiResponse({ status: 201, description: 'Success', type: ApiResponseDto }) - // @UseGuards(AuthGuard('jwt'), EcosystemRolesGuard, OrgRolesGuard) - // @ApiBearerAuth() - // @EcosystemsRoles(EcosystemRoles.ECOSYSTEM_LEAD) - // @Roles(OrgRoles.OWNER, OrgRoles.ADMIN) + @UseGuards(AuthGuard('jwt'), EcosystemRolesGuard, OrgRolesGuard) + @ApiBearerAuth() + @EcosystemsRoles(EcosystemRoles.ECOSYSTEM_LEAD) + @Roles(OrgRoles.OWNER, OrgRoles.ADMIN) async SignEndorsementRequests(@Param('endorsementId') endorsementId: string, @Param('ecosystemId') ecosystemId: string, @Param('orgId') orgId: number, @Res() res: Response): Promise { await this.ecosystemService.signTransaction(endorsementId, ecosystemId); const finalResponse: IResponseType = { @@ -322,10 +322,10 @@ export class EcosystemController { @Post('/:ecosystemId/:orgId/transaction/sumbit/:endorsementId') @ApiOperation({ summary: 'Sumbit transaction', description: 'Sumbit transaction' }) @ApiResponse({ status: 201, description: 'Success', type: ApiResponseDto }) - // @UseGuards(AuthGuard('jwt'), EcosystemRolesGuard, OrgRolesGuard) - // @ApiBearerAuth() - // @EcosystemsRoles(EcosystemRoles.ECOSYSTEM_MEMBER) - // @Roles(OrgRoles.OWNER, OrgRoles.ADMIN, OrgRoles.ISSUER) + @UseGuards(AuthGuard('jwt'), EcosystemRolesGuard, OrgRolesGuard) + @ApiBearerAuth() + @EcosystemsRoles(EcosystemRoles.ECOSYSTEM_MEMBER) + @Roles(OrgRoles.OWNER, OrgRoles.ADMIN, OrgRoles.ISSUER) async SumbitEndorsementRequests(@Param('endorsementId') endorsementId: string, @Param('ecosystemId') ecosystemId: string, @Param('orgId') orgId: number, @Res() res: Response): Promise { await this.ecosystemService.submitTransaction(endorsementId, ecosystemId); const finalResponse: IResponseType = {