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

hyperledger / identus-cloud-agent / 11407164708

18 Oct 2024 04:02PM CUT coverage: 48.619% (-0.1%) from 48.741%
11407164708

Pull #1400

FabioPinheiro
build: add job Update Dependency Graph

Signed-off-by: FabioPinheiro <fabiomgpinheiro@gmail.com>
Pull Request #1400: build: add job Update Dependency Graph

7867 of 16181 relevant lines covered (48.62%)

0.49 hits per line

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

73.91
/castor/src/main/scala/org/hyperledger/identus/castor/core/model/did/w3c/W3CModelHelper.scala
1
package org.hyperledger.identus.castor.core.model.did.w3c
2

3
import io.circe.Json
4
import org.hyperledger.identus.castor.core.model.did.*
5
import org.hyperledger.identus.castor.core.model.did.ServiceEndpoint.UriOrJsonEndpoint
6
import org.hyperledger.identus.shared.crypto.Apollo
7
import org.hyperledger.identus.shared.models.{Base64UrlString, HexString}
8

9
import java.time.{Instant, ZoneOffset}
10
import java.time.format.DateTimeFormatter
11

12
object W3CModelHelper extends W3CModelHelper
13

14
private[castor] trait W3CModelHelper {
15

16
  private val XML_DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")
1✔
17

18
  private def toXmlDateTime(time: Instant): String = {
×
19
    val zonedDateTime = time.atZone(ZoneOffset.UTC)
×
20
    XML_DATETIME_FORMATTER.format(zonedDateTime)
×
21
  }
22

23
  extension (didMetadata: DIDMetadata) {
24
    def toW3C: DIDDocumentMetadataRepr = DIDDocumentMetadataRepr(
1✔
25
      deactivated = didMetadata.deactivated,
26
      canonicalId = didMetadata.canonicalId.map(_.toString),
×
27
      versionId = HexString.fromByteArray(didMetadata.lastOperationHash.toArray).toString,
1✔
28
      created = didMetadata.created.map(toXmlDateTime),
1✔
29
      updated = didMetadata.updated.map(toXmlDateTime)
×
30
    )
31
  }
32

33
  extension (didData: DIDData) {
34
    def toW3C(did: PrismDID): DIDDocumentRepr = {
1✔
35
      import VerificationRelationship.*
36
      val embeddedKeys = didData.publicKeys.map(k => k.toW3C(did, did))
1✔
37
      val keyRefWithPurpose = didData.publicKeys.map(k => k.purpose -> s"${did.toString}#${k.id}")
1✔
38
      val services = didData.services.map(_.toW3C(did))
1✔
39
      DIDDocumentRepr(
40
        id = did.toString,
1✔
41
        controller = did.toString,
1✔
42
        verificationMethod = embeddedKeys,
43
        authentication = keyRefWithPurpose.collect { case (Authentication, k) => k },
1✔
44
        assertionMethod = keyRefWithPurpose.collect { case (AssertionMethod, k) => k },
1✔
45
        keyAgreement = keyRefWithPurpose.collect { case (KeyAgreement, k) => k },
1✔
46
        capabilityInvocation = keyRefWithPurpose.collect { case (CapabilityInvocation, k) => k },
1✔
47
        capabilityDelegation = keyRefWithPurpose.collect { case (CapabilityDelegation, k) => k },
1✔
48
        service = services,
49
        context = deriveContext(embeddedKeys, services)
1✔
50
      )
51
    }
52

53
    // Reference: https://github.com/input-output-hk/prism-did-method-spec/blob/main/w3c-spec/PRISM-method.md#constructing-a-json-ld-did-document
54
    private def deriveContext(keys: Seq[PublicKeyRepr], services: Seq[ServiceRepr]): Seq[String] = {
1✔
55
      val mandatoryContext = Seq("https://www.w3.org/ns/did/v1")
1✔
56
      val additionalContext = {
57
        val keyTypes = keys.map(_.`type`).toSet
1✔
58
        val serviceTypes = services
59
          .map(_.`type`)
1✔
60
          .flatMap {
1✔
61
            case s: String      => Seq(s)
×
62
            case s: Seq[String] => s
1✔
63
          }
64
          .toSet
1✔
65
        Seq(
1✔
66
          Option.when(keyTypes.contains("JsonWebKey2020"))("https://w3id.org/security/suites/jws-2020/v1"),
1✔
67
          Option.when(serviceTypes.contains("DIDCommMessaging"))("https://didcomm.org/messaging/contexts/v2"),
1✔
68
          Option.when(serviceTypes.contains("LinkedDomains"))(
1✔
69
            "https://identity.foundation/.well-known/did-configuration/v1"
70
          )
71
        ).flatten
72
      }
73
      val userDefinedContext = didData.context
74
      mandatoryContext ++ additionalContext ++ userDefinedContext
1✔
75
    }
76
  }
77

78
  extension (service: Service) {
79
    def toW3C(did: PrismDID): ServiceRepr =
1✔
80
      ServiceRepr(
81
        id = s"${did.toString}#${service.id}",
1✔
82
        `type` = serviceTypeToW3C(service.`type`),
1✔
83
        serviceEndpoint = serviceEndpointToW3C(service.serviceEndpoint)
1✔
84
      )
85

86
    private def serviceTypeToW3C(serviceType: ServiceType): String | Seq[String] = {
1✔
87
      import ServiceType.*
88
      serviceType match {
89
        case ServiceType.Single(name)    => name.value
×
90
        case names: ServiceType.Multiple => names.values.map(_.value)
1✔
91
      }
92
    }
93

94
    private def serviceEndpointToW3C(serviceEndpoint: ServiceEndpoint): Json = {
1✔
95
      serviceEndpoint match {
96
        case ServiceEndpoint.Single(uri) =>
1✔
97
          uri match {
98
            case UriOrJsonEndpoint.Uri(uri)   => Json.fromString(uri.value)
1✔
99
            case UriOrJsonEndpoint.Json(json) => Json.fromJsonObject(json)
1✔
100
          }
101
        case ep: ServiceEndpoint.Multiple =>
102
          val uris = ep.values.map {
×
103
            case UriOrJsonEndpoint.Uri(uri)   => Json.fromString(uri.value)
×
104
            case UriOrJsonEndpoint.Json(json) => Json.fromJsonObject(json)
×
105
          }
106
          Json.arr(uris*)
×
107
      }
108
    }
109
  }
110

111
  extension (publicKey: PublicKey) {
112
    def toW3C(did: PrismDID, controller: PrismDID): PublicKeyRepr = {
1✔
113
      val curve = publicKey.publicKeyData match {
114
        case PublicKeyData.ECCompressedKeyData(crv, _) => crv
1✔
115
        case PublicKeyData.ECKeyData(crv, _, _)        => crv
1✔
116
      }
117
      val publicKeyJwk = curve match {
118
        case EllipticCurve.SECP256K1 => secp256k1Repr(publicKey.publicKeyData)
1✔
119
        case EllipticCurve.ED25519   => okpPublicKeyRepr(publicKey.publicKeyData)
×
120
        case EllipticCurve.X25519    => okpPublicKeyRepr(publicKey.publicKeyData)
×
121
      }
122
      PublicKeyRepr(
123
        id = s"${did.toString}#${publicKey.id}",
1✔
124
        `type` = "JsonWebKey2020",
125
        controller = controller.toString,
1✔
126
        publicKeyJwk = publicKeyJwk
127
      )
128
    }
129

130
    private def okpPublicKeyRepr(pk: PublicKeyData): PublicKeyJwk = {
×
131
      pk match {
132
        case PublicKeyData.ECCompressedKeyData(crv, data) =>
×
133
          PublicKeyJwk(
134
            kty = "OKP",
135
            crv = crv.name,
136
            x = Some(data.toStringNoPadding),
×
137
            y = None
138
          )
139
        case PublicKeyData.ECKeyData(crv, x, _) =>
×
140
          PublicKeyJwk(
141
            kty = "OKP",
142
            crv = crv.name,
143
            x = Some(x.toStringNoPadding),
×
144
            y = None
145
          )
146
      }
147
    }
148

149
    private def secp256k1Repr(pk: PublicKeyData): PublicKeyJwk = {
1✔
150
      val (x, y) = pk match {
151
        case PublicKeyData.ECKeyData(_, x, y) => (x, y)
1✔
152
        case PublicKeyData.ECCompressedKeyData(_, data) =>
153
          val point = Apollo.default.secp256k1.publicKeyFromEncoded(data.toByteArray).get.getECPoint
1✔
154
          val x = Base64UrlString.fromByteArray(point.x)
1✔
155
          val y = Base64UrlString.fromByteArray(point.y)
1✔
156
          (x, y)
157
      }
158
      PublicKeyJwk(
159
        kty = "EC",
160
        crv = EllipticCurve.SECP256K1.name,
161
        x = Some(x.toStringNoPadding),
1✔
162
        y = Some(y.toStringNoPadding)
1✔
163
      )
164
    }
165
  }
166

167
}
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