Skip to content

Commit

Permalink
ATL-7264: Present Error Handling Job
Browse files Browse the repository at this point in the history
Signed-off-by: Bassam Riman <bassam.riman@iohk.io>
  • Loading branch information
CryptoKnightIOG committed Jun 19, 2024
1 parent 833d6f4 commit e90d607
Show file tree
Hide file tree
Showing 8 changed files with 808 additions and 821 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import org.hyperledger.identus.iam.authentication.apikey.ApiKeyAuthenticator
import org.hyperledger.identus.iam.entity.http.EntityServerEndpoints
import org.hyperledger.identus.iam.wallet.http.WalletManagementServerEndpoints
import org.hyperledger.identus.issue.controller.IssueServerEndpoints
import org.hyperledger.identus.mercury.{DidOps, HttpClient}
import org.hyperledger.identus.mercury.{DidAgent, DidOps, HttpClient}
import org.hyperledger.identus.oid4vci.CredentialIssuerServerEndpoints
import org.hyperledger.identus.pollux.core.service.{CredentialService, PresentationService}
import org.hyperledger.identus.pollux.credentialdefinition.CredentialDefinitionRegistryServerEndpoints
Expand Down Expand Up @@ -68,7 +68,7 @@ object CloudAgentApp {

private val presentProofExchangeJob: RIO[
AppConfig & DidOps & DIDResolver & JwtDidResolver & HttpClient & PresentationService & CredentialService &
DIDNonSecretStorage & DIDService & ManagedDIDService & WalletManagementService,
DIDNonSecretStorage & DIDService & ManagedDIDService,
Unit
] =
for {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ sealed trait BackgroundJobError

object BackgroundJobError {
final case class InvalidState(cause: String) extends BackgroundJobError

final case class ErrorSendingMessage(cause: String) extends BackgroundJobError
case object NotImplemented extends BackgroundJobError
final case class ErrorResponseReceivedFromPeerAgent(response: HttpResponse) extends BackgroundJobError {
override def toString: String = s"DIDComm sending error: [${response.status}] - ${response.bodyAsString}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.hyperledger.identus.agent.server.jobs

import org.hyperledger.identus.agent.walletapi.model.{ManagedDIDState, PublicationState}
import org.hyperledger.identus.agent.walletapi.model.error.DIDSecretStorageError.{KeyNotFoundError, WalletNotFoundError}
import org.hyperledger.identus.agent.walletapi.model.error.GetManagedDIDError
import org.hyperledger.identus.agent.walletapi.service.ManagedDIDService
import org.hyperledger.identus.agent.walletapi.storage.DIDNonSecretStorage
import org.hyperledger.identus.castor.core.model.did.{
Expand All @@ -10,22 +11,22 @@ import org.hyperledger.identus.castor.core.model.did.{
PrismDID,
VerificationRelationship
}
import org.hyperledger.identus.castor.core.model.error.DIDResolutionError
import org.hyperledger.identus.castor.core.service.DIDService
import org.hyperledger.identus.mercury.{AgentPeerService, DidAgent}
import org.hyperledger.identus.mercury.model.DidId
import org.hyperledger.identus.pollux.core.model.error.PresentationError
import org.hyperledger.identus.pollux.sdjwt.SDJWT.*
import org.hyperledger.identus.pollux.vc.jwt.{DIDResolutionFailed, DIDResolutionSucceeded, ES256KSigner, *}
import org.hyperledger.identus.pollux.vc.jwt.{DidResolver as JwtDidResolver, Issuer as JwtIssuer}
import org.hyperledger.identus.shared.crypto.{
Ed25519KeyPair,
Ed25519PublicKey,
KmpEd25519KeyOps,
Secp256k1KeyPair,
X25519KeyPair
import org.hyperledger.identus.pollux.vc.jwt.{
DIDResolutionFailed,
DIDResolutionSucceeded,
DidResolver as JwtDidResolver,
ES256KSigner,
Issuer as JwtIssuer,
*
}
import org.hyperledger.identus.shared.models.KeyId
import org.hyperledger.identus.shared.models.WalletAccessContext
import org.hyperledger.identus.shared.crypto.*
import org.hyperledger.identus.shared.models.{KeyId, WalletAccessContext}
import zio.{ZIO, ZLayer}

import java.util.Base64
Expand All @@ -35,16 +36,20 @@ trait BackgroundJobsHelper {
def getLongForm(
did: PrismDID,
allowUnpublishedIssuingDID: Boolean = false
): ZIO[ManagedDIDService & WalletAccessContext, RuntimeException, LongFormPrismDID] = {
): ZIO[ManagedDIDService & WalletAccessContext, BackgroundJobError | GetManagedDIDError, LongFormPrismDID] = {
for {
managedDIDService <- ZIO.service[ManagedDIDService]
didState <- managedDIDService
.getManagedDIDState(did.asCanonical)
.mapError(e => RuntimeException(s"Error occurred while getting did from wallet: ${e.toString}"))
.someOrFail(RuntimeException(s"Issuer DID does not exist in the wallet: $did"))
.someOrFail(BackgroundJobError.InvalidState(s"Issuer DID does not exist in the wallet: $did"))
.flatMap {
case s @ ManagedDIDState(_, _, PublicationState.Published(_)) => ZIO.succeed(s)
case s => ZIO.cond(allowUnpublishedIssuingDID, s, RuntimeException(s"Issuer DID must be published: $did"))
case s =>
ZIO.cond(
allowUnpublishedIssuingDID,
s,
BackgroundJobError.InvalidState(s"Issuer DID must be published: $did")
)
}
longFormPrismDID = PrismDID.buildLongFormFromOperation(didState.createOperation)
} yield longFormPrismDID
Expand All @@ -53,39 +58,45 @@ trait BackgroundJobsHelper {
def createJwtIssuer(
jwtIssuerDID: PrismDID,
verificationRelationship: VerificationRelationship
): ZIO[DIDService & ManagedDIDService & WalletAccessContext, RuntimeException, JwtIssuer] = {
): ZIO[
DIDService & ManagedDIDService & WalletAccessContext,
BackgroundJobError | GetManagedDIDError | DIDResolutionError,
JwtIssuer
] = {
for {
managedDIDService <- ZIO.service[ManagedDIDService]
didService <- ZIO.service[DIDService]
// Automatically infer keyId to use by resolving DID and choose the corresponding VerificationRelationship
issuingKeyId <- didService
.resolveDID(jwtIssuerDID)
.mapError(e => RuntimeException(s"Error occured while resolving Issuing DID during VC creation: ${e.toString}"))
.someOrFail(RuntimeException(s"Issuing DID resolution result is not found"))
.someOrFail(BackgroundJobError.InvalidState(s"Issuing DID resolution result is not found"))
.map { case (_, didData) =>
didData.publicKeys
.find(pk => pk.purpose == verificationRelationship && pk.publicKeyData.crv == EllipticCurve.SECP256K1)
.map(_.id)
}
.someOrFail(
RuntimeException(s"Issuing DID doesn't have a key in ${verificationRelationship.name} to use: $jwtIssuerDID")
BackgroundJobError.InvalidState(
s"Issuing DID doesn't have a key in ${verificationRelationship.name} to use: $jwtIssuerDID"
)
)
jwtIssuer <- managedDIDService
.findDIDKeyPair(jwtIssuerDID.asCanonical, issuingKeyId)
.flatMap {
case None =>
ZIO.fail(
RuntimeException(s"Issuer key-pair does not exist in the wallet: ${jwtIssuerDID.toString}#$issuingKeyId")
BackgroundJobError
.InvalidState(s"Issuer key-pair does not exist in the wallet: ${jwtIssuerDID.toString}#$issuingKeyId")
)
case Some(Ed25519KeyPair(publicKey, privateKey)) =>
ZIO.fail(
RuntimeException(
BackgroundJobError.InvalidState(
s"Issuer key-pair '$issuingKeyId' is of the type Ed25519. It's not supported by this feature in this version"
)
)
case Some(X25519KeyPair(publicKey, privateKey)) =>
ZIO.fail(
RuntimeException(
BackgroundJobError.InvalidState(
s"Issuer key-pair '$issuingKeyId' is of the type X25519. It's not supported by this feature in this version"
)
)
Expand Down Expand Up @@ -127,14 +138,22 @@ trait BackgroundJobsHelper {
proverDid: PrismDID,
verificationRelationship: VerificationRelationship,
keyId: KeyId
): ZIO[DIDService & ManagedDIDService & WalletAccessContext, RuntimeException, Ed25519KeyPair] = {
): ZIO[
DIDService & ManagedDIDService & WalletAccessContext,
DIDResolutionError | BackgroundJobError,
Ed25519KeyPair
] = {
for {
managedDIDService <- ZIO.service[ManagedDIDService]
didService <- ZIO.service[DIDService]
issuingKeyId <- didService
.resolveDID(proverDid)
.mapError(e => RuntimeException(s"Error occured while resolving Issuing DID during VC creation: ${e.toString}"))
.someOrFail(RuntimeException(s"Issuing DID resolution result is not found"))
.mapError(e =>
BackgroundJobError.InvalidState(
s"Error occured while resolving Issuing DID during VC creation: ${e.toString}"
)
)
.someOrFail(BackgroundJobError.InvalidState(s"Issuing DID resolution result is not found"))
.map { case (_, didData) =>
didData.publicKeys
.find(pk =>
Expand All @@ -144,13 +163,17 @@ trait BackgroundJobsHelper {
.map(_.id)
}
.someOrFail(
RuntimeException(s"Issuing DID doesn't have a key in ${verificationRelationship.name} to use: $proverDid")
BackgroundJobError.InvalidState(
s"Issuing DID doesn't have a key in ${verificationRelationship.name} to use: $proverDid"
)
)
ed25519keyPair <- managedDIDService
.findDIDKeyPair(proverDid.asCanonical, issuingKeyId)
.map(_.collect { case keyPair: Ed25519KeyPair => keyPair })
.someOrFail(
RuntimeException(s"Issuer key-pair does not exist in the wallet: ${proverDid.toString}#$issuingKeyId")
BackgroundJobError.InvalidState(
s"Issuer key-pair does not exist in the wallet: ${proverDid.toString}#$issuingKeyId"
)
)
} yield ed25519keyPair
}
Expand All @@ -162,28 +185,21 @@ trait BackgroundJobsHelper {
publicKeyBase64 <- didResolutionResult match {
case failed: DIDResolutionFailed =>
ZIO.fail(
PresentationError.UnexpectedError(
s"DIDResolutionFailed for $did: ${failed.error.toString}"
)
PresentationError.DIDResolutionFailed(did, failed.error.toString)
)
case succeeded: DIDResolutionSucceeded =>
succeeded.didDocument.verificationMethod
.find(vm => succeeded.didDocument.assertionMethod.contains(vm.id))
.flatMap(_.publicKeyJwk.flatMap(_.x))
.toRight(
PresentationError.UnexpectedError(
s"Did Document is missing the required publicKey: $did"
)
)
.toRight(PresentationError.DIDDocumentMissing(did))
.fold(ZIO.fail(_), ZIO.succeed(_))
}
ed25519PublicKey <- ZIO
.fromTry {
val decodedKey = Base64.getUrlDecoder.decode(publicKeyBase64)
KmpEd25519KeyOps.publicKeyFromEncoded(decodedKey)
}
.mapError(t => PresentationError.UnexpectedError(t.getMessage))
.mapError(t => PresentationError.PublicKeyDecodingError(t.getMessage))
} yield ed25519PublicKey
}

}
Loading

0 comments on commit e90d607

Please sign in to comment.