diff --git a/apps/agent-service/src/agent-service.controller.ts b/apps/agent-service/src/agent-service.controller.ts index 88d9a4668..a92ae251d 100644 --- a/apps/agent-service/src/agent-service.controller.ts +++ b/apps/agent-service/src/agent-service.controller.ts @@ -1,28 +1,7 @@ import { Controller } from '@nestjs/common'; import { MessagePattern } from '@nestjs/microservices'; import { AgentServiceService } from './agent-service.service'; -import { - IAgentStatus, - IConnectionDetails, - IUserRequestInterface, - ISendProofRequestPayload, - IAgentSpinUpSatus, - IGetCredDefAgentRedirection, - IGetSchemaAgentRedirection, - IAgentSpinupDto, - IIssuanceCreateOffer, - ITenantCredDef, - ITenantDto, - ITenantSchema, - IOutOfBandCredentialOffer, - IAgentProofRequest, - IDidCreate, - IWallet, - ITenantRecord, - ICreateConnectionInvitation, - IStoreAgent, - IAgentConfigure -} from './interface/agent-service.interface'; +import { IAgentStatus, IConnectionDetails, IUserRequestInterface, ISendProofRequestPayload, IAgentSpinUpSatus, IGetCredDefAgentRedirection, IGetSchemaAgentRedirection, IAgentSpinupDto, IIssuanceCreateOffer, ITenantCredDef, ITenantDto, ITenantSchema, IOutOfBandCredentialOffer, IProofPresentation, IAgentProofRequest, IPresentation, IDidCreate, IWallet, ITenantRecord } from './interface/agent-service.interface'; import { user } from '@prisma/client'; import { InvitationMessage } from '@credebl/common/interfaces/agent-service.interface'; import { AgentSpinUpStatus } from '@credebl/enum/enum'; @@ -61,7 +40,7 @@ export class AgentServiceController { } @MessagePattern({ cmd: 'create-wallet' }) - async createWallet(payload: { createWalletDto: IWallet, user: IUserRequestInterface }): Promise { + async createWallet(payload: { createWalletDto: IWallet, user: IUserRequestInterface}): Promise { return this.agentServiceService.createWallet(payload.createWalletDto); } @@ -269,29 +248,9 @@ export class AgentServiceController { } @MessagePattern({ cmd: 'polygon-create-keys' }) - async createSecp256k1KeyPair(payload: { orgId: string }): Promise { + async createSecp256k1KeyPair(payload: {orgId: string}): Promise { return this.agentServiceService.createSecp256k1KeyPair(payload.orgId); } - @MessagePattern({ cmd: 'agent-create-connection-invitation' }) - async createConnectionInvitation(payload: { - url: string, - orgId: string, - connectionPayload: ICreateConnectionInvitation, - }): Promise { - return this.agentServiceService.createConnectionInvitation(payload.url, payload.orgId, payload.connectionPayload); - } - - /** - * Configure the agent by organization - * @param payload - * @returns Get agent status - */ - @MessagePattern({ cmd: 'agent-configure' }) - async agentConfigure(payload: { - agentConfigureDto: IAgentConfigure, - user: IUserRequestInterface, - }): Promise { - return this.agentServiceService.agentConfigure(payload.agentConfigureDto, payload.user); - } } + diff --git a/apps/agent-service/src/agent-service.service.ts b/apps/agent-service/src/agent-service.service.ts index 39125221b..c914ada75 100644 --- a/apps/agent-service/src/agent-service.service.ts +++ b/apps/agent-service/src/agent-service.service.ts @@ -19,40 +19,7 @@ import * as dotenv from 'dotenv'; import * as fs from 'fs'; import { map } from 'rxjs/operators'; dotenv.config(); -import { - IGetCredDefAgentRedirection, - IConnectionDetails, - IUserRequestInterface, - IAgentSpinupDto, - IStoreOrgAgentDetails, - ITenantCredDef, - ITenantDto, - ITenantSchema, - IWalletProvision, - ISendProofRequestPayload, - IIssuanceCreateOffer, - IOutOfBandCredentialOffer, - IAgentSpinUpSatus, - ICreateTenant, - IAgentStatus, - ICreateOrgAgent, - IOrgAgentsResponse, - IProofPresentation, - IAgentProofRequest, - IPresentation, - IReceiveInvitationUrl, - IReceiveInvitation, - IQuestionPayload, - IDidCreate, - IWallet, - ITenantRecord, - LedgerListResponse, - ICreateConnectionInvitation, - IStoreAgent, - AgentHealthData, - IAgentStore, - IAgentConfigure -} from './interface/agent-service.interface'; +import { IGetCredDefAgentRedirection, IConnectionDetails, IUserRequestInterface, IAgentSpinupDto, IStoreOrgAgentDetails, ITenantCredDef, ITenantDto, ITenantSchema, IWalletProvision, ISendProofRequestPayload, IIssuanceCreateOffer, IOutOfBandCredentialOffer, IAgentSpinUpSatus, ICreateTenant, IAgentStatus, ICreateOrgAgent, IOrgAgentsResponse, IProofPresentation, IAgentProofRequest, IPresentation, IReceiveInvitationUrl, IReceiveInvitation, IQuestionPayload, IDidCreate, IWallet, ITenantRecord, IPlatformAgent, LedgerListResponse, IOrgLedgers, IStoreOrgAgent } from './interface/agent-service.interface'; import { AgentSpinUpStatus, AgentType, DidMethod, Ledgers, OrgAgentType } from '@credebl/enum/enum'; import { AgentServiceRepository } from './repositories/agent-service.repository'; import { ledgers, org_agents, organisation, platform_config } from '@prisma/client'; @@ -72,6 +39,7 @@ import { ledgerName } from '@credebl/common/cast.helper'; import { InvitationMessage } from '@credebl/common/interfaces/agent-service.interface'; import * as CryptoJS from 'crypto-js'; + @Injectable() @WebSocketGateway() export class AgentServiceService { @@ -124,7 +92,7 @@ export class AgentServiceService { agentSpinupDto.network ? agentSpinupDto.network : [Ledgers.Indicio_Demonet] ) ]); - + let orgData; if (!user?.userId && agentSpinupDto?.platformAdminEmail) { // Get Platform admin user by platform admin email @@ -166,10 +134,10 @@ export class AgentServiceService { } if (AgentSpinUpStatus.COMPLETED === getOrgAgent?.agentSpinUpStatus) { - throw new ConflictException(ResponseMessages.agent.error.walletAlreadyCreated, { - cause: new Error(), - description: ResponseMessages.errorMessages.conflict - }); + throw new ConflictException( + ResponseMessages.agent.error.walletAlreadyCreated, + { cause: new Error(), description: ResponseMessages.errorMessages.conflict } + ); } if (!agentSpinupDto.orgId) { @@ -180,9 +148,7 @@ export class AgentServiceService { agentSpinupDto.agentType = agentSpinupDto.agentType || getAgentType; agentSpinupDto.tenant = agentSpinupDto.tenant || false; - agentSpinupDto.ledgerName = agentSpinupDto.ledgerName?.length - ? agentSpinupDto.ledgerName - : [Ledgers.Indicio_Demonet]; + agentSpinupDto.ledgerName = agentSpinupDto.ledgerName?.length ? agentSpinupDto.ledgerName : [Ledgers.Indicio_Demonet]; // Invoke function for validate platform configuration this.validatePlatformConfig(platformConfig); @@ -456,33 +422,25 @@ export class AgentServiceService { } } - async _agentSpinup( - walletProvisionPayload: IWalletProvision, - agentSpinupDto: IAgentSpinupDto, - orgApiKey: string, - orgData: organisation, - user: IUserRequestInterface, - socket: Socket, - ledgerId: string[], - agentProcess: ICreateOrgAgent - ): Promise { + async _agentSpinup(walletProvisionPayload: IWalletProvision, agentSpinupDto: IAgentSpinupDto, orgApiKey: string, orgData: organisation, user: IUserRequestInterface, socket: Socket, ledgerId: string[], agentProcess: ICreateOrgAgent): Promise { let ledgerIdData = []; try { if (agentSpinupDto.method !== DidMethod.KEY && agentSpinupDto.method !== DidMethod.WEB) { - const { network } = agentSpinupDto; - const ledger = await ledgerName(network); - const ledgerList = (await this._getALlLedgerDetails()) as unknown as LedgerListResponse; - const isLedgerExist = ledgerList.response.find((existingLedgers) => existingLedgers.name === ledger); - if (!isLedgerExist) { - throw new BadRequestException(ResponseMessages.agent.error.invalidLedger, { - cause: new Error(), - description: ResponseMessages.errorMessages.notFound - }); - } - ledgerIdData = await this.agentServiceRepository.getLedgerDetails(ledger); + const { network } = agentSpinupDto; + const ledger = await ledgerName(network); + const ledgerList = await this._getALlLedgerDetails() as unknown as LedgerListResponse; + const isLedgerExist = ledgerList.response.find((existingLedgers) => existingLedgers.name === ledger); + if (!isLedgerExist) { + throw new BadRequestException( + ResponseMessages.agent.error.invalidLedger, + { cause: new Error(), description: ResponseMessages.errorMessages.notFound } + ); } + + ledgerIdData = await this.agentServiceRepository.getLedgerDetails(ledger); + } /** * Invoke wallet create and provision with agent */ @@ -521,7 +479,7 @@ export class AgentServiceService { role: agentSpinupDto.role, network: agentSpinupDto.network, keyType: agentSpinupDto.keyType, - ledgerId: ledgerIdData ? ledgerIdData.map((item) => item.id) : null, + ledgerId: ledgerIdData ? ledgerIdData.map(item => item.id) : null, did: agentSpinupDto.did, id: agentProcess?.id }; @@ -550,7 +508,7 @@ export class AgentServiceService { const getOrganization = await this.agentServiceRepository.getOrgDetails(orgData?.id); - await this._createConnectionInvitation(orgData?.id, user, getOrganization.name); + await this._createLegacyConnectionInvitation(orgData?.id, user, getOrganization.name); if (agentSpinupDto.clientSocketId) { socket.emit('invitation-url-creation-success', { clientId: agentSpinupDto.clientSocketId }); } @@ -605,28 +563,19 @@ export class AgentServiceService { } private async _getAgentDid(payload: IStoreOrgAgentDetails): Promise { - const { agentEndPoint, apiKey, ledgerId, seed, keyType, method, network, role, did } = payload; + const { agentEndPoint, apiKey, ledgerId, seed, keyType, method, network, role, did } = payload; const writeDid = 'write-did'; const ledgerDetails = await this.agentServiceRepository.getGenesisUrl(ledgerId); const agentDidWriteUrl = `${agentEndPoint}${CommonConstants.URL_AGENT_WRITE_DID}`; return this._retryAgentSpinup(agentDidWriteUrl, apiKey, writeDid, seed, keyType, method, network, role, did); + } private async _getDidMethod(payload: IStoreOrgAgentDetails, agentDid: object): Promise { - const { agentEndPoint, apiKey, seed, keyType, method, network, role } = payload; + const { agentEndPoint, apiKey, seed, keyType, method, network, role } = payload; const getDidDoc = 'get-did-doc'; const getDidMethodUrl = `${agentEndPoint}${CommonConstants.URL_AGENT_GET_DID}/${agentDid['did']}`; - return this._retryAgentSpinup( - getDidMethodUrl, - apiKey, - getDidDoc, - seed, - keyType, - method, - network, - role, - `${agentDid['did']}` - ); + return this._retryAgentSpinup(getDidMethodUrl, apiKey, getDidDoc, seed, keyType, method, network, role, `${agentDid['did']}`); } private _buildStoreOrgAgentData( @@ -663,23 +612,15 @@ export class AgentServiceService { } if (payload && payload?.id) { + this.agentServiceRepository.removeOrgAgent(payload?.id); } this.logger.error(`[_storeOrgAgentDetails] - Error in store agent details : ${JSON.stringify(error)}`); } - async _retryAgentSpinup( - agentUrl: string, - apiKey: string, - agentApiState: string, - seed: string, - keyType: string, - method: string, - network: string, - role: string, - did: string - ): Promise { + + async _retryAgentSpinup(agentUrl: string, apiKey: string, agentApiState: string, seed: string, keyType: string, method: string, network: string, role: string, did: string): Promise { const retryOptions = { retries: 10 }; @@ -687,15 +628,12 @@ export class AgentServiceService { const getDcryptedToken = await this.commonService.decryptPassword(apiKey); return retry(async () => { if (agentApiState === 'write-did') { - return this.commonService.httpPost( - agentUrl, - { seed, keyType, method, network, role, did }, - { headers: { authorization: getDcryptedToken } } - ); + return this.commonService.httpPost(agentUrl, { seed, keyType, method, network, role, did}, { headers: { 'authorization': apiKey } }); } else if (agentApiState === 'get-did-doc') { return this.commonService.httpGet(agentUrl, { headers: { authorization: getDcryptedToken } }); } }, retryOptions); + } catch (error) { throw error; } @@ -727,7 +665,22 @@ export class AgentServiceService { cmd: 'get-all-ledgers' }; const payload = {}; - return await this.natsCall(pattern, payload); + return this.agentServiceProxy + .send(pattern, payload) + .pipe( + map((response) => ( + { + response + })) + ).toPromise() + .catch(error => { + this.logger.error(`catch: ${JSON.stringify(error)}`); + throw new HttpException( + { + status: error.statusCode, + error: error.message + }, error.error); + }); } catch (error) { this.logger.error(`error in while fetching all the ledger details : ${JSON.stringify(error)}`); } @@ -792,104 +745,185 @@ export class AgentServiceService { * @param user * @returns Get agent status */ - async _createTenant(payload: ITenantDto, user: IUserRequestInterface): Promise { - let agentProcess; - let ledgerIdData = []; - try { - if (payload.method !== DidMethod.KEY && payload.method !== DidMethod.WEB) { - const { network } = payload; - const ledger = await ledgerName(network); - const ledgerList = (await this._getALlLedgerDetails()) as unknown as LedgerListResponse; - const isLedgerExist = ledgerList.response.find((existingLedgers) => existingLedgers.name === ledger); - if (!isLedgerExist) { - throw new BadRequestException(ResponseMessages.agent.error.invalidLedger, { - cause: new Error(), - description: ResponseMessages.errorMessages.notFound - }); + async _createTenant(payload: ITenantDto, user: IUserRequestInterface): Promise { + let agentProcess; + let ledgerIdData = []; + try { + if (payload.method !== DidMethod.KEY && payload.method !== DidMethod.WEB) { + + const { network } = payload; + const ledger = await ledgerName(network); + const ledgerList = await this._getALlLedgerDetails() as unknown as LedgerListResponse; + const isLedgerExist = ledgerList.response.find((existingLedgers) => existingLedgers.name === ledger); + if (!isLedgerExist) { + throw new BadRequestException( + ResponseMessages.agent.error.invalidLedger, + { cause: new Error(), description: ResponseMessages.errorMessages.notFound } + ); + } + + ledgerIdData = await this.agentServiceRepository.getLedgerDetails(ledger); + } + + const agentSpinUpStatus = AgentSpinUpStatus.PROCESSED; + + // Create and stored agent details + agentProcess = await this.agentServiceRepository.createOrgAgent(agentSpinUpStatus, user?.id); + + // Get platform admin details + const platformAdminSpinnedUp = await this.getPlatformAdminAndNotify(payload.clientSocketId); + + payload.endpoint = platformAdminSpinnedUp.org_agents[0].agentEndPoint; + // Create tenant wallet and DID + const tenantDetails = await this.createTenantAndNotify(payload, platformAdminSpinnedUp); + if (!tenantDetails?.walletResponseDetails?.id || !tenantDetails?.DIDCreationOption?.did) { + this.logger.error(`Error in getting wallet id and wallet did`); + throw new NotFoundException( + ResponseMessages.agent.error.notAbleToSpinUpAgent, + { cause: new Error(), description: ResponseMessages.errorMessages.notFound } + ); } - ledgerIdData = await this.agentServiceRepository.getLedgerDetails(ledger); + if (AgentSpinUpStatus.COMPLETED !== platformAdminSpinnedUp.org_agents[0].agentSpinUpStatus) { + this.logger.error(`Platform-admin agent is not spun-up`); + throw new NotFoundException( + ResponseMessages.agent.error.platformAdminNotAbleToSpinp, + { cause: new Error(), description: ResponseMessages.errorMessages.notFound } + ); + } + // Get shared agent type + const orgAgentTypeId = await this.agentServiceRepository.getOrgAgentTypeDetails(OrgAgentType.SHARED); + // Get agent type details + const agentTypeId = await this.agentServiceRepository.getAgentTypeId(AgentType.AFJ); + + const storeOrgAgentData: IStoreOrgAgentDetails = { + did: tenantDetails.DIDCreationOption.did, + isDidPublic: true, + agentSpinUpStatus: AgentSpinUpStatus.COMPLETED, + agentsTypeId: agentTypeId, + orgId: payload.orgId, + agentEndPoint: platformAdminSpinnedUp.org_agents[0].agentEndPoint, + orgAgentTypeId, + tenantId: tenantDetails.walletResponseDetails['id'], + walletName: payload.label, + ledgerId: ledgerIdData ? ledgerIdData.map(item => item.id) : null, + id: agentProcess?.id + }; + + // Get organization data + const getOrganization = await this.agentServiceRepository.getOrgDetails(payload.orgId); + + this.notifyClientSocket('agent-spinup-process-completed', payload.clientSocketId); + + await this.agentServiceRepository.storeOrgAgentDetails(storeOrgAgentData); + + this.notifyClientSocket('invitation-url-creation-started', payload.clientSocketId); + + // Create the legacy connection invitation + await this._createLegacyConnectionInvitation(payload.orgId, user, getOrganization.name); + + this.notifyClientSocket('invitation-url-creation-success', payload.clientSocketId); + + } catch (error) { + this.handleError(error, payload.clientSocketId); + + if (agentProcess && agentProcess?.id) { + this.agentServiceRepository.removeOrgAgent(agentProcess?.id); + } + throw error; } + } - const agentSpinUpStatus = AgentSpinUpStatus.PROCESSED; + /** + * Create wallet + * @param payload + * @returns wallet details + */ + async createWallet(payload: IWallet): Promise { + try { + const platformAdminSpinnedUp = await this.agentServiceRepository.platformAdminAgent(CommonConstants.PLATFORM_ADMIN_ORG); - // Create and stored agent details - agentProcess = await this.agentServiceRepository.createOrgAgent(agentSpinUpStatus, user?.id); + const getPlatformAgentEndPoint = platformAdminSpinnedUp.org_agents[0].agentEndPoint; - // Get platform admin details - const platformAdminSpinnedUp = await this.getPlatformAdminAndNotify(payload.clientSocketId); + const { label } = payload; + const createTenantOptions = { + config: { label } + }; - payload.endpoint = platformAdminSpinnedUp.org_agents[0].agentEndPoint; - // Create tenant wallet and DID - const tenantDetails = await this.createTenantAndNotify(payload, platformAdminSpinnedUp); - if (!tenantDetails?.walletResponseDetails?.id || !tenantDetails?.DIDCreationOption?.did) { - this.logger.error(`Error in getting wallet id and wallet did`); - throw new NotFoundException(ResponseMessages.agent.error.notAbleToSpinUpAgent, { - cause: new Error(), - description: ResponseMessages.errorMessages.notFound - }); - } + const tenantDetails = await this.commonService.httpPost( + `${getPlatformAgentEndPoint}${CommonConstants.URL_SHAGENT_CREATE_TENANT}`, + createTenantOptions, + { headers: { 'authorization': platformAdminSpinnedUp.org_agents[0].apiKey } } + ); - if (AgentSpinUpStatus.COMPLETED !== platformAdminSpinnedUp.org_agents[0].agentSpinUpStatus) { - this.logger.error(`Platform-admin agent is not spun-up`); - throw new NotFoundException(ResponseMessages.agent.error.platformAdminNotAbleToSpinp, { - cause: new Error(), - description: ResponseMessages.errorMessages.notFound - }); - } - // Get shared agent type - const orgAgentTypeId = await this.agentServiceRepository.getOrgAgentTypeDetails(OrgAgentType.SHARED); - // Get agent type details - const agentTypeId = await this.agentServiceRepository.getAgentTypeId(AgentType.AFJ); + return tenantDetails; - const storeOrgAgentData: IStoreOrgAgentDetails = { - did: tenantDetails.DIDCreationOption.did, - isDidPublic: true, - didDoc: tenantDetails.DIDCreationOption.didDocument || tenantDetails.DIDCreationOption.didDoc, //changed the didDoc into didDocument - agentSpinUpStatus: AgentSpinUpStatus.COMPLETED, - agentsTypeId: agentTypeId, - orgId: payload.orgId, - agentEndPoint: platformAdminSpinnedUp.org_agents[0].agentEndPoint, - orgAgentTypeId, - tenantId: tenantDetails.walletResponseDetails['id'], - walletName: payload.label, - ledgerId: ledgerIdData ? ledgerIdData.map((item) => item.id) : null, - id: agentProcess?.id - }; + } catch (error) { + this.logger.error(`error in create wallet : ${JSON.stringify(error)}`); + throw new RpcException(error.response ? error.response : error); + } + } - // Get organization data - const getOrganization = await this.agentServiceRepository.getOrgDetails(payload.orgId); + /** + * Create did + * @param payload + * @returns did and didDocument + */ + async createDid(payload: IDidCreate, orgId: string, user: IUserRequestInterface): Promise { + try { + const agentDetails = await this.agentServiceRepository.getOrgAgentDetails(orgId); + let apiKey: string = await this.cacheService.get(CommonConstants.CACHE_APIKEY_KEY); + if (!apiKey || null === apiKey || undefined === apiKey) { + apiKey = await this.getOrgAgentApiKey(orgId); + } + const getOrgAgentType = await this.agentServiceRepository.getOrgAgentType(agentDetails?.orgAgentTypeId); + let url; - this.notifyClientSocket('agent-spinup-process-completed', payload.clientSocketId); + if (getOrgAgentType.agent === OrgAgentType.DEDICATED) { + url = `${agentDetails.agentEndPoint}${CommonConstants.URL_AGENT_WRITE_DID}`; + } else if (getOrgAgentType.agent === OrgAgentType.SHARED) { + url = `${agentDetails.agentEndPoint}${CommonConstants.URL_SHAGENT_CREATE_DID}${agentDetails.tenantId}`; + } + const didDetails = await this.commonService.httpPost(url, payload, + { headers: { 'authorization': apiKey } } + ); + return didDetails; - const orgAgentDetails = await this.agentServiceRepository.storeOrgAgentDetails(storeOrgAgentData); + } catch (error) { + this.logger.error(`error in create did : ${JSON.stringify(error)}`); - const createdDidDetails = { - orgId: payload.orgId, - did: tenantDetails.DIDCreationOption.did, - didDocument: tenantDetails.DIDCreationOption.didDocument || tenantDetails.DIDCreationOption.didDoc, - isPrimaryDid: true, - orgAgentId: orgAgentDetails.id, - userId: user.id - }; + if (error?.response?.error?.message) { + throw new RpcException({ + statusCode: error?.response?.status, + error: error?.response?.error?.message + }); + } else { + throw new RpcException(error.response ? error.response : error); + } - await this.agentServiceRepository.storeDidDetails(createdDidDetails); + } +} - this.notifyClientSocket('invitation-url-creation-started', payload.clientSocketId); + /** + * @returns Secp256k1 key pair for polygon DID + */ + async createSecp256k1KeyPair(orgId:string): Promise { + try { + const platformAdminSpinnedUp = await this.agentServiceRepository.platformAdminAgent( + CommonConstants.PLATFORM_ADMIN_ORG + ); - // Create the legacy connection invitation - await this._createConnectionInvitation(payload.orgId, user, getOrganization.name); + const getPlatformAgentEndPoint = platformAdminSpinnedUp.org_agents[0].agentEndPoint; - this.notifyClientSocket('invitation-url-creation-success', payload.clientSocketId); - } catch (error) { - this.handleError(error, payload.clientSocketId); + const url = `${getPlatformAgentEndPoint}${CommonConstants.CREATE_POLYGON_SECP256k1_KEY}`; - if (agentProcess && agentProcess?.id) { - this.agentServiceRepository.removeOrgAgent(agentProcess?.id); - } - throw error; - } - } + const createKeyPairResponse = await this.commonService.httpPost(url, {}, { headers: { 'authorization': platformAdminSpinnedUp.org_agents[0].apiKey } }); + return createKeyPairResponse; + } catch (error) { + this.logger.error(`error in createSecp256k1KeyPair : ${JSON.stringify(error)}`); + throw new RpcException(error.response ? error.response : error); + } + } /** * Create wallet @@ -1043,10 +1077,10 @@ export class AgentServiceService { * @param platformAdminSpinnedUp * @returns Get tanant status */ - + // eslint-disable-next-line @typescript-eslint/no-explicit-any private async createTenantAndNotify(payload: ITenantDto, platformAdminSpinnedUp: IOrgAgentsResponse): Promise { - const WalletSetupPayload = { ...payload }; + const WalletSetupPayload = {...payload}; const socket = await this.createSocketInstance(); if (WalletSetupPayload.clientSocketId) { socket.emit('agent-spinup-process-initiated', { clientId: WalletSetupPayload.clientSocketId }); @@ -1058,15 +1092,11 @@ export class AgentServiceService { delete WalletSetupPayload.orgId; delete WalletSetupPayload.ledgerId; - const getDcryptedToken = await this.commonService.decryptPassword(platformAdminSpinnedUp?.org_agents[0].apiKey); - const walletResponseDetails = await this._createTenantWallet( - walletLabel, - platformAdminSpinnedUp.org_agents[0].agentEndPoint, - getDcryptedToken - ); - if (!walletResponseDetails && !walletResponseDetails.id) { - throw new InternalServerErrorException('Error while creating the wallet'); - } + + const walletResponseDetails = await this._createTenantWallet(walletLabel, platformAdminSpinnedUp.org_agents[0].agentEndPoint, platformAdminSpinnedUp.org_agents[0].apiKey); + if (!walletResponseDetails && !walletResponseDetails.id) { + throw new InternalServerErrorException('Error while creating the wallet'); + } const didCreateOption = { didPayload: WalletSetupPayload, agentEndpoint: platformAdminSpinnedUp.org_agents[0].agentEndPoint, @@ -1076,49 +1106,50 @@ export class AgentServiceService { const DIDCreationOption = await this._createDID(didCreateOption); if (!DIDCreationOption) { throw new InternalServerErrorException('Error while creating the wallet'); - } - - return { walletResponseDetails, DIDCreationOption }; + } + + return {walletResponseDetails, DIDCreationOption}; } - // +// - /** + /** * Create tenant wallet on the agent * @param createTenantWalletPayload * @returns Get tanant status */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - private async _createTenantWallet(label, endpoint, agentApiKey): Promise { - //remove any - - const createTenantOptions = { - config: { label } - }; - // Invoke an API request from the agent to create multi-tenant agent - const tenantDetails = await this.commonService.httpPost( - `${endpoint}${CommonConstants.URL_SHAGENT_CREATE_TENANT}`, - createTenantOptions, - { headers: { authorization: agentApiKey } } - ); - return tenantDetails; - } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + private async _createTenantWallet(label, endpoint, agentApiKey): Promise { //remove any + + + const createTenantOptions = { + config: { label } + }; + // Invoke an API request from the agent to create multi-tenant agent + const tenantDetails = await this.commonService.httpPost( + `${endpoint}${CommonConstants.URL_SHAGENT_CREATE_TENANT}`, + createTenantOptions, + { headers: { authorization: agentApiKey } } + ); + return tenantDetails; +} - /** + /** * Create tenant wallet on the agent * @param _createDID * @returns Get tanant status */ - private async _createDID(didCreateOption): Promise { - const { didPayload, agentEndpoint, apiKey, tenantId } = didCreateOption; - // Invoke an API request from the agent to create multi-tenant agent - const didDetails = await this.commonService.httpPost( - `${agentEndpoint}${CommonConstants.URL_SHAGENT_CREATE_DID}${tenantId}`, - didPayload, - { headers: { authorization: apiKey } } - ); - return didDetails; - } + private async _createDID(didCreateOption): Promise { + + const {didPayload, agentEndpoint, apiKey, tenantId} = didCreateOption; + // Invoke an API request from the agent to create multi-tenant agent + const didDetails = await this.commonService.httpPost( + `${agentEndpoint}${CommonConstants.URL_SHAGENT_CREATE_DID}${tenantId}`, + didPayload, + { headers: { authorization: apiKey } } + ); + return didDetails; +} private async createSocketInstance(): Promise { return io(`${process.env.SOCKET_HOST}`, { reconnection: true, @@ -1158,14 +1189,15 @@ export class AgentServiceService { name: payload.name, issuerId: payload.issuerId }; - schemaResponse = await this.commonService - .httpPost(url, schemaPayload, { headers: { authorization: getApiKey } }) - .then(async (schema) => schema) - .catch((error) => { - throw new InternalServerErrorException(ResponseMessages.agent.error.agentDown, { - cause: new Error(), - description: ResponseMessages.errorMessages.serverError - }); + schemaResponse = await this.commonService.httpPost(url, schemaPayload, { headers: { 'authorization': payload.apiKey } }) + .then(async (schema) => { + return schema; + }) + .catch(error => { + throw new InternalServerErrorException( + ResponseMessages.agent.error.agentDown, + { cause: new Error(), description: ResponseMessages.errorMessages.serverError } + ); }); } else if (OrgAgentType.SHARED === payload.agentType) { const url = `${payload.agentEndPoint}${CommonConstants.URL_SHAGENT_CREATE_SCHEMA}`.replace( @@ -1178,14 +1210,15 @@ export class AgentServiceService { name: payload.payload.name, issuerId: payload.payload.issuerId }; - schemaResponse = await this.commonService - .httpPost(url, schemaPayload, { headers: { authorization: getApiKey } }) - .then(async (schema) => schema) - .catch((error) => { - throw new InternalServerErrorException(ResponseMessages.agent.error.agentDown, { - cause: new Error(), - description: ResponseMessages.errorMessages.serverError - }); + schemaResponse = await this.commonService.httpPost(url, schemaPayload, { headers: { 'authorization': payload.apiKey } }) + .then(async (schema) => { + return schema; + }) + .catch(error => { + throw new InternalServerErrorException( + ResponseMessages.agent.error.agentDown, + { cause: new Error(), description: ResponseMessages.errorMessages.serverError } + ); }); } return schemaResponse; @@ -1201,19 +1234,21 @@ export class AgentServiceService { const getApiKey = await this.getOrgAgentApiKey(payload.orgId); if (OrgAgentType.DEDICATED === payload.agentType) { - const url = `${payload.agentEndPoint}${CommonConstants.URL_SCHM_GET_SCHEMA_BY_ID.replace( - '#', - `${payload.schemaId}` - )}`; - schemaResponse = await this.commonService.httpGet(url, { headers: { authorization: getApiKey } }).then(async (schema) => schema); + const url = `${payload.agentEndPoint}${CommonConstants.URL_SCHM_GET_SCHEMA_BY_ID.replace('#', `${payload.schemaId}`)}`; + schemaResponse = await this.commonService.httpGet(url, payload.schemaId) + .then(async (schema) => { + return schema; + }); + } else if (OrgAgentType.SHARED === payload.agentType) { const url = `${payload.agentEndPoint}${CommonConstants.URL_SHAGENT_GET_SCHEMA}` .replace('@', `${payload.payload.schemaId}`) .replace('#', `${payload.tenantId}`); - schemaResponse = await this.commonService - .httpGet(url, { headers: { authorization: getApiKey } }) - .then(async (schema) => schema); + schemaResponse = await this.commonService.httpGet(url, { headers: { 'authorization': payload.apiKey } }) + .then(async (schema) => { + return schema; + }); } return schemaResponse; } catch (error) { @@ -1235,9 +1270,11 @@ export class AgentServiceService { issuerId: payload.issuerId }; - credDefResponse = await this.commonService - .httpPost(url, credDefPayload, { headers: { authorization: getApiKey } }) - .then(async (credDef) => credDef); + credDefResponse = await this.commonService.httpPost(url, credDefPayload, { headers: { 'authorization': payload.apiKey } }) + .then(async (credDef) => { + return credDef; + }); + } else if (OrgAgentType.SHARED === payload.agentType) { const url = `${payload.agentEndPoint}${CommonConstants.URL_SHAGENT_CREATE_CRED_DEF}`.replace( '#', @@ -1248,9 +1285,10 @@ export class AgentServiceService { schemaId: payload.payload.schemaId, issuerId: payload.payload.issuerId }; - credDefResponse = await this.commonService - .httpPost(url, credDefPayload, { headers: { authorization: getApiKey } }) - .then(async (credDef) => credDef); + credDefResponse = await this.commonService.httpPost(url, credDefPayload, { headers: { 'authorization': payload.apiKey } }) + .then(async (credDef) => { + return credDef; + }); } return credDefResponse; @@ -1266,20 +1304,18 @@ export class AgentServiceService { const getApiKey = await this.getOrgAgentApiKey(payload.orgId); if (OrgAgentType.DEDICATED === payload.agentType) { - const url = `${payload.agentEndPoint}${CommonConstants.URL_SCHM_GET_CRED_DEF_BY_ID.replace( - '#', - `${payload.credentialDefinitionId}` - )}`; - credDefResponse = await this.commonService - .httpGet(url, { headers: { authorization: getApiKey } }) - .then(async (credDef) => credDef); + const url = `${payload.agentEndPoint}${CommonConstants.URL_SCHM_GET_CRED_DEF_BY_ID.replace('#', `${payload.credentialDefinitionId}`)}`; + credDefResponse = await this.commonService.httpGet(url, payload.credentialDefinitionId) + .then(async (credDef) => { + return credDef; + }); + } else if (OrgAgentType.SHARED === payload.agentType) { - const url = `${payload.agentEndPoint}${CommonConstants.URL_SHAGENT_GET_CRED_DEF}` - .replace('@', `${payload.payload.credentialDefinitionId}`) - .replace('#', `${payload.tenantId}`); - credDefResponse = await this.commonService - .httpGet(url, { headers: { authorization: getApiKey } }) - .then(async (credDef) => credDef); + const url = `${payload.agentEndPoint}${CommonConstants.URL_SHAGENT_GET_CRED_DEF}`.replace('@', `${payload.payload.credentialDefinitionId}`).replace('#', `${payload.tenantId}`); + credDefResponse = await this.commonService.httpGet(url, { headers: { 'authorization': payload.apiKey } }) + .then(async (credDef) => { + return credDef; + }); } return credDefResponse; } catch (error) { @@ -1466,17 +1502,14 @@ export class AgentServiceService { try { const getLedgerConfigData = await this.agentServiceRepository.getLedgerConfigByOrgId(); return getLedgerConfigData; + } catch (error) { this.logger.error(`Error in send out of band proof request in agent service : ${JSON.stringify(error)}`); throw error; } } - async sendOutOfBandProofRequest( - proofRequestPayload: ISendProofRequestPayload, - url: string, - orgId: string - ): Promise { + async sendOutOfBandProofRequest(proofRequestPayload: ISendProofRequestPayload, url: string, apiKey: string): Promise { try { const getApiKey = await this.getOrgAgentApiKey(orgId); const sendProofRequest = await this.commonService @@ -1684,69 +1717,4 @@ export class AgentServiceService { return data; } - async createWC3Schema(url: string, apiKey: string, schemaRequestPayload): Promise { - try { - const schemaRequest = await this.commonService - .httpPost(url, schemaRequestPayload, { headers: { authorization: getApiKey } }) - .then(async (response) => response); - return schemaRequest; - } catch (error) { - this.logger.error(`Error in createW3CSchema request in agent service : ${JSON.stringify(error)}`); - } - } - - async createConnectionInvitation( - url: string, - orgId: string, - connectionPayload: ICreateConnectionInvitation - ): Promise { - try { - const getApiKey = await this.getOrgAgentApiKey(orgId); - - const createConnectionInvitation = await this.commonService - .httpPost(url, connectionPayload, { headers: { authorization: getApiKey } }) - .then(async (response) => response); - return createConnectionInvitation; - } catch (error) { - this.logger.error(`Error in create connection invitation in agent service : ${JSON.stringify(error)}`); - throw error; - } - } - - async natsCall( - pattern: object, - payload: object - ): Promise<{ - response: string; - }> { - try { - return this.agentServiceProxy - .send(pattern, payload) - .pipe(map((response) => ({ response }))) - .toPromise() - .catch((error) => { - this.logger.error(`catch: ${JSON.stringify(error)}`); - throw new HttpException( - { - status: error.statusCode, - error: error.message - }, - error.error - ); - }); - } catch (error) { - this.logger.error(`[natsCall] - error in nats call : ${JSON.stringify(error)}`); - throw error; - } - } - - private async tokenEncryption(token: string): Promise { - try { - const encryptedToken = CryptoJS.AES.encrypt(JSON.stringify(token), process.env.CRYPTO_PRIVATE_KEY).toString(); - - return encryptedToken; - } catch (error) { - throw error; - } - } } diff --git a/apps/agent-service/src/interface/agent-service.interface.ts b/apps/agent-service/src/interface/agent-service.interface.ts index 654ec688c..e5f5eab26 100644 --- a/apps/agent-service/src/interface/agent-service.interface.ts +++ b/apps/agent-service/src/interface/agent-service.interface.ts @@ -2,42 +2,28 @@ import { AgentSpinUpStatus } from '@credebl/enum/enum'; import { UserRoleOrgPermsDto } from 'apps/api-gateway/src/dtos/user-role-org-perms.dto'; export interface IAgentSpinupDto { - walletName: string; - walletPassword: string; - seed: string; - orgId?: string; - orgName?: string; - ledgerId?: string[]; - keyType: string; - domain?: string; - privatekey?: string; - endpoint?: string; - role?: string; - network?: string; - endorserDid?: string; - method: string; - did?: string; - agentType?: string; - transactionApproval?: boolean; - clientSocketId?: string; - tenant?: boolean; - ledgerName?: string[]; - platformAdminEmail?: string; - isOnPremises?: boolean; - agentEndpoint?: string; - apiKey?: string; - orgAgentType?: string; - userId?: string; -} - -export interface IAgentConfigure { - walletName: string; - did: string; - agentEndpoint: string; - apiKey: string; - orgId: string; - network?: string; - tenant?: boolean; + walletName: string; + walletPassword: string; + seed: string; + orgId?: string; + orgName?: string; + ledgerId?: string[]; + keyType: string; + domain?: string; + privatekey?: string; + endpoint?: string; + role?: string; + network?: string + endorserDid?: string + method: string; + did?: string; + agentType?: string; + transactionApproval?: boolean; + clientSocketId?: string + tenant?: boolean; + ledgerName?: string[]; + platformAdminEmail?: string; + apiKey?: string; } export interface IOutOfBandCredentialOffer { @@ -54,43 +40,42 @@ export interface IOutOfBandCredentialOffer { } export interface ITenantDto { - label: string; - seed?: string; - keyType: string; - ledgerId: string[]; - domain?: string; - privatekey?: string; - endpoint?: string; - role?: string; - network?: string; - endorserDid?: string; - method: string; - orgId: string; - did?: string; - tenantId?: string; - didDocument?: string; - clientSocketId?: string; + label: string; + seed?: string; + keyType: string; + ledgerId: string[]; + domain?: string; + privatekey?: string; + endpoint?: string; + role?: string; + network?: string + endorserDid?: string + method: string; + orgId: string; + did?: string; + tenantId?: string; + didDocument?: string; + clientSocketId?: string; } export interface IWallet { - label: string; - orgId: string; - did?: string; - clientSocketId?: string; + label: string; + orgId: string; + did?: string; + clientSocketId?: string; } export interface IDidCreate { - keyType: KeyType; - seed: string; - domain?: string; - network?: string; - privatekey?: string; - endpoint?: string; - method: string; - did?: string; - role?: string; - endorserDid?: string; - isPrimaryDid?: boolean; + keyType: KeyType; + seed: string; + domain?: string; + network?: string; + privatekey?: string; + endpoint?: string; + method: string; + did?: string; + role?: string; + endorserDid?: string; } export interface ITenantSchema { tenantId?: string; @@ -185,7 +170,6 @@ export interface IStoreOrgAgentDetails { network?: string; role?: string; did?: string; - didDoc?: string; verkey?: string; isDidPublic?: boolean; agentSpinUpStatus?: number; @@ -197,36 +181,26 @@ export interface IStoreOrgAgentDetails { tenantId?: string; ledgerId?: string[]; agentType?: string; - userId?: string; -} - -export interface IStoreDidDetails { - orgId: string; - isPrimaryDid?: boolean; - did: string; - didDocument?: string; - userId: string; - orgAgentId: string; } export interface IStoreOrgAgent { - id?: string; - clientSocketId?: string; - agentEndPoint?: string; - apiKey?: string; - seed?: string; - did?: string; - verkey?: string; - isDidPublic?: boolean; - agentSpinUpStatus?: number; - walletName?: string; - agentsTypeId?: string; - orgId?: string; - agentId?: string; - orgAgentTypeId?: string; - tenantId?: string; - ledgerId?: unknown; - agentType?: string; + id?: string; + clientSocketId?: string; + agentEndPoint?: string; + apiKey?: string; + seed?: string; + did?: string; + verkey?: string; + isDidPublic?: boolean; + agentSpinUpStatus?: number; + walletName?: string; + agentsTypeId?: string; + orgId?: string; + agentId?: string; + orgAgentTypeId?: string; + tenantId?: string; + ledgerId?: unknown; + agentType?: string; } export interface IConnectionDetails { @@ -272,6 +246,14 @@ export interface IPlatformAgent { role: string; } +export interface IPlatformAgent { + seed: string; + keyType: string; + method: string; + network: string; + role: string; + } + export interface IOrgAgentInterface { orgDid: string; verkey: string; @@ -421,12 +403,12 @@ interface IConfig { walletConfig: IWalletConfig; } export interface ITenantRecord { - _tags: string; - metadata: string; - id: string; - createdAt: string; - config: IConfig; - updatedAt: string; + _tags: string; + metadata: string; + id: string; + createdAt: string; + config: IConfig; + updatedAt: string; } export interface ICreateTenant { @@ -435,6 +417,7 @@ export interface ICreateTenant { verkey: string; } + export interface IOrgAgent { agentSpinUpStatus: number; } @@ -540,73 +523,31 @@ interface ITags { } export interface IValidResponses { - text: string; -} -export interface IQuestionPayload { - detail: string; - validResponses: IValidResponses[]; - question: string; - orgId?: string; - connectionId: string; - tenantId: string; -} + text: string; + } + export interface IQuestionPayload { + detail: string; + validResponses: IValidResponses[]; + question: string; + orgId?: string; + connectionId: string; + tenantId: string; + } interface Ledger { - id: string; - createDateTime: string; - lastChangedDateTime: string; - name: string; - networkType: string; - poolConfig: string; - isActive: boolean; - networkString: string; - nymTxnEndpoint: string; - indyNamespace: string; - networkUrl: string | null; -} - -export interface LedgerListResponse { - response: Ledger[]; -} - -export interface ICreateConnectionInvitation { - label?: string; - alias?: string; - imageUrl?: string; - goalCode?: string; - goal?: string; - handshake?: boolean; - handshakeProtocols?: object[]; - messages?: object[]; - multiUseInvitation?: boolean; - autoAcceptConnection?: boolean; - routing?: object; - appendedAttachments?: object[]; - orgId?: string; -} - -export interface AgentHealthData { - label: string; - endpoints: string[]; - isInitialized: boolean; -} - -export interface IAgentStore { - did?: string; - verkey?: string; - isDidPublic?: boolean; - agentSpinUpStatus?: AgentSpinUpStatus; - walletName?: string; - agentsTypeId?: string; - orgId?: string; - agentEndPoint?: string; - agentId?: string; - orgAgentTypeId?: string; - ledgerId?: string[]; - id?: string; - apiKey?: string; - userId?: string; - createdBy?: string; - lastChangedBy?: string; - didDoc?: string; - tenantId?: string; -} + id: string; + createDateTime: string; + lastChangedDateTime: string; + name: string; + networkType: string; + poolConfig: string; + isActive: boolean; + networkString: string; + registerDIDEndpoint: string; + registerDIDPayload: string; + indyNamespace: string; + networkUrl: string | null; + } + + export interface LedgerListResponse { + response: Ledger[]; + } diff --git a/apps/agent-service/src/repositories/agent-service.repository.ts b/apps/agent-service/src/repositories/agent-service.repository.ts index 34e0e7782..678b179f5 100644 --- a/apps/agent-service/src/repositories/agent-service.repository.ts +++ b/apps/agent-service/src/repositories/agent-service.repository.ts @@ -329,4 +329,4 @@ export class AgentServiceRepository { throw error; } } -} +} \ No newline at end of file diff --git a/apps/api-gateway/src/agent-service/agent-service.controller.ts b/apps/api-gateway/src/agent-service/agent-service.controller.ts index f5918acfa..58bb09acc 100644 --- a/apps/api-gateway/src/agent-service/agent-service.controller.ts +++ b/apps/api-gateway/src/agent-service/agent-service.controller.ts @@ -39,11 +39,9 @@ import { CustomExceptionFilter } from 'apps/api-gateway/common/exception-handler import { Roles } from '../authz/decorators/roles.decorator'; import { OrgRoles } from 'libs/org-roles/enums'; import { OrgRolesGuard } from '../authz/guards/org-roles.guard'; +import { CreateDidDto } from './dto/create-did.dto'; import { validateDid } from '@credebl/common/did.validator'; import { CreateWalletDto } from './dto/create-wallet.dto'; -import { CreateNewDidDto } from './dto/create-new-did.dto'; -import { AgentSpinupValidator } from '@credebl/common/cast.helper'; -import { AgentConfigureDto } from './dto/agent-configure.dto'; const seedLength = 32; @@ -100,6 +98,29 @@ export class AgentController { return res.status(HttpStatus.OK).json(finalResponse); } + @Get('/orgs/agents/ledgerConfig') + @ApiOperation({ + summary: 'Get the ledger config details', + description: 'Get the ledger config details' + }) + @UseGuards(AuthGuard('jwt')) + async getLedgerDetails( + @User() reqUser: user, + @Res() res: Response + ): Promise { + + const ledgerConfigData = await this.agentService.getLedgerConfig(reqUser); + + const finalResponse: IResponse = { + statusCode: HttpStatus.OK, + message: ResponseMessages.agent.success.ledgerConfig, + data: ledgerConfigData + }; + + return res.status(HttpStatus.OK).json(finalResponse); + + } + /** * Spinup the agent by organization * @param agentSpinupDto @@ -120,7 +141,17 @@ export class AgentController { @User() user: user, @Res() res: Response ): Promise { - AgentSpinupValidator.validate(agentSpinupDto); + + const regex = new RegExp('^[a-zA-Z0-9]+$'); + + if (!regex.test(agentSpinupDto.walletName)) { + this.logger.error(`Please enter valid wallet name, It allows only alphanumeric values`); + throw new BadRequestException( + ResponseMessages.agent.error.seedChar, + { cause: new Error(), description: ResponseMessages.errorMessages.badRequest } + ); + } + this.logger.log(`**** Spin up the agent...${JSON.stringify(agentSpinupDto)}`); agentSpinupDto.orgId = orgId; @@ -172,128 +203,100 @@ export class AgentController { /** * Create wallet - * @param orgId + * @param orgId * @returns wallet */ - @Post('/orgs/:orgId/agents/createWallet') - @ApiOperation({ - summary: 'Create wallet', - description: 'Create wallet' - }) - @UseGuards(AuthGuard('jwt'), OrgRolesGuard) - @Roles(OrgRoles.OWNER, OrgRoles.ADMIN) - @ApiResponse({ status: HttpStatus.CREATED, description: 'Success', type: ApiResponseDto }) - async createWallet( - @Param('orgId') orgId: string, - @Body() createWalletDto: CreateWalletDto, - @User() user: user, - @Res() res: Response - ): Promise { - createWalletDto.orgId = orgId; - const walletDetails = await this.agentService.createWallet(createWalletDto, user); - - const finalResponse: IResponse = { - statusCode: HttpStatus.CREATED, - message: ResponseMessages.agent.success.createWallet, - data: walletDetails - }; - - return res.status(HttpStatus.CREATED).json(finalResponse); - } - + @Post('/orgs/:orgId/agents/createWallet') + @ApiOperation({ + summary: 'Create wallet', + description: 'Create wallet' + }) + @UseGuards(AuthGuard('jwt'), OrgRolesGuard) + @Roles(OrgRoles.OWNER, OrgRoles.ADMIN) + @ApiResponse({ status: HttpStatus.CREATED, description: 'Success', type: ApiResponseDto }) + async createWallet( + @Param('orgId') orgId: string, + @Body() createWalletDto: CreateWalletDto, + @User() user: user, + @Res() res: Response + ): Promise { + + createWalletDto.orgId = orgId; + const walletDetails = await this.agentService.createWallet(createWalletDto, user); + + const finalResponse: IResponse = { + statusCode: HttpStatus.CREATED, + message: ResponseMessages.agent.success.createWallet, + data: walletDetails + }; + + return res.status(HttpStatus.CREATED).json(finalResponse); + } + // This function will be used after multiple did method implementation in create wallet - /** + /** * Create did - * @param orgId + * @param orgId * @returns did */ - @Post('/orgs/:orgId/agents/did') - @ApiOperation({ - summary: 'Create new did', - description: 'Create new did for an organization' - }) - @UseGuards(AuthGuard('jwt'), OrgRolesGuard) - @Roles(OrgRoles.OWNER, OrgRoles.ADMIN, OrgRoles.ISSUER) - @ApiResponse({ status: HttpStatus.CREATED, description: 'Success', type: ApiResponseDto }) - async createDid( - @Param('orgId') orgId: string, - @Body() createDidDto: CreateNewDidDto, - @User() user: user, - @Res() res: Response - ): Promise { - await validateDid(createDidDto); + @Post('/orgs/:orgId/agents/createDid') + @ApiOperation({ + summary: 'Create did', + description: 'Create did' + }) + @UseGuards(AuthGuard('jwt'), OrgRolesGuard) + @Roles(OrgRoles.OWNER, OrgRoles.ADMIN) + @ApiResponse({ status: HttpStatus.CREATED, description: 'Success', type: ApiResponseDto }) + async createDid( + @Param('orgId') orgId: string, + @Body() createDidDto: CreateDidDto, + @User() user: user, + @Res() res: Response + ): Promise { + + validateDid(createDidDto); - if (createDidDto.seed && seedLength !== createDidDto.seed.length) { + if (seedLength !== createDidDto.seed.length) { this.logger.error(`seed must be at most 32 characters.`); - throw new BadRequestException(ResponseMessages.agent.error.seedChar, { - cause: new Error(), - description: ResponseMessages.errorMessages.badRequest - }); + throw new BadRequestException( + ResponseMessages.agent.error.seedChar, + { cause: new Error(), description: ResponseMessages.errorMessages.badRequest } + ); } - const didDetails = await this.agentService.createDid(createDidDto, orgId, user); - - const finalResponse: IResponse = { - statusCode: HttpStatus.CREATED, - message: ResponseMessages.agent.success.createDid, - data: didDetails - }; - - return res.status(HttpStatus.CREATED).json(finalResponse); - } + const didDetails = await this.agentService.createDid(createDidDto, orgId, user); + + const finalResponse: IResponse = { + statusCode: HttpStatus.CREATED, + message: ResponseMessages.agent.success.createDid, + data: didDetails + }; + + return res.status(HttpStatus.CREATED).json(finalResponse); + } - /** + /** * Create Secp256k1 key pair for polygon DID - * @param orgId + * @param orgId * @returns Secp256k1 key pair for polygon DID */ - @Post('/orgs/:orgId/agents/polygon/create-keys') - @UseGuards(AuthGuard('jwt'), OrgRolesGuard) - @Roles(OrgRoles.OWNER, OrgRoles.ADMIN, OrgRoles.PLATFORM_ADMIN, OrgRoles.ISSUER, OrgRoles.VERIFIER) - @ApiResponse({ status: HttpStatus.CREATED, description: 'Success', type: ApiResponseDto }) - async createSecp256k1KeyPair(@Param('orgId') orgId: string, @Res() res: Response): Promise { - const didDetails = await this.agentService.createSecp256k1KeyPair(orgId); - - const finalResponse: IResponse = { - statusCode: HttpStatus.CREATED, - message: ResponseMessages.agent.success.createKeys, - data: didDetails - }; - - return res.status(HttpStatus.CREATED).json(finalResponse); - } - - /** - * Configure the agent by organization - * @param agentSpinupDto - * @param user - * @returns Get agent status - */ - @Post('/orgs/:orgId/agents/configure') - @ApiOperation({ - summary: 'Agent configure', - description: 'Create a new agent configure.' - }) - @UseGuards(AuthGuard('jwt'), OrgRolesGuard) - @Roles(OrgRoles.OWNER, OrgRoles.ADMIN) - @ApiResponse({ status: HttpStatus.CREATED, description: 'Success', type: ApiResponseDto }) - async agentconfigure( - @Param('orgId') orgId: string, - @Body() agentConfigureDto: AgentConfigureDto, - @User() user: user, - @Res() res: Response - ): Promise { - this.logger.log(`**** Configure the agent...${JSON.stringify(agentConfigureDto)}`); - - agentConfigureDto.orgId = orgId; - const agentDetails = await this.agentService.agentConfigure(agentConfigureDto, user); - - const finalResponse: IResponseType = { - statusCode: HttpStatus.CREATED, - message: ResponseMessages.agent.success.create, - data: agentDetails - }; - - return res.status(HttpStatus.CREATED).json(finalResponse); - } + @Post('/orgs/:orgId/agents/polygon/create-keys') + @UseGuards(AuthGuard('jwt'), OrgRolesGuard) + @Roles(OrgRoles.OWNER, OrgRoles.ADMIN, OrgRoles.PLATFORM_ADMIN, OrgRoles.ISSUER, OrgRoles.VERIFIER) + @ApiResponse({ status: HttpStatus.CREATED, description: 'Success', type: ApiResponseDto }) + async createSecp256k1KeyPair( + @Param('orgId') orgId: string, + @Res() res: Response + ): Promise { + + const didDetails = await this.agentService.createSecp256k1KeyPair(orgId); + + const finalResponse: IResponse = { + statusCode: HttpStatus.CREATED, + message: ResponseMessages.agent.success.createKeys, + data: didDetails + }; + + return res.status(HttpStatus.CREATED).json(finalResponse); + } } diff --git a/apps/api-gateway/src/agent-service/agent-service.service.ts b/apps/api-gateway/src/agent-service/agent-service.service.ts index 38efd54e8..48cead6c9 100644 --- a/apps/api-gateway/src/agent-service/agent-service.service.ts +++ b/apps/api-gateway/src/agent-service/agent-service.service.ts @@ -8,7 +8,6 @@ import { AgentSpinUpSatus, IWalletRecord } from './interface/agent-service.inter import { AgentStatus } from './interface/agent-service.interface'; import { CreateDidDto } from './dto/create-did.dto'; import { CreateWalletDto } from './dto/create-wallet.dto'; -import { AgentConfigureDto } from './dto/agent-configure.dto'; @Injectable() export class AgentService extends BaseService { @@ -73,11 +72,4 @@ export class AgentService extends BaseService { return this.sendNatsMessage(this.agentServiceProxy, 'polygon-create-keys', payload); } - async agentConfigure(agentConfigureDto: AgentConfigureDto, user: user): Promise { - const payload = { agentConfigureDto, user }; - // NATS call - - return this.sendNatsMessage(this.agentServiceProxy, 'agent-configure', payload); - } - } \ No newline at end of file diff --git a/apps/api-gateway/src/agent-service/dto/agent-service.dto.ts b/apps/api-gateway/src/agent-service/dto/agent-service.dto.ts index d04cce6a9..93f022b6f 100644 --- a/apps/api-gateway/src/agent-service/dto/agent-service.dto.ts +++ b/apps/api-gateway/src/agent-service/dto/agent-service.dto.ts @@ -5,38 +5,40 @@ import { IsBoolean, IsNotEmpty, IsOptional, IsString, Matches, MaxLength, MinLen import { CreateDidDto } from './create-did.dto'; const regex = /^[a-zA-Z0-9 ]*$/; export class AgentSpinupDto extends CreateDidDto { - @ApiProperty() - @MaxLength(25, { message: 'Maximum length for wallet must be 25 characters.' }) - @IsString({ message: 'label must be in string format.' }) - @Transform(({ value }) => trim(value)) - @MinLength(2, { message: 'Minimum length for wallet name must be 2 characters.' }) - @Matches(regex, { message: 'Wallet name must not contain special characters.' }) - @Matches(/^\S*$/, { - message: 'Spaces are not allowed in walletName' - }) - walletName: string; - @ApiProperty() - @Transform(({ value }) => trim(value)) - @IsOptional() - @IsString({ message: 'walletPassword must be in string format.' }) - @IsNotEmpty({ message: 'Password is required.' }) - walletPassword?: string; + @ApiProperty() + @MaxLength(25, { message: 'Maximum length for wallet must be 25 characters.' }) + @IsString({ message: 'label must be in string format.' }) + @Transform(({ value }) => trim(value)) + @MinLength(2, { message: 'Minimum length for wallet name must be 2 characters.' }) + @Matches(regex, { message: 'Wallet name must not contain special characters.' }) + @Matches(/^\S*$/, { + message: 'Spaces are not allowed in label' + }) + walletName: string; - @ApiPropertyOptional({ example: 'XzFjo1RTZ2h9UVFCnPUyaQ' }) - @IsOptional() - @Transform(({ value }) => trim(value)) - @IsString({ message: 'did must be in string format.' }) - did?: string; + @ApiProperty() + @Transform(({ value }) => trim(value)) + @IsString({ message: 'walletPassword must be in string format.' }) + @IsNotEmpty({ message: 'Password is required.' }) + walletPassword: string; - @ApiPropertyOptional({ example: 'ojIckSD2jqNzOqIrAGzL' }) - @IsOptional() - clientSocketId?: string; + @ApiProperty({ example: 'XzFjo1RTZ2h9UVFCnPUyaQ' }) + @IsOptional() + @ApiPropertyOptional() + @IsString({ message: 'did must be in string format.' }) + did?: string; - @ApiPropertyOptional({ example: true }) - @IsOptional() - @IsBoolean() - tenant?: boolean; - - orgId: string; + @ApiProperty({ example: 'ojIckSD2jqNzOqIrAGzL' }) + @IsOptional() + @ApiPropertyOptional() + clientSocketId?: string; + + @ApiProperty({ example: true }) + @IsOptional() + @IsBoolean() + @ApiPropertyOptional() + tenant?: boolean; + + orgId: string; } diff --git a/apps/api-gateway/src/agent-service/dto/create-did.dto.ts b/apps/api-gateway/src/agent-service/dto/create-did.dto.ts index 1dda2d25a..7f75116ec 100644 --- a/apps/api-gateway/src/agent-service/dto/create-did.dto.ts +++ b/apps/api-gateway/src/agent-service/dto/create-did.dto.ts @@ -18,54 +18,53 @@ export class CreateDidDto { @ApiProperty({ example: 'ed25519'}) @IsNotEmpty({ message: 'key type is required' }) - @Transform(({ value }) => trim(value)) @IsString({ message: 'key type be in string format.' }) keyType: string; @ApiProperty({ example: 'indy'}) - @IsNotEmpty({ message: 'method is required' }) - @Transform(({ value }) => trim(value)) - @IsString({ message: 'method must be in string format.' }) + @IsNotEmpty({ message: 'seed is required' }) + @IsString({ message: 'did must be in string format.' }) method: string; - @ApiPropertyOptional({example: 'bcovrin:testnet'}) + @ApiProperty({example: 'bcovrin:testnet'}) @IsOptional() - @Transform(({ value }) => trim(value)) + @ApiPropertyOptional() @IsString({ message: 'network must be in string format.' }) network?: string; - @ApiPropertyOptional({example: 'www.github.com'}) + @ApiProperty({example: 'www.github.com'}) @IsOptional() - @Transform(({ value }) => trim(value)) + @ApiPropertyOptional() @IsString({ message: 'domain must be in string format.' }) domain?: string; - @ApiPropertyOptional({example: 'endorser'}) + @ApiProperty({example: 'endorser'}) @IsOptional() - @Transform(({ value }) => trim(value)) + @ApiPropertyOptional() @IsString({ message: 'role must be in string format.' }) role?: string; - @ApiPropertyOptional({example: ''}) + @ApiProperty({example: ''}) @IsOptional() + @ApiPropertyOptional() @IsString({ message: 'private key must be in string format.' }) - @Transform(({ value }) => trim(value)) privatekey?: string; - @ApiPropertyOptional({example: 'http://localhost:6006/docs'}) + @ApiProperty({example: 'http://localhost:6006/docs'}) @IsOptional() + @ApiPropertyOptional() @IsString({ message: 'endpoint must be in string format.' }) endpoint?: string; - @ApiPropertyOptional({ example: 'XzFjo1RTZ2h9UVFCnPUyaQ' }) + @ApiProperty({ example: 'XzFjo1RTZ2h9UVFCnPUyaQ' }) @IsOptional() - @Transform(({ value }) => trim(value)) + @ApiPropertyOptional() @IsString({ message: 'did must be in string format.' }) did?: string; - @ApiPropertyOptional({example: 'did:indy:bcovrin:testnet:UEeW111G1tYo1nEkPwMcF'}) + @ApiProperty({example: 'did:indy:bcovrin:testnet:UEeW111G1tYo1nEkPwMcF'}) @IsOptional() - @Transform(({ value }) => trim(value)) + @ApiPropertyOptional() @IsString({ message: 'endorser did must be in string format.' }) endorserDid?: string; } \ No newline at end of file diff --git a/apps/api-gateway/src/agent-service/dto/create-tenant.dto.ts b/apps/api-gateway/src/agent-service/dto/create-tenant.dto.ts index e26131431..94d099f2c 100644 --- a/apps/api-gateway/src/agent-service/dto/create-tenant.dto.ts +++ b/apps/api-gateway/src/agent-service/dto/create-tenant.dto.ts @@ -1,8 +1,9 @@ import { trim } from '@credebl/common/cast.helper'; import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { Transform } from 'class-transformer'; -import { MaxLength, IsString, MinLength, IsOptional } from 'class-validator'; +import { MaxLength, IsString, MinLength, Matches, IsOptional } from 'class-validator'; import { CreateDidDto } from './create-did.dto'; +const labelRegex = /^[a-zA-Z0-9 ]*$/; export class CreateTenantDto extends CreateDidDto { @ApiProperty() @MaxLength(25, { message: 'Maximum length for label must be 25 characters.' }) diff --git a/apps/api-gateway/src/connection/connection.service.ts b/apps/api-gateway/src/connection/connection.service.ts index b8566168d..50d10f7f7 100644 --- a/apps/api-gateway/src/connection/connection.service.ts +++ b/apps/api-gateway/src/connection/connection.service.ts @@ -24,6 +24,32 @@ export class ConnectionService extends BaseService { } } + createLegacyConnectionInvitation( + connectionDto: CreateConnectionDto, + user: IUserRequestInterface + ): Promise { + try { + const connectionDetails = { + orgId: connectionDto.orgId, + alias: connectionDto.alias, + label: connectionDto.label, + imageUrl: connectionDto.imageUrl, + multiUseInvitation: connectionDto.multiUseInvitation, + autoAcceptConnection: connectionDto.autoAcceptConnection, + goalCode: connectionDto.goalCode, + goal: connectionDto.goal, + handshake: connectionDto.handshake, + handshakeProtocols: connectionDto.handshakeProtocols, + user, + recipientKey:connectionDto.recipientKey + }; + + return this.sendNatsMessage(this.connectionServiceProxy, 'create-connection', connectionDetails); + } catch (error) { + throw new RpcException(error.response); + } + } + getConnectionWebhook( connectionDto: ConnectionDto, orgId: string diff --git a/apps/api-gateway/src/connection/dtos/connection.dto.ts b/apps/api-gateway/src/connection/dtos/connection.dto.ts index 38721b303..2a662dc36 100644 --- a/apps/api-gateway/src/connection/dtos/connection.dto.ts +++ b/apps/api-gateway/src/connection/dtos/connection.dto.ts @@ -134,12 +134,6 @@ export class CreateConnectionDto { @IsOptional() @IsNotEmpty({ message: 'Please provide recipientKey' }) recipientKey: string; - - @ApiPropertyOptional() - @IsString() - @IsOptional() - @IsNotEmpty({ message: 'Please provide invitation did' }) - invitationDid?: string; } export class ConnectionDto { diff --git a/apps/api-gateway/src/verification/dto/request-proof.dto.ts b/apps/api-gateway/src/verification/dto/request-proof.dto.ts index 7a3aa553d..6f7a01a69 100644 --- a/apps/api-gateway/src/verification/dto/request-proof.dto.ts +++ b/apps/api-gateway/src/verification/dto/request-proof.dto.ts @@ -429,6 +429,14 @@ export class SendProofRequestPayload { @IsArray() @IsString({ each: true, message: 'Each emailId in the array should be a string' }) @IsOptional() - emailId: string[]; + @IsNotEmpty({message:'Please provide the flag for shorten url.'}) + isShortenUrl?: boolean; + + @ApiPropertyOptional({ default: true }) + @IsOptional() + @IsNotEmpty({ message: 'please provide valid value for reuseConnection' }) + @IsBoolean({ message: 'reuseConnection must be a boolean' }) + reuseConnection?: boolean; + } diff --git a/apps/connection/src/connection.repository.ts b/apps/connection/src/connection.repository.ts index 0e38d3fa6..3883f4315 100644 --- a/apps/connection/src/connection.repository.ts +++ b/apps/connection/src/connection.repository.ts @@ -49,7 +49,7 @@ export class ConnectionRepository { connectionInvitation: string, agentId: string, orgId: string, - invitationDid: string + recipientKey: string // eslint-disable-next-line camelcase ): Promise { try { @@ -59,7 +59,7 @@ export class ConnectionRepository { agentId, connectionInvitation, multiUse: true, - invitationDid + recipientKey } }); return agentDetails; diff --git a/apps/connection/src/connection.service.ts b/apps/connection/src/connection.service.ts index 5be8c5ebe..eedf86554 100644 --- a/apps/connection/src/connection.service.ts +++ b/apps/connection/src/connection.service.ts @@ -36,6 +36,98 @@ export class ConnectionService { @Inject(CACHE_MANAGER) private cacheService: Cache ) {} + /** + * Create connection legacy invitation URL + * @param orgId + * @param user + * @returns Connection legacy invitation URL + */ + async createLegacyConnectionInvitation(payload: IConnection): Promise { + const { + orgId, + multiUseInvitation, + autoAcceptConnection, + alias, + imageUrl, + goal, + goalCode, + handshake, + handshakeProtocols, + recipientKey + } = payload; + try { + const agentDetails = await this.connectionRepository.getAgentEndPoint(orgId); + + const { agentEndPoint, id, organisation } = agentDetails; + const agentId = id; + if (!agentDetails) { + throw new NotFoundException(ResponseMessages.connection.error.agentEndPointNotFound); + } + + this.logger.log(`logoUrl:::, ${organisation.logoUrl}`); + const connectionPayload = { + multiUseInvitation: multiUseInvitation ?? true, + autoAcceptConnection: autoAcceptConnection ?? true, + alias: alias || undefined, + imageUrl: organisation.logoUrl || imageUrl || undefined, + label: organisation.name, + goal: goal || undefined, + goalCode: goalCode || undefined, + handshake: handshake || undefined, + handshakeProtocols: handshakeProtocols || undefined, + recipientKey:recipientKey || undefined + }; + + const orgAgentType = await this.connectionRepository.getOrgAgentType(agentDetails?.orgAgentTypeId); + const url = await this.getAgentUrl(orgAgentType, agentEndPoint, agentDetails?.tenantId); + + let apiKey: string = await this.cacheService.get(CommonConstants.CACHE_APIKEY_KEY); + if (!apiKey || null === apiKey || undefined === apiKey) { + apiKey = await this._getOrgAgentApiKey(orgId); + } + const createConnectionInvitation = await this._createConnectionInvitation(connectionPayload, url, apiKey); + + const connectionInvitationUrl: string = createConnectionInvitation?.message?.invitationUrl; + const shortenedUrl: string = await this.storeConnectionObjectAndReturnUrl( + connectionInvitationUrl, + connectionPayload.multiUseInvitation + ); + const recipientsKey = createConnectionInvitation?.message?.recipientKey || recipientKey; + const saveConnectionDetails = await this.connectionRepository.saveAgentConnectionInvitations( + shortenedUrl, + agentId, + orgId, + recipientsKey + ); + const connectionDetailRecords: ConnectionResponseDetail = { + id: saveConnectionDetails.id, + orgId: saveConnectionDetails.orgId, + agentId: saveConnectionDetails.agentId, + connectionInvitation: saveConnectionDetails.connectionInvitation, + multiUse: saveConnectionDetails.multiUse, + createDateTime: saveConnectionDetails.createDateTime, + createdBy: saveConnectionDetails.createdBy, + lastChangedDateTime: saveConnectionDetails.lastChangedDateTime, + lastChangedBy: saveConnectionDetails.lastChangedBy, + recordId: createConnectionInvitation.message.outOfBandRecord.id, + recipientKey:saveConnectionDetails.recipientKey + }; + return connectionDetailRecords; + } catch (error) { + this.logger.error(`[createLegacyConnectionInvitation] - error in connection invitation: ${error}`); + if (error && error?.status && error?.status?.message && error?.status?.message?.error) { + throw new RpcException({ + message: error?.status?.message?.error?.reason + ? error?.status?.message?.error?.reason + : error?.status?.message?.error, + statusCode: error?.status?.code + }); + } else { + throw new RpcException(error.response ? error.response : error); + } + } + } + /** * Description: Catch connection webhook responses and save details in connection table * @param orgId diff --git a/apps/connection/src/interfaces/connection.interfaces.ts b/apps/connection/src/interfaces/connection.interfaces.ts index 49f06697a..02f530ff2 100644 --- a/apps/connection/src/interfaces/connection.interfaces.ts +++ b/apps/connection/src/interfaces/connection.interfaces.ts @@ -16,7 +16,6 @@ export interface IConnection { handshakeProtocols: string[]; orgId: string; recipientKey?: string; - invitationDid?: string } export interface IUserRequestInterface { userId: string; @@ -266,7 +265,7 @@ export interface ConnectionResponseDetail { lastChangedDateTime: Date; lastChangedBy: number; recordId: string; - invitationDid?: string + recipientKey:string; } export interface ICreateConnectionInvitation { diff --git a/apps/issuance/src/issuance.repository.ts b/apps/issuance/src/issuance.repository.ts index 07a7e83c2..38901cf6e 100644 --- a/apps/issuance/src/issuance.repository.ts +++ b/apps/issuance/src/issuance.repository.ts @@ -71,18 +71,19 @@ export class IssuanceRepository { } } - async getInvitationDidByOrgId(orgId: string): Promise { + + async getRecipientKeyByOrgId(orgId: string): Promise { try { return this.prisma.agent_invitations.findMany({ where: { orgId }, orderBy: { - createDateTime: 'asc' + createDateTime: 'asc' } }); } catch (error) { - this.logger.error(`Error in getInvitationDid in issuance repository: ${error.message}`); + this.logger.error(`Error in getRecipientKey in issuance repository: ${error.message}`); throw error; } } diff --git a/apps/ledger/src/credential-definition/credential-definition.service.ts b/apps/ledger/src/credential-definition/credential-definition.service.ts index d9b9ed687..d0453f5a7 100644 --- a/apps/ledger/src/credential-definition/credential-definition.service.ts +++ b/apps/ledger/src/credential-definition/credential-definition.service.ts @@ -1,5 +1,6 @@ /* eslint-disable camelcase */ import { + BadRequestException, ConflictException, HttpException, Inject, diff --git a/apps/verification/src/interfaces/verification.interface.ts b/apps/verification/src/interfaces/verification.interface.ts index d1a92a54c..b37391da7 100644 --- a/apps/verification/src/interfaces/verification.interface.ts +++ b/apps/verification/src/interfaces/verification.interface.ts @@ -159,11 +159,9 @@ export interface ISendProofRequestPayload { imageUrl?: string; isShortenUrl?: boolean; type?:string; - orgId?: string; presentationDefinition?:IProofRequestPresentationDefinition; reuseConnection?: boolean; recipientKey?:string; - invitationDid?: string } export interface IWSendProofRequestPayload { diff --git a/apps/verification/src/repositories/verification.repository.ts b/apps/verification/src/repositories/verification.repository.ts index fd12b7efe..7d831de78 100644 --- a/apps/verification/src/repositories/verification.repository.ts +++ b/apps/verification/src/repositories/verification.repository.ts @@ -184,9 +184,9 @@ export class VerificationRepository { throw error; } } - + // eslint-disable-next-line camelcase - async getInvitationDidByOrgId(orgId: string): Promise { + async getRecipientKeyByOrgId(orgId: string): Promise { try { return this.prisma.agent_invitations.findMany({ where: { @@ -197,7 +197,7 @@ export class VerificationRepository { } }); } catch (error) { - this.logger.error(`Error in getInvitationDid in verification repository: ${error.message}`); + this.logger.error(`Error in getRecipientKey in verification repository: ${error.message}`); throw error; } } diff --git a/apps/verification/src/verification.service.ts b/apps/verification/src/verification.service.ts index 55ab19733..22d1c3dba 100644 --- a/apps/verification/src/verification.service.ts +++ b/apps/verification/src/verification.service.ts @@ -6,7 +6,7 @@ import { IGetAllProofPresentations, IProofRequestSearchCriteria, IGetProofPresen import { VerificationRepository } from './repositories/verification.repository'; import { CommonConstants } from '@credebl/common/common.constant'; import { agent_invitations, org_agents, organisation, presentations } from '@prisma/client'; -import { AutoAccept, OrgAgentType } from '@credebl/enum/enum'; +import { OrgAgentType } from '@credebl/enum/enum'; import { ResponseMessages } from '@credebl/common/response-messages'; import * as QRCode from 'qrcode'; import { OutOfBandVerification } from '../templates/out-of-band-verification.template'; @@ -344,24 +344,23 @@ export class VerificationService { const url = await this.getAgentUrl(verificationMethodLabel, orgAgentType, getAgentDetails?.agentEndPoint, getAgentDetails?.tenantId); - // Destructuring 'outOfBandRequestProof' to remove emailId, as it is not used while agent operation - const { isShortenUrl, emailId, type, reuseConnection, ...updateOutOfBandRequestProof } = outOfBandRequestProof; - let invitationDid: string | undefined; + const { isShortenUrl, type, reuseConnection, ...updateOutOfBandRequestProof } = outOfBandRequestProof; + let recipientKey: string | undefined; if (true === reuseConnection) { - const data: agent_invitations[] = await this.verificationRepository.getInvitationDidByOrgId(user.orgId); + const data: agent_invitations[] = await this.verificationRepository.getRecipientKeyByOrgId(user.orgId); if (data && 0 < data.length) { const [firstElement] = data; - invitationDid = firstElement?.invitationDid ?? undefined; + recipientKey = firstElement?.recipientKey ?? undefined; } } - outOfBandRequestProof.autoAcceptProof = outOfBandRequestProof.autoAcceptProof || AutoAccept.Always; + outOfBandRequestProof.autoAcceptProof = outOfBandRequestProof.autoAcceptProof || 'always'; let payload: IProofRequestPayload; if (ProofRequestType.INDY === type) { updateOutOfBandRequestProof.protocolVersion = updateOutOfBandRequestProof.protocolVersion || 'v1'; - updateOutOfBandRequestProof.invitationDid = invitationDid || undefined; + updateOutOfBandRequestProof.recipientKey = recipientKey || undefined; payload = { orgId: user.orgId, url, @@ -388,8 +387,8 @@ export class VerificationService { } } }, - autoAcceptProof:outOfBandRequestProof.autoAcceptProof, - invitationDid:invitationDid || undefined + autoAcceptProof:outOfBandRequestProof.autoAcceptProof || 'always', + recipientKey:recipientKey || undefined } }; } diff --git a/libs/common/src/did.validator.ts b/libs/common/src/did.validator.ts index 4aa0f626a..c630fb66a 100644 --- a/libs/common/src/did.validator.ts +++ b/libs/common/src/did.validator.ts @@ -1,40 +1,27 @@ -import { DidMethod } from '@credebl/enum/enum'; -import { IDidCreate } from './interfaces/did.interface'; -import { BadRequestException } from '@nestjs/common'; +import { DidMethod, KeyType } from "@credebl/enum/enum"; +import { IDidCreate } from "./interfaces/did.interface"; -export function validateDid(createDid: IDidCreate): void { - const errors = []; +export function validateDid(createDid: IDidCreate): string[] { + const errors: string[] = []; - switch (true) { - case DidMethod.WEB === createDid.method && !createDid.domain: - errors.push('domain is required for Web method'); - break; - case (createDid.method === DidMethod.INDY || createDid.method === DidMethod.POLYGON) && !createDid.network: - errors.push('network is required'); - break; - case (createDid.method === DidMethod.INDY || createDid.method === DidMethod.POLYGON) && 'ed25519' !== createDid.keyType: - errors.push('Only ed25519 key type is supported'); - break; - case (createDid.method === DidMethod.WEB || createDid.method === DidMethod.KEY) && !('ed25519' === createDid.keyType || 'bls12381g2' === createDid.keyType): - errors.push('Only ed25519 and bls12381g2 key type is supported'); - break; - case DidMethod.INDY === createDid.method && !(createDid.role || createDid.endorserDid): - errors.push('role or endorserDid is required'); - break; - case DidMethod.POLYGON === createDid.method && !createDid.privatekey: - errors.push('privatekey is required for polygon method'); - break; - case DidMethod.POLYGON === createDid.method && createDid.privatekey && 64 !== createDid.privatekey.length: - errors.push('Private key must be exactly 64 characters long'); - break; - case (DidMethod.INDY === createDid.method || DidMethod.KEY === createDid.method || DidMethod.WEB === createDid.method) && (!createDid.seed): - errors.push('seed is required'); - break; - default: - break; + if (DidMethod.WEB && !createDid.domain) { + errors.push('domain is required for Web method'); + } else if (DidMethod.INDY && !createDid.network) { + errors.push('network is required for Indy method'); + } else if (DidMethod.INDY && createDid.keyType !== KeyType.Ed25519) { + errors.push('Only ed25519 key type is supported for Indy method'); + } else if ((createDid.method === DidMethod.WEB || createDid.method === DidMethod.KEY) && + (createDid.keyType !== KeyType.Ed25519 && createDid.keyType !== KeyType.Bls12381g2)) { + errors.push('Only ed25519 and bls12381g2 key type is supported'); + } else if (!createDid.role) { + errors.push('role or endorserDid is required'); + } else if (DidMethod.POLYGON && !createDid.privatekey) { + errors.push('privateKey is required for polygon method'); + } else if (DidMethod.POLYGON && !createDid.endpoint) { + errors.push('endpoint is required for polygon method'); + } else if ((DidMethod.INDY || DidMethod.KEY || DidMethod.WEB) && (!createDid.seed)) { + errors.push('seed is required'); } - if (0 < errors.length) { - throw new BadRequestException(errors); - } + return errors; } diff --git a/libs/common/src/interfaces/agent-service.interface.ts b/libs/common/src/interfaces/agent-service.interface.ts index 26613351d..235e00210 100644 --- a/libs/common/src/interfaces/agent-service.interface.ts +++ b/libs/common/src/interfaces/agent-service.interface.ts @@ -11,7 +11,6 @@ export interface InvitationMessage { }; outOfBandRecord: OutOfBandRecord; recipientKey?:string - invitationDid?: string }; } diff --git a/libs/common/src/interfaces/connection.interface.ts b/libs/common/src/interfaces/connection.interface.ts index 996b48c4c..9ff7c4785 100644 --- a/libs/common/src/interfaces/connection.interface.ts +++ b/libs/common/src/interfaces/connection.interface.ts @@ -31,6 +31,5 @@ export interface IConnectionsListCount { lastChangedDateTime: Date; lastChangedBy: number; recipientKey?:string; - invitationDid?: string } \ No newline at end of file diff --git a/libs/enum/src/enum.ts b/libs/enum/src/enum.ts index 459eaae9b..1ed1df54b 100644 --- a/libs/enum/src/enum.ts +++ b/libs/enum/src/enum.ts @@ -120,8 +120,3 @@ const transitionMap: { [key in Invitation]: Invitation[] } = { }; export const transition = (currentStatus: Invitation, nextStatus: Invitation): boolean => (transitionMap[currentStatus].includes(nextStatus)); - -export enum SchemaType { - INDY = 'indy', - W3C_Schema = 'w3c' -} \ No newline at end of file diff --git a/libs/prisma-service/prisma/data/credebl-master-table.json b/libs/prisma-service/prisma/data/credebl-master-table.json index 509cde62f..27848d27d 100644 --- a/libs/prisma-service/prisma/data/credebl-master-table.json +++ b/libs/prisma-service/prisma/data/credebl-master-table.json @@ -132,7 +132,8 @@ "poolConfig": "", "isActive": true, "networkString": "testnet", - "nymTxnEndpoint": "", + "registerDIDEndpoint": "", + "registerDIDPayload": "", "indyNamespace": "polygon:testnet" } ], diff --git a/libs/prisma-service/prisma/schema.prisma b/libs/prisma-service/prisma/schema.prisma index 210ccc093..64c0ada57 100644 --- a/libs/prisma-service/prisma/schema.prisma +++ b/libs/prisma-service/prisma/schema.prisma @@ -309,8 +309,7 @@ model agent_invitations { lastChangedBy Int @default(1) org_agents org_agents @relation(fields: [agentId], references: [id]) organisation organisation @relation(fields: [orgId], references: [id]) - recipientKey String? - invitationDid String? + recipientKey String? } model connections { @@ -504,7 +503,6 @@ model notification { lastChangedBy String @default("1") deletedAt DateTime? @db.Timestamp(6) } - model ledgerConfig { id String @id @default(uuid()) @db.Uuid name String