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

feat: implement ADR Use ZIO Failures and Defects Effectively - Mercury should not throw exceptions #1192

Merged
merged 2 commits into from
Jun 18, 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 @@ -615,19 +615,16 @@ object IssueBackgroundJobs extends BackgroundJobsHelper {
aux
.tapError(
{
case walletNotFound: WalletNotFoundError =>
ZIO.logErrorCause(
s"Issue Credential- Error processing record: ${record.id}",
Cause.fail(walletNotFound)
)
case walletNotFound: WalletNotFoundError => ZIO.unit
case CredentialServiceError.RecordNotFound(_, _) => ZIO.unit
case CredentialServiceError.UnsupportedDidFormat(_) => ZIO.unit
case ((walletAccessContext, e)) =>
for {
credentialService <- ZIO.service[CredentialService]
_ <- credentialService
.reportProcessingFailure(record.id, Some(e.toString))
.provideSomeLayer(ZLayer.succeed(walletAccessContext))
} yield ()

}
)
.catchAll(e => ZIO.logErrorCause(s"Issue Credential - Error processing record: ${record.id} ", Cause.fail(e)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ class DIDCommControllerImpl(
.catchAll {
case f: Failure => ZIO.fail(f)
case _: DIDCommMessageParsingError => ZIO.fail(UnexpectedError(StatusCode.BadRequest))
case _: PresentationError => ZIO.fail(UnexpectedError(StatusCode.UnprocessableContent))
}
.provideSomeLayer(ZLayer.succeed(msgAndContext._2))
} yield ()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ class DidCommX() extends DidOps /* with DidAgent with DIDResolver */ {
new DIDComm(UniversalDidResolver, AgentPeerService.getSecretResolverInMemory(agent))
}

// override def id: DidId = fixme // FIXME the Secret is on org.didcommx.didcomm.model.DIDComm ...

// override def resolveDID(did: DidId): Task[DIDDoc] = UniversalDidResolver.resolveDID(did)

override def packSigned(msg: Message): URIO[DidAgent, SignedMesage] = for {
agent <- ZIO.service[DidAgent]
params = new PackSignedParams.Builder(msg, agent.id.value).build()
Expand All @@ -39,7 +35,7 @@ class DidCommX() extends DidOps /* with DidAgent with DIDResolver */ {
ret = didCommFor(agent).packEncrypted(params)
} yield (ret)

// FIXME theoretically DidAgent is not needed
// TODO theoretically DidAgent is not needed
override def packEncryptedAnon(msg: Message, to: DidId): URIO[DidAgent, EncryptedMessage] = for {
agent <- ZIO.service[DidAgent]
params = new PackEncryptedParams.Builder(msg, to.value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,12 @@ object MessagingService {
finalMessage <- makeMessage(forwardMessage.asMessage) // Maybe it needs a double warping
} yield finalMessage
case ServiceEndpoint(uri, _, Some(routingKeys)) =>
ZIO.log(s"RoutingDID: $routingKeys") *> ??? // ZIO.fail(???) // FIXME no support for routingKeys
ZIO.log(s"RoutingDID: $routingKeys") *>
ZIO.fail(
SendMessageError(
RuntimeException("routingKeys is not supported at the moment")
)
)
case s @ ServiceEndpoint(_, _, None) =>
ZIO.logError(s"Unxpected ServiceEndpoint $s") *> ZIO.fail(
SendMessageError(new RuntimeException(s"Unxpected ServiceEndpoint $s"))
Expand All @@ -116,11 +121,15 @@ object MessagingService {
auxFinalMessage <- makeMessage(msg)
MessageAndAddress(finalMessage, serviceEndpoint) = auxFinalMessage
didCommService <- ZIO.service[DidOps]
to <- finalMessage.to match {
case Seq() => ZIO.fail(SendMessageError(new RuntimeException("Message must have a recipient")))
case firstTo +: Seq() => ZIO.succeed(firstTo)
case all @ (firstTo +: _) =>
ZIO.logWarning(s"Message have multi recipients: $all") *> ZIO.succeed(firstTo)
}
encryptedMessage <-
if (finalMessage.`type` == ForwardMessage.PIURI)
didCommService.packEncryptedAnon(msg = finalMessage, to = finalMessage.to.head) // TODO Head
else
didCommService.packEncrypted(msg = finalMessage, to = finalMessage.to.head) // TODO Head
if (finalMessage.`type` == ForwardMessage.PIURI) didCommService.packEncryptedAnon(msg = finalMessage, to = to)
else didCommService.packEncrypted(msg = finalMessage, to = to)

_ <- ZIO.log(s"Sending a Message to '$serviceEndpoint'")
resp <- org.hyperledger.identus.mercury.HttpClient
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ given Conversion[Message, org.didcommx.didcomm.message.Message] with {
msg.to.foreach(did => aux.to(Seq(did.value).asJava))

msg.pleaseAck.foreach { seq => // https://identity.foundation/didcomm-messaging/spec/#acks
aux.pleaseAck(true) // FIXME lib limitation the field pleaseAck MUST be a Array of string
aux.pleaseAck(true) // NOTE lib limitation the field pleaseAck MUST be a Array of string
}
msg.ack.flatMap(_.headOption).foreach(str => aux.ack(str)) // NOTE: headOption becuase DidCommx only support one ack
msg.thid.foreach(str => aux.thid(str))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ object UnpackMessageImp {
pleaseAck = Option(msg.getPleaseAck())
.flatMap {
// https://identity.foundation/didcomm-messaging/spec/#acks
case java.lang.Boolean.TRUE => Some(Seq.empty) // FIXME getPleaseAck MUST return a Array
case java.lang.Boolean.TRUE =>
Some(Seq.empty) // NOTE lib limitation the field pleaseAck MUST be a Array of string
case java.lang.Boolean.FALSE => None
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,15 @@ object CoordinateMediationPrograms {
_ <- ZIO.log("#### Send Mediation request ####")
link <- InvitationPrograms
.getInvitationProgram(mediatorURL + "/oob_url")
.map(_.toOption) // FIXME
.flatMap {
case Left(value) => ZIO.fail(value)
case Right(value) => ZIO.succeed(value)
}
opsService <- ZIO.service[DidOps]
agentService <- ZIO.service[DidAgent]

planMessage = link.map(to => replyToInvitation(agentService.id, to)).get
invitationFrom = link.get.from
planMessage = replyToInvitation(agentService.id, link)
invitationFrom = link.from
_ <- ZIO.log(s"Invitation from $invitationFrom")

encryptedMessage <- opsService.packEncrypted(planMessage, to = invitationFrom)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import scala.util.{Failure, Success, Try}
trait DidOps {
def packSigned(msg: Message): URIO[DidAgent, SignedMesage]
def packEncrypted(msg: Message, to: DidId): URIO[DidAgent, EncryptedMessage]
// FIXME theoretically DidAgent is not needed for packEncryptedAnon
// TODO theoretically DidAgent is not needed for packEncryptedAnon
def packEncryptedAnon(msg: Message, to: DidId): URIO[DidAgent, EncryptedMessage]
def unpack(str: String): URIO[DidAgent, UnpackMessage]
def unpackBase64(dataBase64: String): RIO[DidAgent, UnpackMessage] = {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -81,23 +81,29 @@ object OfferCredential {
given Decoder[Body] = deriveDecoder[Body]
}

def makeOfferToProposeCredential(msg: Message): OfferCredential = { // TODO change msg: Message to ProposeCredential
val pc: ProposeCredential = ProposeCredential.readFromMessage(msg)

OfferCredential(
body = OfferCredential.Body(
goal_code = pc.body.goal_code,
comment = pc.body.comment,
replacement_id = None,
multiple_available = None,
credential_preview = pc.body.credential_preview.get, // FIXME .get
),
attachments = pc.attachments,
thid = msg.thid.orElse(Some(pc.id)),
from = pc.to,
to = pc.from,
)
}
def makeOfferToProposeCredential(
msg: Message // TODO change msg: Message to ProposeCredential
): Either[String, OfferCredential] =
ProposeCredential.readFromMessage(msg).flatMap { pc =>
pc.body.credential_preview match
case None => Left("This method expects the ProposeCredential to have a 'credential_preview' in the body")
case Some(credential_preview) =>
Right(
OfferCredential(
body = OfferCredential.Body(
goal_code = pc.body.goal_code,
comment = pc.body.comment,
replacement_id = None,
multiple_available = None,
credential_preview = credential_preview,
),
attachments = pc.attachments,
thid = msg.thid.orElse(Some(pc.id)),
from = pc.to,
to = pc.from,
)
)
}

def readFromMessage(message: Message): Either[String, OfferCredential] = {
message.body.asJson.as[OfferCredential.Body] match
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,20 +79,26 @@ object ProposeCredential {
given Decoder[Body] = deriveDecoder[Body]
}

def readFromMessage(message: Message): ProposeCredential = {
val body = message.body.asJson.as[ProposeCredential.Body].toOption.get // TODO get

ProposeCredential(
id = message.id,
`type` = message.piuri,
body = body,
attachments = message.attachments.getOrElse(Seq.empty),
from = message.from.get, // TODO get
to = {
assert(message.to.length == 1, "The recipient is ambiguous. Need to have only 1 recipient") // TODO return error
message.to.head
},
)
def readFromMessage(message: Message): Either[String, ProposeCredential] = {
message.body.asJson.as[ProposeCredential.Body] match
case Left(fail) => Left("Fail to parse ProposeCredential's body: " + fail.getMessage)
case Right(body) =>
message.from match
case None => Left("ProposeCredential MUST have the sender explicit")
case Some(from) =>
message.to match
case firstTo +: Seq() =>
Right(
ProposeCredential(
id = message.id,
`type` = message.piuri,
body = body,
attachments = message.attachments.getOrElse(Seq.empty),
from = from,
to = firstTo,
)
)
case tos => Left(s"ProposeCredential MUST have only 1 recipient instead has '${tos}'")
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ private trait ReadAttachmentsUtils {

def attachments: Seq[AttachmentDescriptor]

// TODO this formatName shoud be type safe
// TODO this formatName should be type safe
lazy val getCredentialFormatAndCredential: Seq[(String, String, Array[Byte])] =
attachments
.flatMap(attachment =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,15 @@ class UtilsCredentialSpec extends ZSuite {
)
.makeMessage

val obj = ProposeCredential.readFromMessage(msg)

assertEquals(obj.getCredentialFormatAndCredential.size, 1)
assertEquals(
obj.getCredentialFormatAndCredential.map(_._2),
Seq(IssueCredentialProposeFormat.Unsupported(nameCredentialType).name)
)
assertEquals(obj.getCredential[TestCredentialType](nameCredentialType).headOption, Some(credential))
ProposeCredential.readFromMessage(msg).map { obj =>
assertEquals(obj.getCredentialFormatAndCredential.size, 1)
assertEquals(
obj.getCredentialFormatAndCredential.map(_._2),
Seq(IssueCredentialProposeFormat.Unsupported(nameCredentialType).name)
)
assertEquals(obj.getCredential[TestCredentialType](nameCredentialType).headOption, Some(credential))
}

}

test("RequestCredential encode and decode any type of Credential into the attachments") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import io.circe.parser.*
import io.circe.syntax.*
import org.hyperledger.identus.mercury.protocol.presentproof.*
import org.hyperledger.identus.pollux.core.model.*
import org.hyperledger.identus.pollux.core.model.PresentationRecord.ProtocolState
import org.hyperledger.identus.pollux.core.repository.PresentationRepository
import org.hyperledger.identus.shared.db.ContextAwareTask
import org.hyperledger.identus.shared.db.Implicits.*
Expand All @@ -36,7 +35,7 @@ class JdbcPresentationRepository(
override def updatePresentationWithCredentialsToUse(
recordId: DidCommID,
credentialsToUse: Option[Seq[String]],
protocolState: ProtocolState
protocolState: PresentationRecord.ProtocolState
): URIO[WalletAccessContext, Unit] = {
val cxnIO = sql"""
| UPDATE public.presentation_records
Expand All @@ -61,7 +60,7 @@ class JdbcPresentationRepository(
recordId: DidCommID,
credentialsToUse: Option[Seq[String]],
sdJwtClaimsToDisclose: Option[SdJwtCredentialToDisclose],
protocolState: ProtocolState
protocolState: PresentationRecord.ProtocolState
): URIO[WalletAccessContext, Unit] = {
val cxnIO =
sql"""
Expand All @@ -88,7 +87,7 @@ class JdbcPresentationRepository(
recordId: DidCommID,
anoncredCredentialsToUseJsonSchemaId: Option[String],
anoncredCredentialsToUse: Option[AnoncredCredentialProofs],
protocolState: ProtocolState
protocolState: PresentationRecord.ProtocolState
): URIO[WalletAccessContext, Unit] = {
val cxnIO =
sql"""
Expand Down
Loading