• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hyperledger / identus-cloud-agent / 10793991050

10 Sep 2024 01:56PM UTC coverage: 48.504% (-4.5%) from 52.962%
10793991050

push

web-flow
build: sbt and plugins dependency update (#1337)

Signed-off-by: Hyperledger Bot <hyperledger-bot@hyperledger.org>
Signed-off-by: Yurii Shynbuiev <yurii.shynbuiev@iohk.io>
Co-authored-by: Hyperledger Bot <hyperledger-bot@hyperledger.org>
Co-authored-by: Yurii Shynbuiev <yurii.shynbuiev@iohk.io>

7406 of 15269 relevant lines covered (48.5%)

0.49 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.75
/castor/src/main/scala/org/hyperledger/identus/castor/core/model/did/PrismDID.scala
1
package org.hyperledger.identus.castor.core.model.did
2

3
import io.iohk.atala.prism.protos.node_models
4
import io.iohk.atala.prism.protos.node_models.AtalaOperation.Operation
5
import org.hyperledger.identus.castor.core.model.ProtoModelHelper
6
import org.hyperledger.identus.shared.crypto.Sha256Hash
7
import org.hyperledger.identus.shared.models.{Base64UrlString, HexString}
8

9
import scala.util.matching.Regex
10
import scala.util.Try
11

12
/** Represents a [Did] used in PRISM with prism-specific method and keys as [PrismDid]
13
  */
14
sealed trait PrismDID {
15
  override def toString: String = did.toString
1✔
16

17
  final def did: DID = DID(PrismDID.PRISM_METHOD, suffix)
1✔
18

19
  final def asCanonical: CanonicalPrismDID = CanonicalPrismDID(stateHash)
1✔
20

21
  def stateHash: HexString
22

23
  def suffix: DIDMethodSpecificId
24

25
}
26

27
object PrismDID extends ProtoModelHelper {
28
  val PRISM_METHOD: DIDMethod = DIDMethod.fromStringUnsafe("prism")
1✔
29
  val CANONICAL_SUFFIX_REGEX: Regex = "^([0-9a-f]{64}$)".r
1✔
30
  val LONG_FORM_SUFFIX_REGEX: Regex = "^([0-9a-f]{64}):([A-Za-z0-9_-]+$)".r
1✔
31

32
  def buildCanonical(stateHash: Array[Byte]): Either[String, CanonicalPrismDID] =
1✔
33
    Try(Sha256Hash.fromBytes(stateHash)).toEither.left
1✔
34
      .map(_.getMessage)
1✔
35
      .map(_ => CanonicalPrismDID(HexString.fromByteArray(stateHash)))
1✔
36

37
  def buildCanonicalFromSuffix(suffix: String): Either[String, CanonicalPrismDID] =
1✔
38
    HexString
39
      .fromString(suffix)
1✔
40
      .toEither
1✔
41
      .left
1✔
42
      .map(e => s"unable to parse suffix as hex string: ${e.getMessage}")
×
43
      .flatMap(suffix => buildCanonical(suffix.toByteArray))
1✔
44

45
  def buildLongFormFromOperation(createOperation: PrismDIDOperation.Create): LongFormPrismDID =
1✔
46
    buildLongFormFromAtalaOperation(
1✔
47
      createOperation.toAtalaOperation
1✔
48
    ).toOption.get // This cannot fail because we know the operation is a CreateDid
1✔
49

50
  def buildLongFormFromAtalaOperation(atalaOperation: node_models.AtalaOperation): Either[String, LongFormPrismDID] =
1✔
51
    atalaOperation.operation match {
52
      case _: Operation.CreateDid => Right(LongFormPrismDID(atalaOperation))
1✔
53
      case operation =>
1✔
54
        Left(s"Provided initial state of long form Prism DID is ${operation.value}, CreateDid Atala operation expected")
1✔
55
    }
56

57
  def fromString(s: String): Either[String, PrismDID] = {
1✔
58
    DID
59
      .fromString(s)
1✔
60
      .flatMap { did =>
1✔
61
        if (did.method == PRISM_METHOD) Right(did)
1✔
62
        else Left(s"Expected DID to have method $PRISM_METHOD, but got \"${did.method.toString}\" instead")
1✔
63
      }
64
      .flatMap { did =>
1✔
65
        val canonicalMatchGroups = CANONICAL_SUFFIX_REGEX.findAllMatchIn(did.methodSpecificId.toString).toList
1✔
66
        val longFormMatchGroups = LONG_FORM_SUFFIX_REGEX.findAllMatchIn(did.methodSpecificId.toString).toList
1✔
67

68
        (canonicalMatchGroups, longFormMatchGroups) match {
69
          case (Nil, longFormPattern :: Nil) =>
1✔
70
            for {
1✔
71
              stateHash <- HexString
72
                .fromString(longFormPattern.group(1))
1✔
73
                .toEither
1✔
74
                .left
1✔
75
                .map(_ => "Invalid long form Prism DID state hash")
1✔
76
              atalaOperation <- Base64UrlString
1✔
77
                .fromString(longFormPattern.group(2))
1✔
78
                .flatMap { encodedStateBase64 =>
1✔
79
                  Try(node_models.AtalaOperation.parseFrom(encodedStateBase64.toByteArray))
1✔
80
                }
81
                .toEither
1✔
82
                .left
1✔
83
                .map(_ => "Invalid long form Prism DID encoded state")
1✔
84
              longFormDID <- buildLongFormFromAtalaOperation(atalaOperation)
1✔
85
              _ <- Either.cond(
1✔
86
                stateHash == longFormDID.stateHash,
87
                (),
88
                "Canonical suffix does not match the computed state"
89
              )
90
            } yield longFormDID
1✔
91
          case (canonicalPattern :: Nil, Nil) =>
1✔
92
            HexString
93
              .fromString(canonicalPattern.group(1))
1✔
94
              .toEither
1✔
95
              .left
1✔
96
              .map(_ => "Invalid canonical form Prism DID")
1✔
97
              .map(stateHash => CanonicalPrismDID(stateHash))
1✔
98
          case _ => Left("Provided DID is not a valid PRISM DID")
×
99
        }
100
      }
101
  }
102
}
103

104
final case class CanonicalPrismDID private[did] (stateHash: HexString) extends PrismDID {
105
  override val suffix: DIDMethodSpecificId = DIDMethodSpecificId.fromStringUnsafe(stateHash.toString)
1✔
106
}
107

108
final case class LongFormPrismDID private[did] (atalaOperation: node_models.AtalaOperation) extends PrismDID {
109

110
  override val stateHash: HexString = {
111
    val encodedState = atalaOperation.toByteArray
1✔
112
    HexString.fromByteArray(Sha256Hash.compute(encodedState).bytes.toArray)
1✔
113
  }
114

115
  override val suffix: DIDMethodSpecificId = {
116
    val encodedState = Base64UrlString.fromByteArray(atalaOperation.toByteArray).toStringNoPadding
1✔
117
    DIDMethodSpecificId.fromStringUnsafe(s"${stateHash.toString}:${encodedState}")
1✔
118
  }
119

120
  def createOperation: Either[String, PrismDIDOperation.Create] = {
1✔
121
    import ProtoModelHelper.*
122
    atalaOperation.operation match {
123
      case Operation.CreateDid(op) => op.toDomain
1✔
124
      case operation =>
×
125
        Left(s"Provided initial state of long form Prism DID is ${operation.value}, CreateDid Atala operation expected")
×
126
    }
127
  }
128

129
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc