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

hyperledger / identus-cloud-agent / 11056380298

26 Sep 2024 04:28PM CUT coverage: 48.66% (+0.05%) from 48.609%
11056380298

Pull #1375

yshyn-iohk
fix: migration to a new eudi.openid4vci library

Signed-off-by: Yurii Shynbuiev <yurii.shynbuiev@iohk.io>
Pull Request #1375: fix: OAS and http clients for Kotliln and TypeScript

34 of 81 new or added lines in 25 files covered. (41.98%)

182 existing lines in 53 files now uncovered.

7860 of 16153 relevant lines covered (48.66%)

0.49 hits per line

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

77.03
/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/model/schema/CredentialSchema.scala
1
package org.hyperledger.identus.pollux.core.model.schema
2

3
import org.hyperledger.identus.pollux.core.model.error.CredentialSchemaError
4
import org.hyperledger.identus.pollux.core.model.error.CredentialSchemaError.*
5
import org.hyperledger.identus.pollux.core.model.schema.`type`.{
6
  AnoncredSchemaType,
7
  CredentialJsonSchemaType,
8
  CredentialSchemaType
9
}
10
import org.hyperledger.identus.pollux.core.model.schema.`type`.anoncred.AnoncredSchemaSerDesV1
11
import org.hyperledger.identus.pollux.core.model.ResourceResolutionMethod
12
import org.hyperledger.identus.shared.http.UriResolver
13
import org.hyperledger.identus.shared.json.{JsonSchemaValidator, JsonSchemaValidatorImpl}
14
import zio.*
15
import zio.json.*
16
import zio.json.ast.Json
17

18
import java.net.URI
19
import java.time.{OffsetDateTime, ZoneOffset}
20
import java.util.UUID
21

22
type Schema = zio.json.ast.Json
23

24
/** @param guid
25
  *   Globally unique identifier of the CredentialSchema object It's calculated as a UUID from string that contains the
26
  *   following fields: author, id and version
27
  * @param id
28
  *   Locally unique identifier of the CredentialSchema. It is UUID When the version of the credential schema changes
29
  *   this `id` keeps the same value
30
  * @param name
31
  *   Human readable name of the CredentialSchema
32
  * @param version
33
  *   Version of the CredentialSchema
34
  * @param author
35
  *   DID of the CredentialSchema's author
36
  * @param authored
37
  *   Datetime stamp of the schema creation
38
  * @param tags
39
  *   Tags of the CredentialSchema used for convenient lookup
40
  * @param description
41
  *   Human readable description of the schema
42
  * @param schema
43
  *   Internal schema object that depends on concrete implementation For W3C JsonSchema it is a JsonSchema object For
44
  *   AnonCreds schema is a AnonCreds schema
45
  */
46
case class CredentialSchema(
47
    guid: UUID,
48
    id: UUID,
49
    name: String,
50
    version: String,
51
    author: String,
52
    authored: OffsetDateTime,
53
    tags: Seq[String],
54
    description: String,
55
    `type`: String,
56
    resolutionMethod: ResourceResolutionMethod,
57
    schema: Schema
58
) {
59
  def longId = CredentialSchema.makeLongId(author, id, version)
1✔
60
}
61

62
object CredentialSchema {
63

64
  def makeLongId(author: String, id: UUID, version: String) =
1✔
65
    s"$author/${id.toString}?version=${version}"
1✔
66

67
  def makeGUID(author: String, id: UUID, version: String) =
1✔
68
    UUID.nameUUIDFromBytes(makeLongId(author, id, version).getBytes)
1✔
69

70
  def make(in: Input, resolutionMethod: ResourceResolutionMethod): UIO[CredentialSchema] = {
1✔
71
    for {
1✔
72
      id <- zio.Random.nextUUID
1✔
73
      cs <- make(id, in, resolutionMethod)
1✔
74
    } yield cs
75
  }
76
  def make(id: UUID, in: Input, resolutionMethod: ResourceResolutionMethod): UIO[CredentialSchema] = {
1✔
77
    for {
1✔
78
      ts <- zio.Clock.currentDateTime.map(
1✔
79
        _.atZoneSameInstant(ZoneOffset.UTC).toOffsetDateTime
1✔
80
      )
81
      guid = makeGUID(in.author, id, in.version)
1✔
82
    } yield CredentialSchema(
1✔
83
      guid = guid,
84
      id = id,
85
      name = in.name,
86
      version = in.version,
87
      author = in.author,
88
      authored = ts,
89
      tags = in.tags,
90
      description = in.description,
×
91
      `type` = in.`type`,
92
      resolutionMethod = resolutionMethod,
93
      schema = in.schema
94
    )
95
  }
96

97
  val defaultAgentDid = "did:prism:agent"
98

99
  case class Input(
100
      name: String,
101
      version: String,
102
      description: String,
103
      authored: Option[OffsetDateTime],
104
      tags: Seq[String],
UNCOV
105
      author: String = defaultAgentDid,
×
106
      `type`: String,
107
      schema: Schema
108
  )
109

110
  case class Filter(
111
      author: Option[String] = None,
1✔
112
      name: Option[String] = None,
1✔
113
      version: Option[String] = None,
1✔
114
      tags: Option[String] = None,
1✔
115
      resolutionMethod: ResourceResolutionMethod = ResourceResolutionMethod.http
1✔
116
  )
117

118
  case class FilteredEntries(entries: Seq[CredentialSchema], count: Long, totalCount: Long)
119

120
  given JsonEncoder[CredentialSchema] = DeriveJsonEncoder.gen[CredentialSchema]
×
121
  given JsonDecoder[CredentialSchema] = DeriveJsonDecoder.gen[CredentialSchema]
×
122

123
  def resolveJWTSchema(uri: URI, uriResolver: UriResolver): IO[CredentialSchemaParsingError, Json] = {
1✔
124
    for {
1✔
125
      content <- uriResolver.resolve(uri.toString).orDieAsUnmanagedFailure
1✔
126
      json <- ZIO
1✔
127
        .fromEither(content.fromJson[Json])
1✔
128
        .mapError(error => CredentialSchemaParsingError(error))
129
    } yield json
130
  }
131

132
  def validSchemaValidator(
1✔
133
      schemaId: String,
134
      uriResolver: UriResolver
135
  ): IO[InvalidURI | CredentialSchemaParsingError, JsonSchemaValidator] = {
136
    for {
1✔
137
      uri <- ZIO.attempt(new URI(schemaId)).mapError(_ => InvalidURI(schemaId))
1✔
138
      json <- resolveJWTSchema(uri, uriResolver)
1✔
139
      schemaValidator <- JsonSchemaValidatorImpl
1✔
140
        .from(json)
1✔
141
        .orElse(
142
          ZIO
×
143
            .fromEither(json.as[CredentialSchema])
×
144
            .mapError(error => CredentialSchemaParsingError(error))
145
            .flatMap(cs =>
146
              JsonSchemaValidatorImpl.from(cs.schema).mapError(error => CredentialSchemaParsingError(error.error))
×
UNCOV
147
            )
×
UNCOV
148
        )
×
UNCOV
149
    } yield schemaValidator
×
UNCOV
150
  }
×
UNCOV
151

×
152
  def validateJWTCredentialSubject(
1✔
153
      schemaId: String,
154
      credentialSubject: String,
155
      uriResolver: UriResolver
156
  ): IO[InvalidURI | CredentialSchemaParsingError | CredentialSchemaValidationError, Unit] = {
157
    for {
1✔
158
      schemaValidator <- validSchemaValidator(schemaId, uriResolver)
1✔
159
      _ <- schemaValidator.validate(credentialSubject).mapError(CredentialSchemaValidationError.apply)
1✔
160
    } yield ()
1✔
161
  }
162

163
  def validateAnonCredsClaims(
1✔
164
      schemaId: String,
165
      claims: String,
166
      uriResolver: UriResolver
167
  ): IO[InvalidURI | CredentialSchemaParsingError | VCClaimsParsingError | VCClaimValidationError, Unit] = {
168
    for {
1✔
169
      content <- uriResolver.resolve(schemaId).orDieAsUnmanagedFailure
1✔
170
      validAttrNames <-
1✔
171
        AnoncredSchemaSerDesV1.schemaSerDes
1✔
172
          .deserialize(content)
173
          .mapError(error => CredentialSchemaParsingError(error.error))
×
174
          .map(_.attrNames)
175
      jsonClaims <- ZIO.fromEither(claims.fromJson[Json]).mapError(error => VCClaimsParsingError(error))
1✔
176
      _ <- jsonClaims match
1✔
177
        case Json.Obj(fields) =>
1✔
178
          ZIO.foreach(fields) {
1✔
179
            case (k, _) if !validAttrNames.contains(k) =>
×
180
              ZIO.fail(VCClaimValidationError(k, "Name undefined in schema"))
×
181
            case (k, Json.Str(v)) => ZIO.succeed(k -> v)
1✔
182
            case (k, _)           => ZIO.fail(VCClaimValidationError(k, "Value should be a string"))
×
183
          }
184
        case _ => ZIO.fail(VCClaimsParsingError("The JSON claims is not a JSON 'object'"))
×
185
    } yield ()
1✔
186
  }
187

188
  private val supportedCredentialSchemaTypes: Map[String, CredentialSchemaType] =
189
    IndexedSeq(CredentialJsonSchemaType, AnoncredSchemaType)
1✔
190
      .map(credentialSchemaType => (credentialSchemaType.`type`, credentialSchemaType))
1✔
191
      .toMap
192

193
  def resolveCredentialSchemaType(`type`: String): IO[UnsupportedCredentialSchemaType, CredentialSchemaType] = {
1✔
194
    ZIO
1✔
195
      .fromOption(supportedCredentialSchemaTypes.get(`type`))
1✔
196
      .mapError(_ => UnsupportedCredentialSchemaType(`type`))
197
  }
198

199
  def validateCredentialSchema(
1✔
200
      vcSchema: CredentialSchema
201
  ): IO[UnsupportedCredentialSchemaType | CredentialSchemaValidationError, Unit] = {
202
    for {
1✔
203
      resolvedSchemaType <- resolveCredentialSchemaType(vcSchema.`type`)
1✔
204
      _ <- resolvedSchemaType.validate(vcSchema.schema).mapError(CredentialSchemaValidationError.apply)
1✔
205
    } yield ()
1✔
206
  }
207

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