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 5f73fff10..a44697187 100644 --- a/apps/ecosystem/src/ecosystem.repository.ts +++ b/apps/ecosystem/src/ecosystem.repository.ts @@ -111,6 +111,23 @@ export class EcosystemRepository { async getAllEcosystemDetails(): Promise { try { const ecosystemDetails = await this.prisma.ecosystem.findMany({ + where: { + ecosystemOrgs: { + some: { + orgId + } + } + }, + include: { + ecosystemOrgs: { + where: { + orgId + }, + include: { + ecosystemRole: true + } + } + } }); return ecosystemDetails; } catch (error) { @@ -188,11 +205,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( { @@ -201,24 +218,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); @@ -407,7 +424,7 @@ export class EcosystemRepository { }, include: { ecosystem: true, - ecosystemRole:true + ecosystemRole: true }, take: pageSize, skip: (pageNumber - 1) * pageSize, @@ -598,6 +615,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 @@ -665,7 +702,7 @@ export class EcosystemRepository { throw error; } } - + // eslint-disable-next-line camelcase async saveCredDef(credDefResult: saveCredDef): Promise { try { @@ -704,35 +741,35 @@ export class EcosystemRepository { async updateEndorsementRequestStatus(ecosystemId: 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.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.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 7cd8d1ac9..23fe01057 100644 --- a/apps/ecosystem/src/ecosystem.service.ts +++ b/apps/ecosystem/src/ecosystem.service.ts @@ -51,14 +51,53 @@ export class EcosystemService { */ // eslint-disable-next-line camelcase - async getAllEcosystem(): Promise { - const getAllEcosystemDetails = await this.ecosystemRepository.getAllEcosystemDetails(); + async getAllEcosystem(payload: { orgId: string }): Promise { + const getAllEcosystemDetails = await this.ecosystemRepository.getAllEcosystemDetails(payload.orgId); + if (!getAllEcosystemDetails) { throw new NotFoundException(ResponseMessages.ecosystem.error.update); } return getAllEcosystemDetails; } + /** + * + * + * @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); + } + } + + /** + * Description: get an ecosystem invitation + * @returns Get sent ecosystem invitation details + */ + + // eslint-disable-next-line camelcase + async getEcosystemInvitations(userEmail: string, status: string, pageNumber: number, pageSize: number, search: string): Promise { + + try { + const query = { + AND: [ + { email: userEmail }, + { status: { contains: search, mode: 'insensitive' } } + ] + }; + + return await this.ecosystemRepository.getEcosystemInvitationsPagination(query, pageNumber, pageSize); + } catch (error) { + this.logger.error(`In error getEcosystemInvitations: ${JSON.stringify(error)}`); + throw new InternalServerErrorException(error); + } + } + + /** * * @param bulkInvitationDto @@ -101,7 +140,7 @@ export class EcosystemService { */ async acceptRejectEcosystemInvitations(acceptRejectInvitation: AcceptRejectEcosystemInvitationDto): Promise { try { - + const { orgId, status, invitationId, orgName, orgDid } = acceptRejectInvitation; const invitation = await this.ecosystemRepository.getEcosystemInvitationById(invitationId); @@ -230,7 +269,12 @@ 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) { throw new InternalServerErrorException(ResponseMessages.ecosystem.error.notFound); @@ -284,6 +328,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); @@ -327,7 +378,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)}`); @@ -502,7 +554,9 @@ export class EcosystemService { payload.credentialDefinition = { tag: parsedRequestPayload.operation.tag, issuerId: ecosystemMemberDetails.orgDid, - schemaId: parsedRequestPayload.operation.schemaId + schemaId: endorsementTransactionPayload.requestBody['schemaId'], + type: endorsementTransactionPayload.requestBody['type'], + value: endorsementTransactionPayload.requestBody['value'] }; } // Need to add valid schema Id @@ -511,7 +565,56 @@ export class EcosystemService { if (!submitTransactionRequest) { throw new InternalServerErrorException(ResponseMessages.ecosystem.error.sumbitTransaction); } - return this.ecosystemRepository.updateTransactionStatus(endorsementId, endorsementTransactionStatus.SUBMITED); + + await this.ecosystemRepository.updateTransactionStatus(endorsementId, endorsementTransactionStatus.SUBMITED); + if (endorsementTransactionPayload.type === endorsementTransactionType.SCHEMA) { + + const regex = /[^:]+$/; + const match = ecosystemMemberDetails.orgDid.match(regex); + let extractedDidValue; + + if (match) { + // eslint-disable-next-line prefer-destructuring + extractedDidValue = match[0]; + + } + const saveSchemaPayload: SaveSchema = { + name: endorsementTransactionPayload.requestBody['name'], + version: endorsementTransactionPayload.requestBody['version'], + attributes: JSON.stringify(endorsementTransactionPayload.requestBody['attributes']), + schemaLedgerId: submitTransactionRequest['message'].schemaId, + issuerId: ecosystemMemberDetails.orgDid, + createdBy: endorsementTransactionPayload.ecosystemOrgs.orgId, + lastChangedBy: endorsementTransactionPayload.ecosystemOrgs.orgId, + publisherDid: extractedDidValue, + orgId: endorsementTransactionPayload.ecosystemOrgs.orgId, + ledgerId: ecosystemMemberDetails.ledgerId + }; + const saveSchemaDetails = await this.ecosystemRepository.saveSchema(saveSchemaPayload); + if (!saveSchemaDetails) { + throw new InternalServerErrorException(ResponseMessages.ecosystem.error.saveSchema); + } + 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'], + tag: endorsementTransactionPayload.requestBody['tag'], + credentialDefinitionId: submitTransactionRequest['message'].credentialDefinitionId, + revocable: false, + createdBy: endorsementTransactionPayload.ecosystemOrgs.orgId, + orgId: ecosystemMemberDetails.orgId, + schemaId: schemaDetails.id + }; + + const saveCredDefDetails = await this.ecosystemRepository.saveCredDef(saveCredentialDefinition); + if (!saveCredDefDetails) { + throw new InternalServerErrorException(ResponseMessages.ecosystem.error.saveCredDef); + } + return saveCredDefDetails; + } + } catch (error) { this.logger.error(`In sumit transaction : ${JSON.stringify(error)}`); @@ -645,12 +748,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; } @@ -663,13 +766,13 @@ 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): Promise { try { diff --git a/libs/common/src/response-messages/index.ts b/libs/common/src/response-messages/index.ts index c26b31d42..f5e1db29d 100644 --- a/libs/common/src/response-messages/index.ts +++ b/libs/common/src/response-messages/index.ts @@ -196,7 +196,24 @@ export const ResponseMessages = { invalidInvitationStatus: 'Invalid invitation status', invitationNotFound: 'Ecosystem Invitation not found', invitationNotUpdate: 'Ecosystem Invitation not updated', - orgsNotUpdate: 'Ecosystem Orgs not updated' + orgsNotUpdate: 'Ecosystem Orgs not updated', + ecosystemNotEnabled: 'Ecosystem service is not enabled', + sumbitTransaction: 'Error while submitting transaction', + requestSchemaTransaction: 'Error while request schema transaction', + 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', + invalidEcosystemId: 'Invalid ecosystem Id', + invalidTransaction: 'Transaction does not exist', + transactionSubmitted: 'Transaction already submitted', + invalidAgentUrl: 'Invalid agent url', + EndorsementTransactionNotFoundException:'Endorsement transaction with status requested not found', + OrgOrEcosystemNotFoundExceptionForEndorsementTransaction:'Cannot update endorsement transaction status as OrgId and EcosystemId is not present in ecosystemOrg' } }