Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Present Error Handling Job #1204

Merged
merged 3 commits into from
Jun 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading