diff --git a/apps/agent-service/src/agent-service.service.ts b/apps/agent-service/src/agent-service.service.ts index 3f501e280..7cca98a34 100644 --- a/apps/agent-service/src/agent-service.service.ts +++ b/apps/agent-service/src/agent-service.service.ts @@ -935,6 +935,14 @@ export class AgentServiceService { async createDid(createDidPayload: IDidCreate, orgId: string, user: IUserRequestInterface): Promise { try { const agentDetails = await this.agentServiceRepository.getOrgAgentDetails(orgId); + + if (createDidPayload?.network) { + const getNameSpace = await this.agentServiceRepository.getLedgerByNameSpace(createDidPayload?.network); + if (agentDetails.ledgerId !== getNameSpace.id) { + throw new BadRequestException(ResponseMessages.agent.error.networkMismatch); + } + } + const getApiKey = await this.getOrgAgentApiKey(orgId); const getOrgAgentType = await this.agentServiceRepository.getOrgAgentType(agentDetails?.orgAgentTypeId); @@ -1045,6 +1053,12 @@ export class AgentServiceService { if (network) { const getLedgerDetails = await this.agentServiceRepository.getLedgerByNameSpace(network); await this.agentServiceRepository.updateLedgerId(orgId, getLedgerDetails.id); + } else { + const noLedgerData = await this.agentServiceRepository.getLedger(Ledgers.Not_Applicable); + if (!noLedgerData) { + throw new NotFoundException(ResponseMessages.agent.error.noLedgerFound); + } + await this.agentServiceRepository.updateLedgerId(orgId, noLedgerData?.id); } } diff --git a/apps/agent-service/src/interface/agent-service.interface.ts b/apps/agent-service/src/interface/agent-service.interface.ts index fed4a1471..f8a1726ba 100644 --- a/apps/agent-service/src/interface/agent-service.interface.ts +++ b/apps/agent-service/src/interface/agent-service.interface.ts @@ -636,4 +636,19 @@ export interface OrgDid { did: string; didDocument: Prisma.JsonValue; orgAgentId: string; +} + +export interface ILedgers { + id: string; + createDateTime: Date; + lastChangedDateTime: Date; + name: string; + networkType: string; + poolConfig: string; + isActive: boolean; + networkString: string; + nymTxnEndpoint: string; + indyNamespace: string; + networkUrl: string; + } \ No newline at end of file diff --git a/apps/agent-service/src/repositories/agent-service.repository.ts b/apps/agent-service/src/repositories/agent-service.repository.ts index 4e1a5faf6..852099aff 100644 --- a/apps/agent-service/src/repositories/agent-service.repository.ts +++ b/apps/agent-service/src/repositories/agent-service.repository.ts @@ -2,7 +2,7 @@ import { PrismaService } from '@credebl/prisma-service'; import { Injectable, Logger } from '@nestjs/common'; // eslint-disable-next-line camelcase import { Prisma, ledgerConfig, ledgers, org_agents, org_agents_type, org_dids, organisation, platform_config, user } from '@prisma/client'; -import { ICreateOrgAgent, IOrgAgent, IOrgAgentsResponse, IOrgLedgers, IStoreAgent, IStoreDidDetails, IStoreOrgAgentDetails, LedgerNameSpace, OrgDid } from '../interface/agent-service.interface'; +import { ICreateOrgAgent, ILedgers, IOrgAgent, IOrgAgentsResponse, IOrgLedgers, IStoreAgent, IStoreDidDetails, IStoreOrgAgentDetails, LedgerNameSpace, OrgDid } from '../interface/agent-service.interface'; import { AgentType } from '@credebl/enum/enum'; @Injectable() @@ -509,4 +509,18 @@ export class AgentServiceRepository { } } + async getLedger(name: string): Promise { + try { + const ledgerData = await this.prisma.ledgers.findFirstOrThrow({ + where: { + name + } + }); + return ledgerData; + } catch (error) { + this.logger.error(`[getLedger] - get org ledger: ${JSON.stringify(error)}`); + throw error; + } + } + } \ No newline at end of file diff --git a/apps/organization/interfaces/organization.interface.ts b/apps/organization/interfaces/organization.interface.ts index 3441a8898..34ed2daea 100644 --- a/apps/organization/interfaces/organization.interface.ts +++ b/apps/organization/interfaces/organization.interface.ts @@ -173,7 +173,8 @@ export interface IDidDetails { } export interface IPrimaryDidDetails extends IPrimaryDid { - id: string, + id: string + networkId: string didDocument: Prisma.JsonValue } @@ -190,3 +191,45 @@ export interface OrgInvitation { orgRoles: string[]; email: string; } + +export interface ILedgerNameSpace { + id: string; + createDateTime: Date; + lastChangedDateTime: Date; + name: string; + networkType: string; + poolConfig: string; + isActive: boolean; + networkString: string; + nymTxnEndpoint: string; + indyNamespace: string; + networkUrl: string; +} + +export interface IGetDids { + id: string; + createDateTime: Date; + createdBy: string; + lastChangedDateTime: Date; + lastChangedBy: string; + orgId: string; + isPrimaryDid: boolean; + did: string; + didDocument: Prisma.JsonValue; + orgAgentId: string; +} + +export interface ILedgerDetails { + id: string; + createDateTime: Date; + lastChangedDateTime: Date; + name: string; + networkType: string; + poolConfig: string; + isActive: boolean; + networkString: string; + nymTxnEndpoint: string; + indyNamespace: string; + networkUrl: string; + +} \ No newline at end of file diff --git a/apps/organization/repositories/organization.repository.ts b/apps/organization/repositories/organization.repository.ts index 43ebb9401..ee2f050cd 100644 --- a/apps/organization/repositories/organization.repository.ts +++ b/apps/organization/repositories/organization.repository.ts @@ -6,7 +6,7 @@ import { ConflictException, Injectable, Logger, NotFoundException } from '@nestj import { Prisma, agent_invitations, org_agents, org_invitations, user, user_org_roles } from '@prisma/client'; import { CreateOrganizationDto } from '../dtos/create-organization.dto'; -import { IDidDetails, IDidList, IGetOrgById, IGetOrganization, IPrimaryDidDetails, IUpdateOrganization, OrgInvitation } from '../interfaces/organization.interface'; +import { IGetDids, IDidDetails, IDidList, IGetOrgById, IGetOrganization, IPrimaryDidDetails, IUpdateOrganization, ILedgerNameSpace, OrgInvitation, ILedgerDetails } from '../interfaces/organization.interface'; import { InternalServerErrorException } from '@nestjs/common'; import { Invitation, SortValue } from '@credebl/enum/enum'; import { PrismaService } from '@credebl/prisma-service'; @@ -864,7 +864,7 @@ export class OrganizationRepository { async setOrgsPrimaryDid(primaryDidDetails: IPrimaryDidDetails): Promise { try { - const {did, didDocument, id, orgId} = primaryDidDetails; + const {did, didDocument, id, orgId, networkId} = primaryDidDetails; await this.prisma.$transaction([ this.prisma.org_dids.update({ where: { @@ -880,7 +880,8 @@ export class OrganizationRepository { }, data: { orgDid: did, - didDocument + didDocument, + ledgerId: networkId } }) ]); @@ -918,6 +919,19 @@ async getDidDetailsByDid(did:string): Promise { } } + async getDids(orgId:string): Promise { + try { + return this.prisma.org_dids.findMany({ + where: { + orgId + } + }); + } catch (error) { + this.logger.error(`[getDids] - get all DIDs: ${JSON.stringify(error)}`); + throw error; + } + } + async setPreviousDidFlase(id:string): Promise { try { return this.prisma.org_dids.update({ @@ -946,4 +960,31 @@ async getDidDetailsByDid(did:string): Promise { throw error; } } + + async getNetworkByNameSpace(nameSpace: string): Promise { + try { + return this.prisma.ledgers.findFirstOrThrow({ + where: { + indyNamespace: nameSpace + } + }); + } catch (error) { + this.logger.error(`[getNetworkByIndyNameSpace] - get network by namespace: ${JSON.stringify(error)}`); + throw error; + } + } + + async getLedger(name: string): Promise { + try { + const ledgerData = await this.prisma.ledgers.findFirstOrThrow({ + where: { + name + } + }); + return ledgerData; + } catch (error) { + this.logger.error(`[getLedger] - get ledger details: ${JSON.stringify(error)}`); + throw error; + } +} } diff --git a/apps/organization/src/organization.service.ts b/apps/organization/src/organization.service.ts index 6023b8eee..653b4beb6 100644 --- a/apps/organization/src/organization.service.ts +++ b/apps/organization/src/organization.service.ts @@ -26,7 +26,7 @@ import { sendEmail } from '@credebl/common/send-grid-helper-file'; import { CreateOrganizationDto } from '../dtos/create-organization.dto'; import { BulkSendInvitationDto } from '../dtos/send-invitation.dto'; import { UpdateInvitationDto } from '../dtos/update-invitation.dt'; -import { Invitation, transition } from '@credebl/enum/enum'; +import { DidMethod, Invitation, Ledgers, transition } from '@credebl/enum/enum'; import { IGetOrgById, IGetOrganization, IUpdateOrganization, IOrgAgent, IClientCredentials, ICreateConnectionUrl, IOrgRole, IDidList, IPrimaryDidDetails } from '../interfaces/organization.interface'; import { UserActivityService } from '@credebl/user-activity'; import { ClientRegistrationService } from '@credebl/client-registration/client-registration.service'; @@ -200,25 +200,55 @@ export class OrganizationService { if (!didDetails) { throw new NotFoundException(ResponseMessages.organisation.error.didNotFound); } + + const dids = await this.organizationRepository.getDids(orgId); + const noPrimaryDid = dids.every(orgDids => false === orgDids.isPrimaryDid); + + let existingPrimaryDid; + let priviousDidFalse; + if (!noPrimaryDid) { + existingPrimaryDid = await this.organizationRepository.getPerviousPrimaryDid(orgId); + + if (!existingPrimaryDid) { + throw new NotFoundException(ResponseMessages.organisation.error.didNotFound); + } + + priviousDidFalse = await this.organizationRepository.setPreviousDidFlase(existingPrimaryDid.id); + } + + const didParts = did.split(':'); + let nameSpace: string | null = null; + + // This condition will handle the multi-ledger support + if (DidMethod.INDY === didParts[1]) { + nameSpace = `${didParts[2]}:${didParts[3]}`; + } else if (DidMethod.POLYGON === didParts[1]) { + nameSpace = `${didParts[1]}:${didParts[2]}`; + } else { + nameSpace = null; + } + + let network; + if (null !== nameSpace) { + network = await this.organizationRepository.getNetworkByNameSpace(nameSpace); + } else { + network = await this.organizationRepository.getLedger(Ledgers.Not_Applicable); + if (!network) { + throw new NotFoundException(ResponseMessages.agent.error.noLedgerFound); + } + } + const primaryDidDetails: IPrimaryDidDetails = { did, orgId, id, - didDocument: didDetails.didDocument + didDocument: didDetails.didDocument, + networkId: network?.id ?? null }; - - const getExistingPrimaryDid = await this.organizationRepository.getPerviousPrimaryDid(orgId); - - if (!getExistingPrimaryDid) { - throw new NotFoundException(ResponseMessages.organisation.error.didNotFound); - } - - const setPriviousDidFalse = await this.organizationRepository.setPreviousDidFlase(getExistingPrimaryDid.id); - const setPrimaryDid = await this.organizationRepository.setOrgsPrimaryDid(primaryDidDetails); - await Promise.all([setPrimaryDid, getExistingPrimaryDid, setPriviousDidFalse]); + await Promise.all([setPrimaryDid, existingPrimaryDid, priviousDidFalse]); return ResponseMessages.organisation.success.primaryDid; diff --git a/libs/common/src/response-messages/index.ts b/libs/common/src/response-messages/index.ts index 9a8f692c4..659e76432 100644 --- a/libs/common/src/response-messages/index.ts +++ b/libs/common/src/response-messages/index.ts @@ -246,8 +246,10 @@ export const ResponseMessages = { invalidTenantIdIdFormat:'Invalid tenantId format', requiredTenantId:'Tenant Id is required', createDid:'Error while creating DID', + networkMismatch:'The network is mismatched.', didAlreadyExist:'DID already exist', storeDid: 'Error while storing DID', + noLedgerFound: 'No ledger data not found.', agentSpinupError: 'Agent endpoint unreachable', agentEndpointRequired: 'Agent endpoint is required', failedAgentType: 'Agent endpoint is required', diff --git a/libs/enum/src/enum.ts b/libs/enum/src/enum.ts index 29e7ffb93..6452092e0 100644 --- a/libs/enum/src/enum.ts +++ b/libs/enum/src/enum.ts @@ -50,6 +50,7 @@ export enum Ledgers { Indicio_Testnet = 'Indicio Testnet', Indicio_Demonet = 'Indicio Demonet', Indicio_Mainnet = 'Indicio Mainnet', + Not_Applicable = 'NA' } export enum Invitation { diff --git a/libs/prisma-service/prisma/data/credebl-master-table.json b/libs/prisma-service/prisma/data/credebl-master-table.json index 37b4fc6b5..17cb6bb79 100644 --- a/libs/prisma-service/prisma/data/credebl-master-table.json +++ b/libs/prisma-service/prisma/data/credebl-master-table.json @@ -134,6 +134,15 @@ "networkString": "testnet", "nymTxnEndpoint": "", "indyNamespace": "polygon:testnet" + }, + { + "name": "NA", + "networkType": "", + "poolConfig": "", + "isActive": true, + "networkString": "", + "nymTxnEndpoint": "", + "indyNamespace": "" } ], "endorseData": [