From 7c31a9d4ec3e63273f804c715ae96791b5aa50c9 Mon Sep 17 00:00:00 2001 From: Fabio Pinheiro Date: Mon, 26 Aug 2024 20:40:30 +0100 Subject: [PATCH] feat: Handle Error Notify webhooks ATL-6934 (#1279) Signed-off-by: FabioPinheiro Signed-off-by: Fabio Pinheiro Signed-off-by: Yurii Shynbuiev Co-authored-by: Yurii Shynbuiev - IOHK --- .../server/jobs/ConnectBackgroundJobs.scala | 6 +- .../server/jobs/PresentBackgroundJobs.scala | 159 ++++++++++++++++-- .../controller/IssueControllerImplSpec.scala | 4 +- .../connect/core/model/ConnectionRecord.scala | 51 +++++- .../repository/ConnectionRepository.scala | 4 +- .../core/service/ConnectionServiceImpl.scala | 12 +- .../service/ConnectionServiceNotifier.scala | 23 ++- .../ConnectionRepositoryInMemory.scala | 7 +- .../ConnectionRepositorySpecSuite.scala | 28 +-- .../ConnectionServiceNotifierSpec.scala | 13 +- .../repository/JdbcConnectionRepository.scala | 17 +- .../core/model/PresentationRecord.scala | 56 +++++- .../repository/PresentationRepository.scala | 2 + .../service/CredentialServiceNotifier.scala | 18 +- .../service/PresentationServiceImpl.scala | 103 ++++++------ .../service/PresentationServiceNotifier.scala | 25 ++- .../PresentationRepositoryInMemory.scala | 8 + .../PresentationRepositorySpecSuite.scala | 136 +++++++-------- .../CredentialServiceNotifierSpec.scala | 11 +- .../PresentationServiceNotifierSpec.scala | 30 +++- .../JdbcPresentationRepository.scala | 54 +++++- tests/integration-tests/build.gradle.kts | 2 +- .../agent-performance-tests-k6/.env | 2 +- .../agent-performance-tests-k6/package.json | 2 +- .../src/scenarios/default.ts | 2 +- .../agent-performance-tests-k6/yarn.lock | 8 +- 26 files changed, 577 insertions(+), 206 deletions(-) diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/agent/server/jobs/ConnectBackgroundJobs.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/agent/server/jobs/ConnectBackgroundJobs.scala index c16c4143c6..46335fd059 100644 --- a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/agent/server/jobs/ConnectBackgroundJobs.scala +++ b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/agent/server/jobs/ConnectBackgroundJobs.scala @@ -99,7 +99,8 @@ object ConnectBackgroundJobs extends BackgroundJobsHelper { _, metaRetries, _, - _ + _, + _, ) if metaRetries > 0 => val inviteeProcessFlow = for { walletAccessContext <- buildWalletAccessContextLayer(request.from) @@ -147,7 +148,8 @@ object ConnectBackgroundJobs extends BackgroundJobsHelper { Some(response), metaRetries, _, - _ + _, + _, ) if metaRetries > 0 => val inviterProcessFlow = for { walletAccessContext <- buildWalletAccessContextLayer(response.from) diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/agent/server/jobs/PresentBackgroundJobs.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/agent/server/jobs/PresentBackgroundJobs.scala index 2d1104eec6..462f39be08 100644 --- a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/agent/server/jobs/PresentBackgroundJobs.scala +++ b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/agent/server/jobs/PresentBackgroundJobs.scala @@ -69,6 +69,7 @@ object PresentBackgroundJobs extends BackgroundJobsHelper { PresentationRecord.ProtocolState.PresentationReceived ) .mapError(err => Throwable(s"Error occurred while getting Presentation records: $err")) + _ <- ZIO.logInfo(s"Processing ${records.size} Presentation records") _ <- ZIO .foreachPar(records)(performPresentProofExchange) .withParallelism(config.pollux.presentationBgJobProcessingParallelism) @@ -97,17 +98,41 @@ object PresentBackgroundJobs extends BackgroundJobsHelper { for { _ <- ZIO.logDebug(s"Running action with records => $record") _ <- record match { - case PresentationRecord(_, _, _, _, _, _, _, _, InvitationGenerated, _, _, _, _, _, _, _, _, _, _, _, _, _) => + case PresentationRecord( + _, + _, + _, + _, + _, + _, + _, + _, + InvitationGenerated, + _, + _, + _, + _, + _, + _, + _, + _, + _, + _, + _, + _, + _, + _ + ) => ZIO.unit - case PresentationRecord(_, _, _, _, _, _, _, _, InvitationExpired, _, _, _, _, _, _, _, _, _, _, _, _, _) => + case PresentationRecord(_, _, _, _, _, _, _, _, InvitationExpired, _, _, _, _, _, _, _, _, _, _, _, _, _, _) => ZIO.unit - case PresentationRecord(id, _, _, _, _, _, _, _, ProposalPending, _, _, _, _, _, _, _, _, _, _, _, _, _) => + case PresentationRecord(id, _, _, _, _, _, _, _, ProposalPending, _, _, _, _, _, _, _, _, _, _, _, _, _, _) => ZIO.fail(NotImplemented) - case PresentationRecord(id, _, _, _, _, _, _, _, ProposalSent, _, _, _, _, _, _, _, _, _, _, _, _, _) => + case PresentationRecord(id, _, _, _, _, _, _, _, ProposalSent, _, _, _, _, _, _, _, _, _, _, _, _, _, _) => ZIO.fail(NotImplemented) - case PresentationRecord(id, _, _, _, _, _, _, _, ProposalReceived, _, _, _, _, _, _, _, _, _, _, _, _, _) => + case PresentationRecord(id, _, _, _, _, _, _, _, ProposalReceived, _, _, _, _, _, _, _, _, _, _, _, _, _, _) => ZIO.fail(NotImplemented) - case PresentationRecord(id, _, _, _, _, _, _, _, ProposalRejected, _, _, _, _, _, _, _, _, _, _, _, _, _) => + case PresentationRecord(id, _, _, _, _, _, _, _, ProposalRejected, _, _, _, _, _, _, _, _, _, _, _, _, _, _) => ZIO.fail(NotImplemented) case PresentationRecord( id, @@ -131,6 +156,7 @@ object PresentBackgroundJobs extends BackgroundJobsHelper { _, _, _, + _, _ ) => // Verifier ZIO.fail(InvalidState("PresentationRecord 'RequestPending' with no Record")) @@ -156,6 +182,7 @@ object PresentBackgroundJobs extends BackgroundJobsHelper { _, _, _, + _, _ ) => // Verifier Verifier.handleRequestPending(id, requestPresentation) @@ -181,6 +208,7 @@ object PresentBackgroundJobs extends BackgroundJobsHelper { _, _, _, + _, _ ) => // Verifier ZIO.logDebug("PresentationRecord: RequestSent") *> ZIO.unit @@ -206,6 +234,7 @@ object PresentBackgroundJobs extends BackgroundJobsHelper { _, _, _, + _, _ ) => // Prover ZIO.logDebug("PresentationRecord: RequestReceived") *> ZIO.unit @@ -231,12 +260,37 @@ object PresentBackgroundJobs extends BackgroundJobsHelper { _, _, _, + _, _ ) => // Prover ZIO.logDebug("PresentationRecord: RequestRejected") *> ZIO.unit - case PresentationRecord(id, _, _, _, _, _, _, _, ProblemReportPending, _, _, _, _, _, _, _, _, _, _, _, _, _) => + case PresentationRecord( + id, + _, + _, + _, + _, + _, + _, + _, + ProblemReportPending, + _, + _, + _, + _, + _, + _, + _, + _, + _, + _, + _, + _, + _, + _ + ) => ZIO.fail(NotImplemented) - case PresentationRecord(id, _, _, _, _, _, _, _, ProblemReportSent, _, _, _, _, _, _, _, _, _, _, _, _, _) => + case PresentationRecord(id, _, _, _, _, _, _, _, ProblemReportSent, _, _, _, _, _, _, _, _, _, _, _, _, _, _) => ZIO.fail(NotImplemented) case PresentationRecord( id, @@ -260,6 +314,7 @@ object PresentBackgroundJobs extends BackgroundJobsHelper { _, _, _, + _, _ ) => ZIO.fail(NotImplemented) @@ -285,6 +340,7 @@ object PresentBackgroundJobs extends BackgroundJobsHelper { _, _, _, + _, _ ) => // Prover ZIO.fail(InvalidState("PresentationRecord 'RequestPending' with no Record")) @@ -311,6 +367,7 @@ object PresentBackgroundJobs extends BackgroundJobsHelper { _, _, _, + _, _ ) => // Prover Prover.PresentationPending.handle( @@ -343,6 +400,7 @@ object PresentBackgroundJobs extends BackgroundJobsHelper { _, _, _, + _, _ ) => // Prover ZIO.fail(InvalidState("PresentationRecord in 'PresentationGenerated' with no Presentation")) @@ -369,12 +427,13 @@ object PresentBackgroundJobs extends BackgroundJobsHelper { _, _, _, + _, _ ) => // Prover ZIO.logDebug("PresentationRecord: PresentationGenerated") *> ZIO.unit Prover.handlePresentationGenerated(id, presentation) - case PresentationRecord(id, _, _, _, _, _, _, _, PresentationSent, _, _, _, _, _, _, _, _, _, _, _, _, _) => + case PresentationRecord(id, _, _, _, _, _, _, _, PresentationSent, _, _, _, _, _, _, _, _, _, _, _, _, _, _) => ZIO.logDebug("PresentationRecord: PresentationSent") *> ZIO.unit case PresentationRecord( id, @@ -398,6 +457,7 @@ object PresentBackgroundJobs extends BackgroundJobsHelper { _, _, _, + _, _ ) => // Verifier ZIO.fail(InvalidState("PresentationRecord in 'PresentationReceived' with no Presentation")) @@ -423,6 +483,7 @@ object PresentBackgroundJobs extends BackgroundJobsHelper { _, _, _, + _, _ ) => ZIO.fail(InvalidState("PresentationRecord in 'PresentationReceived' with no Presentation Request")) @@ -448,6 +509,7 @@ object PresentBackgroundJobs extends BackgroundJobsHelper { _, _, _, + _, _ ) => // Verifier ZIO.logDebug("PresentationRecord: PresentationReceived") *> ZIO.unit @@ -475,14 +537,87 @@ object PresentBackgroundJobs extends BackgroundJobsHelper { _, _, _, + _, _ ) => ZIO.logDebug("PresentationRecord: PresentationVerificationFailed") *> ZIO.unit - case PresentationRecord(id, _, _, _, _, _, _, _, PresentationAccepted, _, _, _, _, _, _, _, _, _, _, _, _, _) => + case PresentationRecord( + id, + _, + _, + _, + _, + _, + _, + _, + PresentationAccepted, + _, + _, + _, + _, + _, + _, + _, + _, + _, + _, + _, + _, + _, + _ + ) => ZIO.logDebug("PresentationRecord: PresentationVerifiedAccepted") *> ZIO.unit - case PresentationRecord(id, _, _, _, _, _, _, _, PresentationVerified, _, _, _, _, _, _, _, _, _, _, _, _, _) => + case PresentationRecord( + id, + _, + _, + _, + _, + _, + _, + _, + PresentationVerified, + _, + _, + _, + _, + _, + _, + _, + _, + _, + _, + _, + _, + _, + _ + ) => ZIO.logDebug("PresentationRecord: PresentationVerified") *> ZIO.unit - case PresentationRecord(id, _, _, _, _, _, _, _, PresentationRejected, _, _, _, _, _, _, _, _, _, _, _, _, _) => + case PresentationRecord( + id, + _, + _, + _, + _, + _, + _, + _, + PresentationRejected, + _, + _, + _, + _, + _, + _, + _, + _, + _, + _, + _, + _, + _, + _ + ) => ZIO.logDebug("PresentationRecord: PresentationRejected") *> ZIO.unit case _ => ZIO.logWarning(s"Unhandled PresentationRecord state: ${record.protocolState}") diff --git a/cloud-agent/service/server/src/test/scala/org/hyperledger/identus/issue/controller/IssueControllerImplSpec.scala b/cloud-agent/service/server/src/test/scala/org/hyperledger/identus/issue/controller/IssueControllerImplSpec.scala index 4762ad6522..8c434c5345 100644 --- a/cloud-agent/service/server/src/test/scala/org/hyperledger/identus/issue/controller/IssueControllerImplSpec.scala +++ b/cloud-agent/service/server/src/test/scala/org/hyperledger/identus/issue/controller/IssueControllerImplSpec.scala @@ -22,6 +22,7 @@ import org.hyperledger.identus.mercury.protocol.invitation.v2.Invitation import org.hyperledger.identus.pollux.core.model.{CredentialFormat, DidCommID, IssueCredentialRecord} import org.hyperledger.identus.pollux.core.model.IssueCredentialRecord.{ProtocolState, Role} import org.hyperledger.identus.pollux.core.service.MockCredentialService +import org.hyperledger.identus.shared.models.WalletId import sttp.client3.{basicRequest, DeserializationException, UriContext} import sttp.client3.ziojson.* import sttp.model.StatusCode @@ -114,7 +115,8 @@ object IssueControllerImplSpec extends ZIOSpecDefault with IssueControllerTestTo Some(connectionResponse), 5, None, - None + None, + WalletId.fromUUID(UUID.randomUUID) ) val acceptCredentialOfferRequest = AcceptCredentialOfferRequest( Some( diff --git a/connect/core/src/main/scala/org/hyperledger/identus/connect/core/model/ConnectionRecord.scala b/connect/core/src/main/scala/org/hyperledger/identus/connect/core/model/ConnectionRecord.scala index db640624d2..1d215cc9fb 100644 --- a/connect/core/src/main/scala/org/hyperledger/identus/connect/core/model/ConnectionRecord.scala +++ b/connect/core/src/main/scala/org/hyperledger/identus/connect/core/model/ConnectionRecord.scala @@ -4,6 +4,9 @@ import org.hyperledger.identus.connect.core.model.ConnectionRecord.{ProtocolStat import org.hyperledger.identus.mercury.protocol.connection.{ConnectionRequest, ConnectionResponse} import org.hyperledger.identus.mercury.protocol.invitation.v2.Invitation import org.hyperledger.identus.shared.models.Failure +import org.hyperledger.identus.shared.models.WalletAccessContext +import org.hyperledger.identus.shared.models.WalletId +import zio.ZIO import java.time.temporal.ChronoUnit import java.time.Instant @@ -43,7 +46,8 @@ case class ConnectionRecord( connectionResponse: Option[ConnectionResponse], metaRetries: Int, metaNextRetry: Option[Instant], - metaLastFailure: Option[Failure] + metaLastFailure: Option[Failure], + walletId: WalletId, ) { def withTruncatedTimestamp(unit: ChronoUnit = ChronoUnit.MICROS): ConnectionRecord = copy( createdAt = createdAt.truncatedTo(unit), @@ -52,6 +56,51 @@ case class ConnectionRecord( ) } +/** Like [[ConnectionRecordBefore]] but without the walletId */ +case class ConnectionRecordBeforeStored( + id: UUID, + createdAt: Instant, + updatedAt: Option[Instant], + thid: String, + label: Option[String], + goalCode: Option[String], + goal: Option[String], + role: Role, + protocolState: ProtocolState, + invitation: Invitation, + connectionRequest: Option[ConnectionRequest], + connectionResponse: Option[ConnectionResponse], + metaRetries: Int, + metaNextRetry: Option[Instant], + metaLastFailure: Option[Failure], +) { + + def withTruncatedTimestamp(unit: ChronoUnit = ChronoUnit.MICROS) = copy( + createdAt = createdAt.truncatedTo(unit), + updatedAt = updatedAt.map(_.truncatedTo(unit)), + metaNextRetry = metaNextRetry.map(_.truncatedTo(unit)) + ) + + def withWalletId(walletId: WalletId): ConnectionRecord = ConnectionRecord( + id = id, + createdAt = createdAt, + updatedAt = updatedAt, + thid = thid, + label = label, + goalCode = goalCode, + goal = goal, + role = role, + protocolState = protocolState, + invitation = invitation, + connectionRequest = connectionRequest, + connectionResponse = connectionResponse, + metaRetries = metaRetries, + metaNextRetry = metaNextRetry, + metaLastFailure = metaLastFailure, + walletId = walletId + ) +} + object ConnectionRecord { enum Role: case Inviter extends Role diff --git a/connect/core/src/main/scala/org/hyperledger/identus/connect/core/repository/ConnectionRepository.scala b/connect/core/src/main/scala/org/hyperledger/identus/connect/core/repository/ConnectionRepository.scala index 9d25fc133a..854470d986 100644 --- a/connect/core/src/main/scala/org/hyperledger/identus/connect/core/repository/ConnectionRepository.scala +++ b/connect/core/src/main/scala/org/hyperledger/identus/connect/core/repository/ConnectionRepository.scala @@ -1,6 +1,6 @@ package org.hyperledger.identus.connect.core.repository -import org.hyperledger.identus.connect.core.model.ConnectionRecord +import org.hyperledger.identus.connect.core.model.{ConnectionRecord, ConnectionRecordBeforeStored} import org.hyperledger.identus.connect.core.model.ConnectionRecord.ProtocolState import org.hyperledger.identus.mercury.protocol.connection.* import org.hyperledger.identus.shared.models.{Failure, WalletAccessContext} @@ -11,7 +11,7 @@ import java.util.UUID trait ConnectionRepository { def create( - record: ConnectionRecord + record: ConnectionRecordBeforeStored ): URIO[WalletAccessContext, Unit] def findAll: URIO[WalletAccessContext, Seq[ConnectionRecord]] diff --git a/connect/core/src/main/scala/org/hyperledger/identus/connect/core/service/ConnectionServiceImpl.scala b/connect/core/src/main/scala/org/hyperledger/identus/connect/core/service/ConnectionServiceImpl.scala index cd703af4b1..a4072aea05 100644 --- a/connect/core/src/main/scala/org/hyperledger/identus/connect/core/service/ConnectionServiceImpl.scala +++ b/connect/core/src/main/scala/org/hyperledger/identus/connect/core/service/ConnectionServiceImpl.scala @@ -1,9 +1,9 @@ package org.hyperledger.identus.connect.core.service import org.hyperledger.identus.* +import org.hyperledger.identus.connect.core.model.{ConnectionRecord, ConnectionRecordBeforeStored} import org.hyperledger.identus.connect.core.model.error.ConnectionServiceError import org.hyperledger.identus.connect.core.model.error.ConnectionServiceError.* -import org.hyperledger.identus.connect.core.model.ConnectionRecord import org.hyperledger.identus.connect.core.model.ConnectionRecord.* import org.hyperledger.identus.connect.core.repository.ConnectionRepository import org.hyperledger.identus.mercury.model.DidId @@ -32,9 +32,10 @@ private class ConnectionServiceImpl( ): ZIO[WalletAccessContext, UserInputValidationError, ConnectionRecord] = for { _ <- validateInputs(label, goalCode, goal) + wallet <- ZIO.service[WalletAccessContext] invitation <- ZIO.succeed(ConnectionInvitation.makeConnectionInvitation(pairwiseDID, goalCode, goal)) record <- ZIO.succeed( - ConnectionRecord( + ConnectionRecordBeforeStored( id = UUID.fromString(invitation.id), createdAt = Instant.now, updatedAt = None, @@ -53,7 +54,7 @@ private class ConnectionServiceImpl( ) ) count <- connectionRepository.create(record) - } yield record + } yield record.withWalletId(wallet.walletId) private def validateInputs( label: Option[String], @@ -109,8 +110,9 @@ private class ConnectionServiceImpl( .mapError(err => InvitationParsingError(err.getMessage)) maybeRecord <- connectionRepository.findByThreadId(invitation.id) _ <- ZIO.noneOrFailWith(maybeRecord)(_ => InvitationAlreadyReceived(invitation.id)) + wallet <- ZIO.service[WalletAccessContext] record <- ZIO.succeed( - ConnectionRecord( + ConnectionRecordBeforeStored( id = UUID.randomUUID(), createdAt = Instant.now, updatedAt = None, @@ -129,7 +131,7 @@ private class ConnectionServiceImpl( ) ) _ <- connectionRepository.create(record) - } yield record + } yield record.withWalletId(wallet.walletId) override def acceptConnectionInvitation( recordId: UUID, diff --git a/connect/core/src/main/scala/org/hyperledger/identus/connect/core/service/ConnectionServiceNotifier.scala b/connect/core/src/main/scala/org/hyperledger/identus/connect/core/service/ConnectionServiceNotifier.scala index 8037fb1ed8..d67f0ba729 100644 --- a/connect/core/src/main/scala/org/hyperledger/identus/connect/core/service/ConnectionServiceNotifier.scala +++ b/connect/core/src/main/scala/org/hyperledger/identus/connect/core/service/ConnectionServiceNotifier.scala @@ -3,6 +3,7 @@ package org.hyperledger.identus.connect.core.service import org.hyperledger.identus.connect.core.model.error.ConnectionServiceError import org.hyperledger.identus.connect.core.model.error.ConnectionServiceError.* import org.hyperledger.identus.connect.core.model.ConnectionRecord +import org.hyperledger.identus.connect.core.repository.ConnectionRepository import org.hyperledger.identus.event.notification.{Event, EventNotificationService} import org.hyperledger.identus.mercury.model.DidId import org.hyperledger.identus.mercury.protocol.connection.{ConnectionRequest, ConnectionResponse} @@ -14,7 +15,8 @@ import java.util.UUID class ConnectionServiceNotifier( svc: ConnectionService, - eventNotificationService: EventNotificationService + eventNotificationService: EventNotificationService, + connectionRepository: ConnectionRepository, ) extends ConnectionService { private val connectionUpdatedEvent = "ConnectionUpdated" @@ -74,10 +76,10 @@ class ConnectionServiceNotifier( notifyOnSuccess(svc.receiveConnectionResponse(response)) private def notifyOnSuccess[E](effect: ZIO[WalletAccessContext, E, ConnectionRecord]) = - for { - record <- effect - _ <- notify(record) - } yield record + effect.tap(record => notify(record)) + + private def notifyOnFail(record: ConnectionRecord) = + notify(record) private def notify(record: ConnectionRecord) = { val result = for { @@ -104,8 +106,11 @@ class ConnectionServiceNotifier( override def reportProcessingFailure( recordId: UUID, failReason: Option[Failure] - ): URIO[WalletAccessContext, Unit] = - svc.reportProcessingFailure(recordId, failReason) + ): URIO[WalletAccessContext, Unit] = for { + ret <- svc.reportProcessingFailure(recordId, failReason) + recordAfterFail <- connectionRepository.getById(recordId) + _ <- notifyOnFail(recordAfterFail) + } yield ret override def findAllRecords(): URIO[WalletAccessContext, Seq[ConnectionRecord]] = svc.findAllRecords() @@ -126,6 +131,6 @@ class ConnectionServiceNotifier( } object ConnectionServiceNotifier { - val layer: URLayer[ConnectionService & EventNotificationService, ConnectionService] = - ZLayer.fromFunction(ConnectionServiceNotifier(_, _)) + val layer: URLayer[ConnectionService & EventNotificationService & ConnectionRepository, ConnectionService] = + ZLayer.fromFunction(ConnectionServiceNotifier(_, _, _)) } diff --git a/connect/core/src/test/scala/org/hyperledger/identus/connect/core/repository/ConnectionRepositoryInMemory.scala b/connect/core/src/test/scala/org/hyperledger/identus/connect/core/repository/ConnectionRepositoryInMemory.scala index 316abdc6c3..f47e03a3d9 100644 --- a/connect/core/src/test/scala/org/hyperledger/identus/connect/core/repository/ConnectionRepositoryInMemory.scala +++ b/connect/core/src/test/scala/org/hyperledger/identus/connect/core/repository/ConnectionRepositoryInMemory.scala @@ -1,6 +1,6 @@ package org.hyperledger.identus.connect.core.repository -import org.hyperledger.identus.connect.core.model.ConnectionRecord +import org.hyperledger.identus.connect.core.model.{ConnectionRecord, ConnectionRecordBeforeStored} import org.hyperledger.identus.connect.core.model.ConnectionRecord.ProtocolState import org.hyperledger.identus.mercury.protocol.connection.{ConnectionRequest, ConnectionResponse} import org.hyperledger.identus.shared.models.* @@ -202,7 +202,7 @@ class ConnectionRepositoryInMemory(walletRefs: Ref[Map[WalletId, Ref[Map[UUID, C } } - override def create(record: ConnectionRecord): URIO[WalletAccessContext, Unit] = { + override def create(record: ConnectionRecordBeforeStored): URIO[WalletAccessContext, Unit] = { for { _ <- for { storeRef <- walletStoreRef @@ -213,7 +213,8 @@ class ConnectionRepositoryInMemory(walletRefs: Ref[Map[WalletId, Ref[Map[UUID, C case None => ZIO.unit } yield () storeRef <- walletStoreRef - _ <- storeRef.update(r => r + (record.id -> record)) + walletId <- ZIO.service[WalletAccessContext].map(_.walletId) + _ <- storeRef.update(r => r + (record.id -> record.withWalletId(walletId))) } yield () } diff --git a/connect/core/src/test/scala/org/hyperledger/identus/connect/core/repository/ConnectionRepositorySpecSuite.scala b/connect/core/src/test/scala/org/hyperledger/identus/connect/core/repository/ConnectionRepositorySpecSuite.scala index cb795b00b2..de0d3742c3 100644 --- a/connect/core/src/test/scala/org/hyperledger/identus/connect/core/repository/ConnectionRepositorySpecSuite.scala +++ b/connect/core/src/test/scala/org/hyperledger/identus/connect/core/repository/ConnectionRepositorySpecSuite.scala @@ -1,6 +1,6 @@ package org.hyperledger.identus.connect.core.repository -import org.hyperledger.identus.connect.core.model.ConnectionRecord +import org.hyperledger.identus.connect.core.model.{ConnectionRecord, ConnectionRecordBeforeStored} import org.hyperledger.identus.connect.core.model.ConnectionRecord.* import org.hyperledger.identus.mercury.model.DidId import org.hyperledger.identus.mercury.protocol.connection.{ConnectionRequest, ConnectionResponse} @@ -18,7 +18,7 @@ object ConnectionRepositorySpecSuite { val maxRetries = 2 - private def connectionRecord = ConnectionRecord( + private def connectionRecord = ConnectionRecordBeforeStored( UUID.randomUUID, Instant.now.truncatedTo(ChronoUnit.MICROS), None, @@ -42,7 +42,7 @@ object ConnectionRepositorySpecSuite { None, maxRetries, Some(Instant.now.truncatedTo(ChronoUnit.MICROS)), - None + None, ).withTruncatedTimestamp() private def connectionRequest = ConnectionRequest( @@ -84,7 +84,8 @@ object ConnectionRepositorySpecSuite { _ <- repo.create(aRecord) _ <- repo.create(bRecord) record <- repo.findById(bRecord.id) - } yield assertTrue(record.contains(bRecord)) + walletId <- ZIO.service[WalletAccessContext].map(_.walletId) + } yield assertTrue(record.contains(bRecord.withWalletId(walletId))) }, test("getConnectionRecord returns None for an unknown record") { for { @@ -104,10 +105,11 @@ object ConnectionRepositorySpecSuite { _ <- repo.create(aRecord) _ <- repo.create(bRecord) records <- repo.findAll + walletId <- ZIO.service[WalletAccessContext].map(_.walletId) } yield { assertTrue(records.size == 2) && - assertTrue(records.contains(aRecord)) && - assertTrue(records.contains(bRecord)) + assertTrue(records.contains(aRecord.withWalletId(walletId))) && + assertTrue(records.contains(bRecord.withWalletId(walletId))) } }, test("getConnectionRecordsByStates returns correct records") { @@ -142,9 +144,10 @@ object ConnectionRepositorySpecSuite { ProtocolState.ConnectionRequestReceived, ProtocolState.ConnectionResponsePending ) + walletId <- ZIO.service[WalletAccessContext].map(_.walletId) } yield { assertTrue(invitationGeneratedRecords.size == 1) && - assertTrue(invitationGeneratedRecords.contains(bRecord)) && + assertTrue(invitationGeneratedRecords.contains(bRecord.withWalletId(walletId))) && assertTrue(otherRecords.size == 2) && assertTrue(otherRecords.exists(_.id == aRecord.id)) && assertTrue(otherRecords.exists(_.id == cRecord.id)) @@ -191,9 +194,10 @@ object ConnectionRepositorySpecSuite { _ <- repo.create(bRecord) _ <- repo.deleteById(aRecord.id) records <- repo.findAll + walletId <- ZIO.service[WalletAccessContext].map(_.walletId) } yield { assertTrue(records.size == 1) && - assertTrue(records.contains(bRecord)) + assertTrue(records.contains(bRecord.withWalletId(walletId))) } }, test("deleteRecord does nothing for an unknown record") { @@ -205,14 +209,15 @@ object ConnectionRepositorySpecSuite { _ <- repo.create(bRecord) deleteResult <- repo.deleteById(UUID.randomUUID).exit records <- repo.findAll + walletId <- ZIO.service[WalletAccessContext].map(_.walletId) } yield { assertTrue(deleteResult match case Exit.Failure(cause: Cause.Die) => true case _ => false ) && assertTrue(records.size == 2) && - assertTrue(records.contains(aRecord)) && - assertTrue(records.contains(bRecord)) + assertTrue(records.contains(aRecord.withWalletId(walletId))) && + assertTrue(records.contains(bRecord.withWalletId(walletId))) } }, test("getConnectionRecordByThreadId correctly returns an existing thid") { @@ -224,7 +229,8 @@ object ConnectionRepositorySpecSuite { _ <- repo.create(aRecord) _ <- repo.create(bRecord) record <- repo.findByThreadId(thid) - } yield assertTrue(record.contains(aRecord)) + walletId <- ZIO.service[WalletAccessContext].map(_.walletId) + } yield assertTrue(record.contains(aRecord.withWalletId(walletId))) }, test("getConnectionRecordByThreadId returns nothing for an unknown thid") { for { diff --git a/connect/core/src/test/scala/org/hyperledger/identus/connect/core/service/ConnectionServiceNotifierSpec.scala b/connect/core/src/test/scala/org/hyperledger/identus/connect/core/service/ConnectionServiceNotifierSpec.scala index 966be4919e..b9e54811b9 100644 --- a/connect/core/src/test/scala/org/hyperledger/identus/connect/core/service/ConnectionServiceNotifierSpec.scala +++ b/connect/core/src/test/scala/org/hyperledger/identus/connect/core/service/ConnectionServiceNotifierSpec.scala @@ -33,7 +33,8 @@ object ConnectionServiceNotifierSpec extends ZIOSpecDefault { None, 5, None, - None + None, + WalletId.fromUUID(UUID.randomUUID) ) private val inviterExpectations = @@ -102,7 +103,10 @@ object ConnectionServiceNotifierSpec extends ZIOSpecDefault { } }.provide( ZLayer.succeed(50) >>> EventNotificationServiceImpl.layer, - inviterExpectations.toLayer >>> ConnectionServiceNotifier.layer, + ( + ConnectionRepositoryInMemory.layer ++ + inviterExpectations.toLayer + ) >>> ConnectionServiceNotifier.layer, ZLayer.succeed(WalletAccessContext(WalletId.random)) ), test("should send relevant events during flow execution on the invitee side") { @@ -143,7 +147,10 @@ object ConnectionServiceNotifierSpec extends ZIOSpecDefault { } }.provide( ZLayer.succeed(50) >>> EventNotificationServiceImpl.layer, - inviteeExpectations.toLayer >>> ConnectionServiceNotifier.layer, + ( + ConnectionRepositoryInMemory.layer ++ + inviteeExpectations.toLayer + ) >>> ConnectionServiceNotifier.layer, ZLayer.succeed(WalletAccessContext(WalletId.random)) ) ) diff --git a/connect/sql-doobie/src/main/scala/org/hyperledger/identus/connect/sql/repository/JdbcConnectionRepository.scala b/connect/sql-doobie/src/main/scala/org/hyperledger/identus/connect/sql/repository/JdbcConnectionRepository.scala index 18d8a1ac05..8b8b450394 100644 --- a/connect/sql-doobie/src/main/scala/org/hyperledger/identus/connect/sql/repository/JdbcConnectionRepository.scala +++ b/connect/sql-doobie/src/main/scala/org/hyperledger/identus/connect/sql/repository/JdbcConnectionRepository.scala @@ -49,7 +49,10 @@ class JdbcConnectionRepository(xa: Transactor[ContextAwareTask], xb: Transactor[ given failureGet: Get[Failure] = Get[String].temap(_.fromJson[FailureInfo]) given failurePut: Put[Failure] = Put[String].contramap(_.asFailureInfo.toJson) - override def create(record: ConnectionRecord): URIO[WalletAccessContext, Unit] = { + given walletIdGet: Get[WalletId] = Get[UUID].map(id => WalletId.fromUUID(id)) + given walletIdPut: Put[WalletId] = Put[UUID].contramap[WalletId](_.toUUID) + + override def create(record: ConnectionRecordBeforeStored): URIO[WalletAccessContext, Unit] = { val cxnIO = sql""" | INSERT INTO public.connection_records( | id, @@ -106,7 +109,8 @@ class JdbcConnectionRepository(xa: Transactor[ContextAwareTask], xb: Transactor[ | connection_response, | meta_retries, | meta_next_retry, - | meta_last_failure + | meta_last_failure, + | wallet_id | FROM public.connection_records | ORDER BY created_at """.stripMargin @@ -169,7 +173,8 @@ class JdbcConnectionRepository(xa: Transactor[ContextAwareTask], xb: Transactor[ | connection_response, | meta_retries, | meta_next_retry, - | meta_last_failure + | meta_last_failure, + | wallet_id | FROM public.connection_records | $conditionFragment | ORDER BY created_at @@ -198,7 +203,8 @@ class JdbcConnectionRepository(xa: Transactor[ContextAwareTask], xb: Transactor[ | connection_response, | meta_retries, | meta_next_retry, - | meta_last_failure + | meta_last_failure, + | wallet_id | FROM public.connection_records | WHERE id = $recordId """.stripMargin @@ -245,7 +251,8 @@ class JdbcConnectionRepository(xa: Transactor[ContextAwareTask], xb: Transactor[ | connection_response, | meta_retries, | meta_next_retry, - | meta_last_failure + | meta_last_failure, + | wallet_id | FROM public.connection_records | WHERE thid = $thid """.stripMargin // | WHERE thid = $thid OR id = $thid diff --git a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/model/PresentationRecord.scala b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/model/PresentationRecord.scala index d6fbaa972e..886d44caa1 100644 --- a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/model/PresentationRecord.scala +++ b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/model/PresentationRecord.scala @@ -3,7 +3,8 @@ package org.hyperledger.identus.pollux.core.model import org.hyperledger.identus.mercury.model.DidId import org.hyperledger.identus.mercury.protocol.invitation.v2.Invitation import org.hyperledger.identus.mercury.protocol.presentproof.{Presentation, ProposePresentation, RequestPresentation} -import org.hyperledger.identus.shared.models.Failure +import org.hyperledger.identus.shared.models.{Failure, WalletAccessContext, WalletId} +import zio.{UIO, URIO, ZIO} import java.time.temporal.ChronoUnit import java.time.Instant @@ -34,6 +35,7 @@ final case class PresentationRecord( metaRetries: Int, metaNextRetry: Option[Instant], metaLastFailure: Option[Failure], + walletId: WalletId, ) { def withTruncatedTimestamp(unit: ChronoUnit = ChronoUnit.MICROS): PresentationRecord = copy( @@ -45,6 +47,58 @@ final case class PresentationRecord( object PresentationRecord { + def make( + id: DidCommID, + createdAt: Instant, + updatedAt: Option[Instant], + thid: DidCommID, + schemaId: Option[String], + connectionId: Option[String], + role: Role, + subjectId: DidId, + protocolState: ProtocolState, + credentialFormat: CredentialFormat, + invitation: Option[Invitation], + requestPresentationData: Option[RequestPresentation], + proposePresentationData: Option[ProposePresentation], + presentationData: Option[Presentation], + credentialsToUse: Option[List[String]], + anoncredCredentialsToUseJsonSchemaId: Option[String], + anoncredCredentialsToUse: Option[AnoncredCredentialProofs], + sdJwtClaimsToUseJsonSchemaId: Option[String], + sdJwtClaimsToDisclose: Option[SdJwtCredentialToDisclose], + metaRetries: Int, + metaNextRetry: Option[Instant], + metaLastFailure: Option[Failure] + ): URIO[WalletAccessContext, PresentationRecord] = + ZIO.serviceWith[WalletAccessContext] { walletAccessContext => + PresentationRecord( + id, + createdAt, + updatedAt, + thid, + schemaId, + connectionId, + role, + subjectId, + protocolState, + credentialFormat, + invitation, + requestPresentationData, + proposePresentationData, + presentationData, + credentialsToUse, + anoncredCredentialsToUseJsonSchemaId, + anoncredCredentialsToUse, + sdJwtClaimsToUseJsonSchemaId, + sdJwtClaimsToDisclose, + metaRetries, + metaNextRetry, + metaLastFailure, + walletAccessContext.walletId, + ) + } + enum Role: case Verifier extends Role case Prover extends Role diff --git a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/repository/PresentationRepository.scala b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/repository/PresentationRepository.scala index fffd057a59..55b7443a0e 100644 --- a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/repository/PresentationRepository.scala +++ b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/repository/PresentationRepository.scala @@ -27,6 +27,8 @@ trait PresentationRepository { def findPresentationRecordByThreadId(thid: DidCommID): URIO[WalletAccessContext, Option[PresentationRecord]] + def getPresentationRecordByDIDCommID(recordId: DidCommID): UIO[Option[PresentationRecord]] + def updatePresentationRecordProtocolState( recordId: DidCommID, from: PresentationRecord.ProtocolState, diff --git a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/CredentialServiceNotifier.scala b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/CredentialServiceNotifier.scala index ab1ecf2e8c..faf93f651a 100644 --- a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/CredentialServiceNotifier.scala +++ b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/CredentialServiceNotifier.scala @@ -8,6 +8,7 @@ import org.hyperledger.identus.mercury.protocol.issuecredential.{IssueCredential import org.hyperledger.identus.pollux.core.model.{DidCommID, IssueCredentialRecord} import org.hyperledger.identus.pollux.core.model.error.CredentialServiceError import org.hyperledger.identus.pollux.core.model.error.CredentialServiceError.* +import org.hyperledger.identus.pollux.core.repository.CredentialRepository import org.hyperledger.identus.pollux.vc.jwt.Issuer import org.hyperledger.identus.shared.models.* import zio.{Duration, UIO, URIO, URLayer, ZIO, ZLayer} @@ -16,7 +17,8 @@ import java.util.UUID class CredentialServiceNotifier( svc: CredentialService, - eventNotificationService: EventNotificationService + eventNotificationService: EventNotificationService, + credentialRepository: CredentialRepository, ) extends CredentialService { private val issueCredentialRecordUpdatedEvent = "IssueCredentialRecordUpdated" @@ -176,6 +178,9 @@ class CredentialServiceNotifier( _ <- notify(record) } yield record + private def notifyOnFail(record: IssueCredentialRecord) = + notify(record) + private def notify(record: IssueCredentialRecord) = { val result = for { walletId <- ZIO.serviceWith[WalletAccessContext](_.walletId) @@ -188,8 +193,11 @@ class CredentialServiceNotifier( override def reportProcessingFailure( recordId: DidCommID, failReason: Option[Failure] - ): URIO[WalletAccessContext, Unit] = - svc.reportProcessingFailure(recordId, failReason) + ): URIO[WalletAccessContext, Unit] = for { + ret <- svc.reportProcessingFailure(recordId, failReason) + recordAfterFail <- credentialRepository.getById(recordId) + _ <- notifyOnFail(recordAfterFail) + } yield ret override def findById( recordId: DidCommID @@ -237,6 +245,6 @@ class CredentialServiceNotifier( } object CredentialServiceNotifier { - val layer: URLayer[CredentialService & EventNotificationService, CredentialServiceNotifier] = - ZLayer.fromFunction(CredentialServiceNotifier(_, _)) + val layer: URLayer[CredentialService & EventNotificationService & CredentialRepository, CredentialServiceNotifier] = + ZLayer.fromFunction(CredentialServiceNotifier(_, _, _)) } diff --git a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/PresentationServiceImpl.scala b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/PresentationServiceImpl.scala index 49789d2c1d..3e8c8a5784 100644 --- a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/PresentationServiceImpl.scala +++ b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/PresentationServiceImpl.scala @@ -413,33 +413,31 @@ private class PresentationServiceImpl( ) )(_ => None) - record <- ZIO.succeed( - PresentationRecord( - id = DidCommID(), - createdAt = Instant.now, - updatedAt = None, - thid = thid, - connectionId = connectionId, - schemaId = None, // TODO REMOVE from DB - role = PresentationRecord.Role.Verifier, - subjectId = pairwiseProverDID.getOrElse(DidId("TODO REMOVE")), // TODO REMOVE from DB - protocolState = invitation.fold(PresentationRecord.ProtocolState.RequestPending)(_ => - PresentationRecord.ProtocolState.InvitationGenerated - ), - credentialFormat = format, - invitation = invitation, - requestPresentationData = Some(request), - proposePresentationData = None, - presentationData = None, - credentialsToUse = None, - anoncredCredentialsToUseJsonSchemaId = None, - anoncredCredentialsToUse = None, - sdJwtClaimsToUseJsonSchemaId = None, - sdJwtClaimsToDisclose = None, - metaRetries = maxRetries, - metaNextRetry = Some(Instant.now()), - metaLastFailure = None, - ) + record <- PresentationRecord.make( + id = DidCommID(), + createdAt = Instant.now, + updatedAt = None, + thid = thid, + connectionId = connectionId, + schemaId = None, // TODO REMOVE from DB + role = PresentationRecord.Role.Verifier, + subjectId = pairwiseProverDID.getOrElse(DidId("TODO REMOVE")), // TODO REMOVE from DB + protocolState = invitation.fold(PresentationRecord.ProtocolState.RequestPending)(_ => + PresentationRecord.ProtocolState.InvitationGenerated + ), + credentialFormat = format, + invitation = invitation, + requestPresentationData = Some(request), + proposePresentationData = None, + presentationData = None, + credentialsToUse = None, + anoncredCredentialsToUseJsonSchemaId = None, + anoncredCredentialsToUse = None, + sdJwtClaimsToUseJsonSchemaId = None, + sdJwtClaimsToDisclose = None, + metaRetries = maxRetries, + metaNextRetry = Some(Instant.now()), + metaLastFailure = None ) _ <- presentationRepository .createPresentationRecord(record) @@ -493,34 +491,33 @@ private class PresentationServiceImpl( case Some(unsupportedFormat) => ZIO.fail(PresentationError.UnsupportedCredentialFormat(unsupportedFormat)) case _ => ZIO.fail(PresentationError.RequestPresentationHasMultipleAttachment(request.id)) } - record <- ZIO.succeed( - PresentationRecord( - id = DidCommID(), - createdAt = Instant.now, - updatedAt = None, - thid = DidCommID(request.thid.getOrElse(request.id)), - connectionId = connectionId, - schemaId = None, - role = Role.Prover, - subjectId = - request.to.getOrElse(throw RuntimeException(s"RequestPresentation from field is missing")), // TODO REMOVE - protocolState = PresentationRecord.ProtocolState.RequestReceived, - credentialFormat = format, - invitation = None, - requestPresentationData = Some(request), - proposePresentationData = None, - presentationData = None, - credentialsToUse = None, - anoncredCredentialsToUseJsonSchemaId = None, - anoncredCredentialsToUse = None, - sdJwtClaimsToUseJsonSchemaId = None, - sdJwtClaimsToDisclose = None, - metaRetries = maxRetries, - metaNextRetry = Some(Instant.now()), - metaLastFailure = None, - ) + record <- PresentationRecord.make( + id = DidCommID(), + createdAt = Instant.now, + updatedAt = None, + thid = DidCommID(request.thid.getOrElse(request.id)), + connectionId = connectionId, + schemaId = None, + role = Role.Prover, + subjectId = + request.to.getOrElse(throw RuntimeException(s"RequestPresentation from field is missing")), // TODO REMOVE + protocolState = PresentationRecord.ProtocolState.RequestReceived, + credentialFormat = format, + invitation = None, + requestPresentationData = Some(request), + proposePresentationData = None, + presentationData = None, + credentialsToUse = None, + anoncredCredentialsToUseJsonSchemaId = None, + anoncredCredentialsToUse = None, + sdJwtClaimsToUseJsonSchemaId = None, + sdJwtClaimsToDisclose = None, + metaRetries = maxRetries, + metaNextRetry = Some(Instant.now()), + metaLastFailure = None, ) _ <- presentationRepository.createPresentationRecord(record) + _ <- ZIO.logDebug(s"Received and created the RequestPresentation: $request") } yield record } diff --git a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/PresentationServiceNotifier.scala b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/PresentationServiceNotifier.scala index d9afe48cd5..cb7d435905 100644 --- a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/PresentationServiceNotifier.scala +++ b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/PresentationServiceNotifier.scala @@ -12,11 +12,12 @@ import org.hyperledger.identus.pollux.anoncreds.AnoncredPresentation import org.hyperledger.identus.pollux.core.model.{DidCommID, PresentationRecord} import org.hyperledger.identus.pollux.core.model.error.PresentationError import org.hyperledger.identus.pollux.core.model.presentation.Options +import org.hyperledger.identus.pollux.core.repository.PresentationRepository import org.hyperledger.identus.pollux.core.service.serdes.{AnoncredCredentialProofsV1, AnoncredPresentationRequestV1} import org.hyperledger.identus.pollux.sdjwt.{HolderPrivateKey, PresentationCompact} import org.hyperledger.identus.pollux.vc.jwt.{Issuer, PresentationPayload, W3cCredentialPayload} import org.hyperledger.identus.shared.models.* -import zio.{Duration, IO, UIO, URLayer, ZIO, ZLayer} +import zio._ import zio.json.* import java.time.Instant @@ -24,7 +25,8 @@ import java.util.UUID class PresentationServiceNotifier( svc: PresentationService, - eventNotificationService: EventNotificationService + eventNotificationService: EventNotificationService, + presentationRepository: PresentationRepository, ) extends PresentationService { private val presentationUpdatedEvent = "PresentationUpdated" @@ -201,6 +203,10 @@ class PresentationServiceNotifier( _ <- notify(record) } yield record + private def notifyOnFail(record: PresentationRecord, walletId: WalletId) = + notify(record) + .provideEnvironment(ZEnvironment.apply(WalletAccessContext(walletId))) + private def notify(record: PresentationRecord) = { val result = for { walletId <- ZIO.serviceWith[WalletAccessContext](_.walletId) @@ -304,7 +310,16 @@ class PresentationServiceNotifier( override def reportProcessingFailure( recordId: DidCommID, failReason: Option[Failure] - ): UIO[Unit] = svc.reportProcessingFailure(recordId, failReason) + ): UIO[Unit] = + for { + ret <- svc.reportProcessingFailure(recordId, failReason) + mRecordAfterFail <- presentationRepository.getPresentationRecordByDIDCommID(recordId) + _ <- mRecordAfterFail match { + case None => ZIO.unit + case Some(recordAfterFail) => + notifyOnFail(recordAfterFail, recordAfterFail.walletId) + } + } yield ret override def getRequestPresentationFromInvitation( pairwiseProverDID: DidId, @@ -314,6 +329,6 @@ class PresentationServiceNotifier( } object PresentationServiceNotifier { - val layer: URLayer[EventNotificationService & PresentationService, PresentationService] = - ZLayer.fromFunction(PresentationServiceNotifier(_, _)) + val layer: URLayer[EventNotificationService & PresentationService & PresentationRepository, PresentationService] = + ZLayer.fromFunction(PresentationServiceNotifier(_, _, _)) } diff --git a/pollux/core/src/test/scala/org/hyperledger/identus/pollux/core/repository/PresentationRepositoryInMemory.scala b/pollux/core/src/test/scala/org/hyperledger/identus/pollux/core/repository/PresentationRepositoryInMemory.scala index 01d00ed4ea..c858330e01 100644 --- a/pollux/core/src/test/scala/org/hyperledger/identus/pollux/core/repository/PresentationRepositoryInMemory.scala +++ b/pollux/core/src/test/scala/org/hyperledger/identus/pollux/core/repository/PresentationRepositoryInMemory.scala @@ -273,6 +273,14 @@ class PresentationRepositoryInMemory( } yield store.values.find(_.thid == thid).filter(_.metaRetries > 0) } + override def getPresentationRecordByDIDCommID(recordId: DidCommID): UIO[Option[PresentationRecord]] = { + ZIO.none + // for { + // storeRef <- walletStoreRef + // store <- storeRef.get + // } yield store.values.find(_.id == recordId).filter(_.metaRetries > 0) + } + override def updateWithRequestPresentation( recordId: DidCommID, request: RequestPresentation, diff --git a/pollux/core/src/test/scala/org/hyperledger/identus/pollux/core/repository/PresentationRepositorySpecSuite.scala b/pollux/core/src/test/scala/org/hyperledger/identus/pollux/core/repository/PresentationRepositorySpecSuite.scala index 0d1aab356c..5ebfe3233e 100644 --- a/pollux/core/src/test/scala/org/hyperledger/identus/pollux/core/repository/PresentationRepositorySpecSuite.scala +++ b/pollux/core/src/test/scala/org/hyperledger/identus/pollux/core/repository/PresentationRepositorySpecSuite.scala @@ -6,7 +6,7 @@ import org.hyperledger.identus.pollux.core.model.* import org.hyperledger.identus.pollux.core.model.PresentationRecord.* import org.hyperledger.identus.pollux.core.service.serdes.{AnoncredCredentialProofV1, AnoncredCredentialProofsV1} import org.hyperledger.identus.shared.models.* -import zio.{ZIO, ZLayer} +import zio.{URIO, ZIO, ZLayer} import zio.test.* import zio.test.Assertion.* @@ -16,30 +16,32 @@ import java.util.UUID object PresentationRepositorySpecSuite { val maxRetries = 5 // TODO Move to config - private def presentationRecord = PresentationRecord( - id = DidCommID(), - createdAt = Instant.now, - updatedAt = None, - thid = DidCommID(), - schemaId = None, - connectionId = None, - role = PresentationRecord.Role.Verifier, - subjectId = DidId("did:prism:aaa"), - protocolState = PresentationRecord.ProtocolState.RequestPending, - credentialFormat = CredentialFormat.JWT, - invitation = None, - requestPresentationData = None, - proposePresentationData = None, - presentationData = None, - credentialsToUse = None, - anoncredCredentialsToUseJsonSchemaId = None, - anoncredCredentialsToUse = None, - sdJwtClaimsToUseJsonSchemaId = None, - sdJwtClaimsToDisclose = None, - metaRetries = maxRetries, - metaNextRetry = Some(Instant.now()), - metaLastFailure = None, - ).withTruncatedTimestamp() + private def presentationRecord: URIO[WalletAccessContext, PresentationRecord] = PresentationRecord + .make( + id = DidCommID(), + createdAt = Instant.now, + updatedAt = None, + thid = DidCommID(), + schemaId = None, + connectionId = None, + role = PresentationRecord.Role.Verifier, + subjectId = DidId("did:prism:aaa"), + protocolState = PresentationRecord.ProtocolState.RequestPending, + credentialFormat = CredentialFormat.JWT, + invitation = None, + requestPresentationData = None, + proposePresentationData = None, + presentationData = None, + credentialsToUse = None, + anoncredCredentialsToUseJsonSchemaId = None, + anoncredCredentialsToUse = None, + sdJwtClaimsToUseJsonSchemaId = None, + sdJwtClaimsToDisclose = None, + metaRetries = maxRetries, + metaNextRetry = Some(Instant.now()), + metaLastFailure = None + ) + .map(_.withTruncatedTimestamp()) private def requestPresentation = RequestPresentation( from = Some(DidId("did:prism:aaa")), @@ -61,7 +63,7 @@ object PresentationRepositorySpecSuite { test("createPresentationRecord creates a new record in DB") { for { repo <- ZIO.service[PresentationRepository] - record = presentationRecord + record <- presentationRecord _ <- repo.createPresentationRecord(record) result <- repo.findPresentationRecord(record.id) } yield assert(result)(isSome) @@ -69,7 +71,7 @@ object PresentationRepositorySpecSuite { test("createPresentationRecord correctly read and write on non-null connectionId") { for { repo <- ZIO.service[PresentationRepository] - record = presentationRecord.copy(connectionId = Some("connectionId")) + record <- presentationRecord.map(_.copy(connectionId = Some("connectionId"))) _ <- repo.createPresentationRecord(record) readRecord <- repo.findPresentationRecord(record.id) } yield assert(readRecord)(isSome(equalTo(record))) @@ -77,8 +79,8 @@ object PresentationRepositorySpecSuite { test("getPresentationRecord correctly returns an existing record") { for { repo <- ZIO.service[PresentationRepository] - aRecord = presentationRecord - bRecord = presentationRecord + aRecord <- presentationRecord + bRecord <- presentationRecord _ <- repo.createPresentationRecord(aRecord) _ <- repo.createPresentationRecord(bRecord) record <- repo.findPresentationRecord(bRecord.id) @@ -87,8 +89,8 @@ object PresentationRepositorySpecSuite { test("getPresentationRecord returns None for an unknown record") { for { repo <- ZIO.service[PresentationRepository] - aRecord = presentationRecord - bRecord = presentationRecord + aRecord <- presentationRecord + bRecord <- presentationRecord _ <- repo.createPresentationRecord(aRecord) _ <- repo.createPresentationRecord(bRecord) record <- repo.findPresentationRecord(DidCommID()) @@ -97,8 +99,8 @@ object PresentationRepositorySpecSuite { test("getPresentationRecord returns all records") { for { repo <- ZIO.service[PresentationRepository] - aRecord = presentationRecord - bRecord = presentationRecord + aRecord <- presentationRecord + bRecord <- presentationRecord _ <- repo.createPresentationRecord(aRecord) _ <- repo.createPresentationRecord(bRecord) records <- repo.getPresentationRecords(false) @@ -112,8 +114,8 @@ object PresentationRepositorySpecSuite { for { repo <- ZIO.service[PresentationRepository] thid = DidCommID() - aRecord = presentationRecord.copy(thid = thid) - bRecord = presentationRecord + aRecord <- presentationRecord.map(_.copy(thid = thid)) + bRecord <- presentationRecord _ <- repo.createPresentationRecord(aRecord) _ <- repo.createPresentationRecord(bRecord) record <- repo.findPresentationRecordByThreadId(thid) @@ -122,8 +124,8 @@ object PresentationRepositorySpecSuite { test("getPresentationRecordByThreadId returns nothing for an unknown thid") { for { repo <- ZIO.service[PresentationRepository] - aRecord = presentationRecord - bRecord = presentationRecord + aRecord <- presentationRecord + bRecord <- presentationRecord _ <- repo.createPresentationRecord(aRecord) _ <- repo.createPresentationRecord(bRecord) record <- repo.findPresentationRecordByThreadId(DidCommID()) @@ -132,9 +134,9 @@ object PresentationRepositorySpecSuite { test("getPresentationRecordsByStates returns valid records") { for { repo <- ZIO.service[PresentationRepository] - aRecord = presentationRecord - bRecord = presentationRecord - cRecord = presentationRecord + aRecord <- presentationRecord + bRecord <- presentationRecord + cRecord <- presentationRecord _ <- repo.createPresentationRecord(aRecord) _ <- repo.createPresentationRecord(bRecord) _ <- repo.createPresentationRecord(cRecord) @@ -170,9 +172,9 @@ object PresentationRepositorySpecSuite { test("getPresentationRecordsByStates returns an empty list if 'states' parameter is empty") { for { repo <- ZIO.service[PresentationRepository] - aRecord = presentationRecord - bRecord = presentationRecord - cRecord = presentationRecord + aRecord <- presentationRecord + bRecord <- presentationRecord + cRecord <- presentationRecord _ <- repo.createPresentationRecord(aRecord) _ <- repo.createPresentationRecord(bRecord) _ <- repo.createPresentationRecord(cRecord) @@ -184,9 +186,9 @@ object PresentationRepositorySpecSuite { test("updatePresentationWithCredentialsToUse updates the record") { for { repo <- ZIO.service[PresentationRepository] - aRecord = presentationRecord - bRecord = presentationRecord - cRecord = presentationRecord + aRecord <- presentationRecord + bRecord <- presentationRecord + cRecord <- presentationRecord _ <- repo.createPresentationRecord(aRecord) _ <- repo.createPresentationRecord(bRecord) _ <- repo.createPresentationRecord(cRecord) @@ -204,9 +206,9 @@ object PresentationRepositorySpecSuite { test("updatePresentationWithCredentialsToUse updates the record") { for { repo <- ZIO.service[PresentationRepository] - aRecord = presentationRecord - bRecord = presentationRecord - cRecord = presentationRecord + aRecord <- presentationRecord + bRecord <- presentationRecord + cRecord <- presentationRecord _ <- repo.createPresentationRecord(aRecord) _ <- repo.createPresentationRecord(bRecord) _ <- repo.createPresentationRecord(cRecord) @@ -232,7 +234,7 @@ object PresentationRepositorySpecSuite { test("updateCredentialRecordProtocolState updates the record") { for { repo <- ZIO.service[PresentationRepository] - aRecord = presentationRecord + aRecord <- presentationRecord _ <- repo.createPresentationRecord(aRecord) record <- repo.findPresentationRecord(aRecord.id) _ <- repo.updatePresentationRecordProtocolState( @@ -249,7 +251,7 @@ object PresentationRepositorySpecSuite { test("updateCredentialRecordProtocolState doesn't update the record for invalid from state") { for { repo <- ZIO.service[PresentationRepository] - aRecord = presentationRecord + aRecord <- presentationRecord _ <- repo.createPresentationRecord(aRecord) record <- repo.findPresentationRecord(aRecord.id) exit <- repo @@ -264,7 +266,7 @@ object PresentationRepositorySpecSuite { test("updateWithRequestPresentation updates record") { for { repo <- ZIO.service[PresentationRepository] - aRecord = presentationRecord + aRecord <- presentationRecord _ <- repo.createPresentationRecord(aRecord) record <- repo.findPresentationRecord(aRecord.id) request = requestPresentation @@ -282,7 +284,7 @@ object PresentationRepositorySpecSuite { test("updateWithPresentation updates record") { for { repo <- ZIO.service[PresentationRepository] - aRecord = presentationRecord + aRecord <- presentationRecord _ <- repo.createPresentationRecord(aRecord) record <- repo.findPresentationRecord(aRecord.id) presentation = Presentation.makePresentationFromRequest(requestPresentation.makeMessage) @@ -300,7 +302,7 @@ object PresentationRepositorySpecSuite { test("updateWithProposePresentation updates record") { for { repo <- ZIO.service[PresentationRepository] - aRecord = presentationRecord + aRecord <- presentationRecord _ <- repo.createPresentationRecord(aRecord) record <- repo.findPresentationRecord(aRecord.id) request = proposePresentation @@ -316,11 +318,10 @@ object PresentationRepositorySpecSuite { } }, test("updateFail (fail one retry) updates record") { - val aRecord = presentationRecord - val failReason = Some(FailureInfo("PresentationRepositorySpecSuite", StatusCode(999), "Just to test")) for { repo <- ZIO.service[PresentationRepository] + aRecord <- presentationRecord tmp <- repo.createPresentationRecord(aRecord) record0 <- repo.findPresentationRecord(aRecord.id) _ <- repo.updateAfterFail( @@ -346,10 +347,9 @@ object PresentationRepositorySpecSuite { } }, test("updateFail (fail all retry) updates record") { - val aRecord = presentationRecord - for { repo <- ZIO.service[PresentationRepository] + aRecord <- presentationRecord _ <- repo.createPresentationRecord(aRecord) record0 <- repo.findPresentationRecord(aRecord.id) _ <- repo.updateAfterFail( @@ -401,8 +401,8 @@ object PresentationRepositorySpecSuite { val wallet2 = ZLayer.succeed(WalletAccessContext(walletId2)) for { repo <- ZIO.service[PresentationRepository] - record1 = presentationRecord - record2 = presentationRecord + record1 <- presentationRecord.provide(wallet1) + record2 <- presentationRecord.provide(wallet2) _ <- repo.createPresentationRecord(record1).provide(wallet1) _ <- repo.createPresentationRecord(record2).provide(wallet2) ownWalletRecords1 <- repo.getPresentationRecords(false).provide(wallet1) @@ -422,8 +422,8 @@ object PresentationRepositorySpecSuite { val newState = PresentationRecord.ProtocolState.PresentationVerified for { repo <- ZIO.service[PresentationRepository] - record1 = presentationRecord - record2 = presentationRecord + record1 <- presentationRecord.provide(wallet1) + record2 <- presentationRecord.provide(wallet2) _ <- repo.createPresentationRecord(record1).provide(wallet1) exit <- repo.updatePresentationWithCredentialsToUse(record2.id, Option(Nil), newState).provide(wallet2).exit } yield assert(exit)(dies(hasMessage(equalTo("Unexpected affected row count: 0")))) @@ -435,8 +435,8 @@ object PresentationRepositorySpecSuite { val wallet2 = ZLayer.succeed(WalletAccessContext(walletId2)) for { repo <- ZIO.service[PresentationRepository] - record1 = presentationRecord - record2 = presentationRecord + record1 <- presentationRecord.provide(wallet1) + record2 <- presentationRecord.provide(wallet2) _ <- repo.createPresentationRecord(record1).provide(wallet1) exit <- repo .updateAfterFail( @@ -454,8 +454,8 @@ object PresentationRepositorySpecSuite { val newState = PresentationRecord.ProtocolState.PresentationVerified for { repo <- ZIO.service[PresentationRepository] - record1 = presentationRecord - record2 = presentationRecord + record1 <- presentationRecord.provide(wallet1) + record2 <- presentationRecord.provide(wallet2) _ <- repo.createPresentationRecord(record1).provide(wallet1) exit <- repo .updatePresentationRecordProtocolState(record2.id, record1.protocolState, newState) @@ -470,8 +470,8 @@ object PresentationRepositorySpecSuite { val wallet2 = ZLayer.succeed(WalletAccessContext(walletId2)) for { repo <- ZIO.service[PresentationRepository] - record1 = presentationRecord - record2 = presentationRecord + record1 <- presentationRecord.provide(wallet1) + record2 <- presentationRecord.provide(wallet2) _ <- repo.createPresentationRecord(record1).provide(wallet1) _ <- repo.createPresentationRecord(record2).provide(wallet2) _ <- repo diff --git a/pollux/core/src/test/scala/org/hyperledger/identus/pollux/core/service/CredentialServiceNotifierSpec.scala b/pollux/core/src/test/scala/org/hyperledger/identus/pollux/core/service/CredentialServiceNotifierSpec.scala index ff37a66709..d22c82e120 100644 --- a/pollux/core/src/test/scala/org/hyperledger/identus/pollux/core/service/CredentialServiceNotifierSpec.scala +++ b/pollux/core/src/test/scala/org/hyperledger/identus/pollux/core/service/CredentialServiceNotifierSpec.scala @@ -5,6 +5,7 @@ import org.hyperledger.identus.mercury.protocol.issuecredential.* import org.hyperledger.identus.pollux.core.model.* import org.hyperledger.identus.pollux.core.model.error.CredentialServiceError import org.hyperledger.identus.pollux.core.model.IssueCredentialRecord.ProtocolState +import org.hyperledger.identus.pollux.core.repository.CredentialRepositoryInMemory import org.hyperledger.identus.shared.models.{WalletAccessContext, WalletId} import zio.* import zio.mock.{Expectation, MockSpecDefault} @@ -114,7 +115,10 @@ object CredentialServiceNotifierSpec extends MockSpecDefault with CredentialServ } }.provide( ZLayer.succeed(50) >>> EventNotificationServiceImpl.layer, - issuerExpectations.toLayer >>> CredentialServiceNotifier.layer, + ( + CredentialRepositoryInMemory.layer ++ + issuerExpectations.toLayer + ) >>> CredentialServiceNotifier.layer, ZLayer.succeed(WalletAccessContext(WalletId.random)) ), test("Happy flow generates relevant events on the holder side") { @@ -141,7 +145,10 @@ object CredentialServiceNotifierSpec extends MockSpecDefault with CredentialServ } }.provide( ZLayer.succeed(50) >>> EventNotificationServiceImpl.layer, - holderExpectations.toLayer >>> CredentialServiceNotifier.layer, + ( + CredentialRepositoryInMemory.layer ++ + holderExpectations.toLayer + ) >>> CredentialServiceNotifier.layer, ZLayer.succeed(WalletAccessContext(WalletId.random)) ) ) diff --git a/pollux/core/src/test/scala/org/hyperledger/identus/pollux/core/service/PresentationServiceNotifierSpec.scala b/pollux/core/src/test/scala/org/hyperledger/identus/pollux/core/service/PresentationServiceNotifierSpec.scala index 02fdfd5a07..d76a00d35c 100644 --- a/pollux/core/src/test/scala/org/hyperledger/identus/pollux/core/service/PresentationServiceNotifierSpec.scala +++ b/pollux/core/src/test/scala/org/hyperledger/identus/pollux/core/service/PresentationServiceNotifierSpec.scala @@ -9,12 +9,14 @@ import org.hyperledger.identus.mercury.protocol.presentproof.{ } import org.hyperledger.identus.pollux.core.model.{CredentialFormat, DidCommID, PresentationRecord} import org.hyperledger.identus.pollux.core.model.PresentationRecord.ProtocolState +import org.hyperledger.identus.pollux.core.repository.PresentationRepositoryInMemory import org.hyperledger.identus.shared.models.{WalletAccessContext, WalletId} import zio.{Scope, ZIO, ZLayer} import zio.mock.Expectation import zio.test.{assertTrue, Assertion, Spec, TestEnvironment, ZIOSpecDefault} import java.time.Instant +import java.util.UUID object PresentationServiceNotifierSpec extends ZIOSpecDefault with PresentationServiceSpecHelper { @@ -40,7 +42,8 @@ object PresentationServiceNotifierSpec extends ZIOSpecDefault with PresentationS None, 5, None, - None + None, + walletId = WalletId.fromUUID(UUID.randomUUID()) ) private val verifierHappyFlowExpectations = @@ -136,7 +139,10 @@ object PresentationServiceNotifierSpec extends ZIOSpecDefault with PresentationS } }.provide( ZLayer.succeed(50) >>> EventNotificationServiceImpl.layer, - verifierHappyFlowExpectations.toLayer >>> PresentationServiceNotifier.layer, + ( + PresentationRepositoryInMemory.layer ++ + verifierHappyFlowExpectations.toLayer + ) >>> PresentationServiceNotifier.layer, ZLayer.succeed(WalletAccessContext(WalletId.random)) ), test("Generates relevant events on presentation verification failed") { @@ -154,7 +160,10 @@ object PresentationServiceNotifierSpec extends ZIOSpecDefault with PresentationS } }.provide( ZLayer.succeed(50) >>> EventNotificationServiceImpl.layer, - verifierPresentationVerificationFailedExpectations.toLayer >>> PresentationServiceNotifier.layer, + ( + PresentationRepositoryInMemory.layer ++ + verifierPresentationVerificationFailedExpectations.toLayer + ) >>> PresentationServiceNotifier.layer, ZLayer.succeed(WalletAccessContext(WalletId.random)) ), test("Generates relevant events on presentation rejected") { @@ -172,7 +181,10 @@ object PresentationServiceNotifierSpec extends ZIOSpecDefault with PresentationS } }.provide( ZLayer.succeed(50) >>> EventNotificationServiceImpl.layer, - verifierRejectPresentationExpectations.toLayer >>> PresentationServiceNotifier.layer, + ( + PresentationRepositoryInMemory.layer ++ + verifierRejectPresentationExpectations.toLayer + ) >>> PresentationServiceNotifier.layer, ZLayer.succeed(WalletAccessContext(WalletId.random)) ), test("Happy flow generates relevant events on the prover side") { @@ -196,7 +208,10 @@ object PresentationServiceNotifierSpec extends ZIOSpecDefault with PresentationS } }.provide( ZLayer.succeed(50) >>> EventNotificationServiceImpl.layer, - proverHappyFlowExpectations.toLayer >>> PresentationServiceNotifier.layer, + ( + PresentationRepositoryInMemory.layer ++ + proverHappyFlowExpectations.toLayer + ) >>> PresentationServiceNotifier.layer, ZLayer.succeed(WalletAccessContext(WalletId.random)) ), test("Happy flow generates relevant events on the prover side") { @@ -214,7 +229,10 @@ object PresentationServiceNotifierSpec extends ZIOSpecDefault with PresentationS } }.provide( ZLayer.succeed(50) >>> EventNotificationServiceImpl.layer, - proverRejectPresentationRequestExpectations.toLayer >>> PresentationServiceNotifier.layer, + ( + PresentationRepositoryInMemory.layer ++ + proverRejectPresentationRequestExpectations.toLayer + ) >>> PresentationServiceNotifier.layer, ZLayer.succeed(WalletAccessContext(WalletId.random)) ) ) diff --git a/pollux/sql-doobie/src/main/scala/org/hyperledger/identus/pollux/sql/repository/JdbcPresentationRepository.scala b/pollux/sql-doobie/src/main/scala/org/hyperledger/identus/pollux/sql/repository/JdbcPresentationRepository.scala index 6df0a78f6d..1711b4ac6c 100644 --- a/pollux/sql-doobie/src/main/scala/org/hyperledger/identus/pollux/sql/repository/JdbcPresentationRepository.scala +++ b/pollux/sql-doobie/src/main/scala/org/hyperledger/identus/pollux/sql/repository/JdbcPresentationRepository.scala @@ -25,6 +25,7 @@ import zio.json.ast.Json import zio.json.ast.Json.* import java.time.Instant +import java.util.UUID // TODO: replace with actual implementation class JdbcPresentationRepository( xa: Transactor[ContextAwareTask], @@ -165,10 +166,14 @@ class JdbcPresentationRepository( given failureGet: Get[Failure] = Get[String].temap(_.fromJson[FailureInfo]) given failurePut: Put[Failure] = Put[String].contramap(_.asFailureInfo.toJson) + given walletIdGet: Get[WalletId] = Get[UUID].map(id => WalletId.fromUUID(id)) + given walletIdPut: Put[WalletId] = Put[UUID].contramap[WalletId](_.toUUID) + given invitationGet: Get[Invitation] = Get[String].map(decode[Invitation](_).getOrElse(???)) given invitationPut: Put[Invitation] = Put[String].contramap(_.asJson.toString) override def createPresentationRecord(record: PresentationRecord): URIO[WalletAccessContext, Unit] = { + val cxnIO = sql""" | INSERT INTO public.presentation_records( | id, @@ -252,7 +257,8 @@ class JdbcPresentationRepository( | sd_jwt_claims_to_disclose, | meta_retries, | meta_next_retry, - | meta_last_failure + | meta_last_failure, + | wallet_id | FROM | public.presentation_records | $conditionFragment @@ -304,7 +310,8 @@ class JdbcPresentationRepository( | sd_jwt_claims_to_disclose, | meta_retries, | meta_next_retry, - | meta_last_failure + | meta_last_failure, + | wallet_id | FROM public.presentation_records | $conditionFragment | ORDER BY created_at @@ -353,7 +360,8 @@ class JdbcPresentationRepository( | sd_jwt_claims_to_disclose, | meta_retries, | meta_next_retry, - | meta_last_failure + | meta_last_failure, + | wallet_id | FROM public.presentation_records | WHERE id = $recordId """.stripMargin @@ -391,7 +399,8 @@ class JdbcPresentationRepository( | sd_jwt_claims_to_disclose, | meta_retries, | meta_next_retry, - | meta_last_failure + | meta_last_failure, + | wallet_id | FROM public.presentation_records | WHERE thid = $thid """.stripMargin @@ -403,6 +412,43 @@ class JdbcPresentationRepository( .orDie } + override def getPresentationRecordByDIDCommID(recordId: DidCommID): UIO[Option[PresentationRecord]] = { + val cxnIO = sql""" + | SELECT + | id, + | created_at, + | updated_at, + | thid, + | schema_id, + | connection_id, + | role, + | subject_id, + | protocol_state, + | credential_format, + | invitation, + | request_presentation_data, + | propose_presentation_data, + | presentation_data, + | credentials_to_use, + | anoncred_credentials_to_use_json_schema_id, + | anoncred_credentials_to_use, + | sd_jwt_claims_to_use_json_schema_id, + | sd_jwt_claims_to_disclose, + | meta_retries, + | meta_next_retry, + | meta_last_failure, + | wallet_id + | FROM public.presentation_records + | WHERE id = ${recordId.value} + """.stripMargin + .query[PresentationRecord] + .option + + cxnIO + .transact(xb) + .orDie + } + override def updatePresentationRecordProtocolState( recordId: DidCommID, from: PresentationRecord.ProtocolState, diff --git a/tests/integration-tests/build.gradle.kts b/tests/integration-tests/build.gradle.kts index 1f56e07876..07fcfb53a3 100644 --- a/tests/integration-tests/build.gradle.kts +++ b/tests/integration-tests/build.gradle.kts @@ -33,7 +33,7 @@ dependencies { testImplementation("io.ktor:ktor-server-netty:2.3.0") testImplementation("io.ktor:ktor-client-apache:2.3.0") // RestAPI client - testImplementation("org.hyperledger.identus:cloud-agent-client-kotlin:1.37.0") + testImplementation("org.hyperledger.identus:cloud-agent-client-kotlin:1.39.0-e077cdd") // Test helpers library testImplementation("io.iohk.atala:atala-automation:0.4.0") // Hoplite for configuration diff --git a/tests/performance-tests/agent-performance-tests-k6/.env b/tests/performance-tests/agent-performance-tests-k6/.env index 600971f095..5d67c0931e 100644 --- a/tests/performance-tests/agent-performance-tests-k6/.env +++ b/tests/performance-tests/agent-performance-tests-k6/.env @@ -1,3 +1,3 @@ -AGENT_VERSION=1.36.1-SNAPSHOT +AGENT_VERSION=1.39.0-SNAPSHOT PRISM_NODE_VERSION=2.3.0 VAULT_DEV_ROOT_TOKEN_ID=root diff --git a/tests/performance-tests/agent-performance-tests-k6/package.json b/tests/performance-tests/agent-performance-tests-k6/package.json index 68d7aa6a1b..3286629382 100644 --- a/tests/performance-tests/agent-performance-tests-k6/package.json +++ b/tests/performance-tests/agent-performance-tests-k6/package.json @@ -26,7 +26,7 @@ "webpack": "webpack" }, "dependencies": { - "@hyperledger/identus-cloud-agent-client-ts": "^1.36.1", + "@hyperledger/identus-cloud-agent-client-ts": "^1.39.0-e077cdd", "uuid": "^9.0.0" } } diff --git a/tests/performance-tests/agent-performance-tests-k6/src/scenarios/default.ts b/tests/performance-tests/agent-performance-tests-k6/src/scenarios/default.ts index f044a619e2..58ae4a273b 100644 --- a/tests/performance-tests/agent-performance-tests-k6/src/scenarios/default.ts +++ b/tests/performance-tests/agent-performance-tests-k6/src/scenarios/default.ts @@ -23,7 +23,7 @@ export const defaultOptions: Options = { ], http_req_duration: [ // TODO: this threshold is too high, it should be adjusted to the actual performance requirements to lower value - { threshold: 'p(95)<11000', abortOnFail: false } // 95% of requests should complete within 5 seconds, but don't fail tests + { threshold: 'p(95)<20000', abortOnFail: false } // 95% of requests should complete within 5 seconds, but don't fail tests ], checks: [{ threshold: 'rate==1', abortOnFail: true }] // fail if any checks fail (the checks are defined in test code which is executed) } diff --git a/tests/performance-tests/agent-performance-tests-k6/yarn.lock b/tests/performance-tests/agent-performance-tests-k6/yarn.lock index 57db548eb7..e743505b63 100644 --- a/tests/performance-tests/agent-performance-tests-k6/yarn.lock +++ b/tests/performance-tests/agent-performance-tests-k6/yarn.lock @@ -993,10 +993,10 @@ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== -"@hyperledger/identus-cloud-agent-client-ts@^1.36.1": - version "1.36.1" - resolved "https://npm.pkg.github.com/download/@hyperledger/identus-cloud-agent-client-ts/1.36.1/81ea78bfb60603eb293172b33994517db893faac#81ea78bfb60603eb293172b33994517db893faac" - integrity sha512-EXP4G+bKy1Jlf5w0mtoPULjQqVBjnG0L4iUVrmK96N4duJP1P7CrEL09qchk6axPXH67DmoLHISwQPTLN2FMVQ== +"@hyperledger/identus-cloud-agent-client-ts@^1.39.0-e077cdd": + version "1.39.0-e077cdd" + resolved "https://npm.pkg.github.com/download/@hyperledger/identus-cloud-agent-client-ts/1.39.0-e077cdd/06803b9bd2fa7d63805f83df22250882e84c94dd#06803b9bd2fa7d63805f83df22250882e84c94dd" + integrity sha512-3FSz2WlrykyF5LqnrI+wcbrY33i8CeyBNQmEYZ9fp84JL3qhWvnF92dBIS9qpgAQY/qIg5vHvL7RIRNrAxQfOw== dependencies: es6-promise "^4.2.4" url-parse "^1.4.3"