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

input-output-hk / atala-prism-building-blocks / 8819221863

24 Apr 2024 03:32PM UTC coverage: 50.082% (+18.2%) from 31.912%
8819221863

Pull #973

mineme0110
minor cleanup

Signed-off-by: mineme0110 <shailesh.patil@iohk.io>
Pull Request #973: feat: Align the repo with new name identus-cloud-agent

1 of 6 new or added lines in 4 files covered. (16.67%)

2998 existing lines in 264 files now uncovered.

7340 of 14656 relevant lines covered (50.08%)

0.5 hits per line

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

80.65
/prism-agent/service/wallet-api/src/main/scala/io/iohk/atala/agent/walletapi/sql/package.scala
1
package io.iohk.atala.agent.walletapi
2

3
import com.nimbusds.jose.jwk.OctetKeyPair
4
import doobie.*
5
import doobie.postgres.implicits.*
6
import doobie.util.invariant.InvalidEnum
7
import io.circe.*
8
import io.circe.parser.*
9
import io.circe.syntax.*
10
import io.iohk.atala.agent.walletapi.model.Wallet
11
import io.iohk.atala.agent.walletapi.model.{ManagedDIDState, PublicationState, KeyManagementMode}
12
import io.iohk.atala.castor.core.model.ProtoModelHelper.*
13
import io.iohk.atala.castor.core.model.did.InternalKeyPurpose
14
import io.iohk.atala.castor.core.model.did.VerificationRelationship
15
import io.iohk.atala.castor.core.model.did.{PrismDID, PrismDIDOperation, ScheduledDIDOperationStatus}
16
import org.hyperledger.identus.event.notification.EventNotificationConfig
17
import io.iohk.atala.prism.protos.node_models
18
import io.iohk.atala.shared.models.WalletId
19
import zio.json.*
20
import zio.json.ast.Json
21
import zio.json.ast.Json.*
22

23
import java.net.URL
24
import java.time.Instant
25
import java.util.UUID
26
import scala.collection.immutable.ArraySeq
27
import scala.util.Try
28

29
package object sql {
30

31
  sealed trait PublicationStatusType
32
  object PublicationStatusType {
33
    case object CREATED extends PublicationStatusType
34
    case object PUBLICATION_PENDING extends PublicationStatusType
35
    case object PUBLISHED extends PublicationStatusType
36

37
    def from(status: PublicationState): PublicationStatusType = status match {
1✔
38
      case PublicationState.Created()             => CREATED
1✔
39
      case PublicationState.PublicationPending(_) => PUBLICATION_PENDING
1✔
40
      case PublicationState.Published(_)          => PUBLISHED
1✔
41
    }
42
  }
43

44
  given Meta[VerificationRelationship | InternalKeyPurpose] = pgEnumString(
1✔
45
    "PRISM_DID_KEY_USAGE",
46
    {
47
      case "MASTER"                => InternalKeyPurpose.Master
1✔
UNCOV
48
      case "ISSUING"               => VerificationRelationship.AssertionMethod
×
49
      case "KEY_AGREEMENT"         => VerificationRelationship.KeyAgreement
1✔
50
      case "AUTHENTICATION"        => VerificationRelationship.Authentication
1✔
51
      case "REVOCATION"            => InternalKeyPurpose.Revocation
×
52
      case "CAPABILITY_INVOCATION" => VerificationRelationship.CapabilityInvocation
×
53
      case "CAPABILITY_DELEGATION" => VerificationRelationship.CapabilityDelegation
×
UNCOV
54
      case s                       => throw InvalidEnum[VerificationRelationship | InternalKeyPurpose](s)
×
55
    },
56
    {
57
      case InternalKeyPurpose.Master                     => "MASTER"
1✔
58
      case VerificationRelationship.AssertionMethod      => "ISSUING"
1✔
59
      case VerificationRelationship.KeyAgreement         => "KEY_AGREEMENT"
1✔
60
      case VerificationRelationship.Authentication       => "AUTHENTICATION"
1✔
61
      case InternalKeyPurpose.Revocation                 => "REVOCATION"
×
62
      case VerificationRelationship.CapabilityInvocation => "CAPABILITY_INVOCATION"
×
UNCOV
63
      case VerificationRelationship.CapabilityDelegation => "CAPABILITY_DELEGATION"
×
64
    }
65
  )
66

67
  given Meta[KeyManagementMode] = pgEnumString(
1✔
68
    "PRISM_DID_KEY_MODE",
69
    {
70
      case "HD" => KeyManagementMode.HD
1✔
UNCOV
71
      case s    => throw InvalidEnum[KeyManagementMode](s)
×
72
    },
73
    { case KeyManagementMode.HD => "HD" }
1✔
74
  )
75

76
  given Meta[PublicationStatusType] = pgEnumString(
1✔
77
    "PRISM_DID_WALLET_STATUS",
78
    {
79
      case "CREATED"             => PublicationStatusType.CREATED
1✔
80
      case "PUBLICATION_PENDING" => PublicationStatusType.PUBLICATION_PENDING
1✔
81
      case "PUBLISHED"           => PublicationStatusType.PUBLISHED
1✔
UNCOV
82
      case s                     => throw InvalidEnum[PublicationStatusType](s)
×
83
    },
84
    {
85
      case PublicationStatusType.CREATED             => "CREATED"
1✔
86
      case PublicationStatusType.PUBLICATION_PENDING => "PUBLICATION_PENDING"
1✔
87
      case PublicationStatusType.PUBLISHED           => "PUBLISHED"
1✔
88
    }
89
  )
90

91
  given Meta[ScheduledDIDOperationStatus] = pgEnumString(
1✔
92
    "PRISM_DID_OPERATION_STATUS",
93
    {
94
      case "PENDING_SUBMISSION"     => ScheduledDIDOperationStatus.Pending
1✔
UNCOV
95
      case "AWAIT_CONFIRMATION"     => ScheduledDIDOperationStatus.AwaitingConfirmation
×
96
      case "CONFIRMED_AND_APPLIED"  => ScheduledDIDOperationStatus.Confirmed
1✔
97
      case "CONFIRMED_AND_REJECTED" => ScheduledDIDOperationStatus.Rejected
×
UNCOV
98
      case s                        => throw InvalidEnum[ScheduledDIDOperationStatus](s)
×
99
    },
100
    {
101
      case ScheduledDIDOperationStatus.Pending              => "PENDING_SUBMISSION"
1✔
102
      case ScheduledDIDOperationStatus.AwaitingConfirmation => "AWAIT_CONFIRMATION"
1✔
103
      case ScheduledDIDOperationStatus.Confirmed            => "CONFIRMED_AND_APPLIED"
1✔
UNCOV
104
      case ScheduledDIDOperationStatus.Rejected             => "CONFIRMED_AND_REJECTED"
×
105
    }
106
  )
107

UNCOV
108
  given prismDIDGet: Get[PrismDID] = Get[String].map(PrismDID.fromString(_).left.map(Exception(_)).toTry.get)
×
109
  given prismDIDPut: Put[PrismDID] = Put[String].contramap(_.asCanonical.toString)
1✔
110

111
  given arraySeqByteGet: Get[ArraySeq[Byte]] = Get[Array[Byte]].map(ArraySeq.from)
1✔
112
  given arraySeqBytePut: Put[ArraySeq[Byte]] = Put[Array[Byte]].contramap(_.toArray)
1✔
113

114
  given urlGet: Get[URL] = Get[String].map(URL(_))
1✔
115
  given urlPut: Put[URL] = Put[String].contramap(_.toString())
1✔
116

117
  given octetKeyPairGet: Get[OctetKeyPair] = Get[String].map(OctetKeyPair.parse)
1✔
118
  given octetKeyPairPut: Put[OctetKeyPair] = Put[String].contramap(_.toJSONString)
1✔
119

120
  given jsonGet: Get[Json] = Get[String].map(_.fromJson[Json] match {
1✔
121
    case Right(value) => value
1✔
UNCOV
122
    case Left(error)  => throw new RuntimeException(error)
×
123
  })
124
  given jsonPut: Put[Json] = Put[String].contramap(_.toString())
1✔
125

126
  final case class DIDStateRow(
127
      did: PrismDID,
128
      publicationStatus: PublicationStatusType,
129
      atalaOperationContent: Array[Byte],
130
      publishOperationId: Option[Array[Byte]],
131
      createdAt: Instant,
132
      updatedAt: Instant,
133
      keyMode: KeyManagementMode,
134
      didIndex: Int,
135
      walletId: WalletId
136
  ) {
137
    def toDomain: Try[ManagedDIDState] = {
1✔
138
      publicationStatus match {
139
        case PublicationStatusType.CREATED =>
1✔
140
          createDIDOperation.map(op => ManagedDIDState(op, didIndex, PublicationState.Created()))
1✔
141
        case PublicationStatusType.PUBLICATION_PENDING =>
1✔
142
          for {
1✔
143
            createDIDOperation <- createDIDOperation
1✔
144
            operationId <- publishOperationId
1✔
145
              .toRight(RuntimeException(s"DID publication operation id does not exists for PUBLICATION_PENDING status"))
1✔
146
              .toTry
147
          } yield ManagedDIDState(
148
            createDIDOperation,
149
            didIndex,
150
            PublicationState.PublicationPending(ArraySeq.from(operationId))
1✔
151
          )
152
        case PublicationStatusType.PUBLISHED =>
1✔
153
          for {
1✔
154
            createDIDOperation <- createDIDOperation
1✔
155
            operationId <- publishOperationId
1✔
UNCOV
156
              .toRight(RuntimeException(s"DID publication operation id does not exists for PUBLISHED status"))
×
157
              .toTry
158
          } yield ManagedDIDState(createDIDOperation, didIndex, PublicationState.Published(ArraySeq.from(operationId)))
1✔
159
      }
160
    }
161

162
    private def createDIDOperation: Try[PrismDIDOperation.Create] = {
1✔
163
      Try(node_models.AtalaOperation.parseFrom(atalaOperationContent))
1✔
164
        .flatMap { atalaOperation =>
1✔
165
          atalaOperation.operation.createDid
1✔
166
            .toRight(
1✔
UNCOV
167
              s"cannot extract CreateDIDOperation from AtalaOperation (${atalaOperation.operation.getClass.getSimpleName} found)"
×
168
            )
169
            .flatMap(_.toDomain)
1✔
170
            .left
1✔
171
            .map(RuntimeException(_))
1✔
172
            .toTry
173
        }
174
    }
175
  }
176

177
  object DIDStateRow {
178
    def from(did: PrismDID, state: ManagedDIDState, now: Instant, walletId: WalletId): DIDStateRow = {
1✔
179
      val createOperation = state.createOperation
180
      val status = PublicationStatusType.from(state.publicationState)
1✔
181
      val publishedOperationId = state.publicationState match {
182
        case PublicationState.Created()                       => None
1✔
183
        case PublicationState.PublicationPending(operationId) => Some(operationId.toArray)
1✔
184
        case PublicationState.Published(operationId)          => Some(operationId.toArray)
1✔
185
      }
186
      DIDStateRow(
187
        did = did,
188
        publicationStatus = status,
189
        atalaOperationContent = createOperation.toAtalaOperation.toByteArray,
1✔
190
        publishOperationId = publishedOperationId.map(_.toArray),
1✔
191
        createdAt = now,
192
        updatedAt = now,
193
        keyMode = state.keyMode,
1✔
194
        didIndex = state.didIndex,
195
        walletId = walletId
196
      )
197
    }
198
  }
199

200
  final case class WalletRow(
201
      id: WalletId,
202
      name: String,
203
      createdAt: Instant,
204
      updatedAt: Instant
205
  ) {
206
    def toDomain: Wallet = {
1✔
207
      Wallet(
208
        id: WalletId,
209
        name: String,
210
        createdAt: Instant,
211
        updatedAt: Instant
212
      )
213
    }
214
  }
215

216
  object WalletRow {
217
    def from(wallet: Wallet): WalletRow = {
1✔
218
      WalletRow(
219
        id = wallet.id,
220
        name = wallet.name,
221
        createdAt = wallet.createdAt,
222
        updatedAt = wallet.updatedAt
223
      )
224
    }
225
  }
226

227
  final case class WalletNofiticationRow(
228
      id: UUID,
229
      walletId: WalletId,
230
      url: URL,
231
      customHeaders: String,
232
      createdAt: Instant,
233
  ) {
234
    def toDomain: Try[EventNotificationConfig] = {
1✔
235
      decode[Map[String, String]](customHeaders).toTry
1✔
236
        .map { headers =>
1✔
237
          EventNotificationConfig(
238
            id = id,
239
            walletId = walletId,
240
            url = url,
241
            customHeaders = headers,
242
            createdAt = createdAt,
243
          )
244
        }
245
    }
246
  }
247

248
  object WalletNofiticationRow {
249
    def from(config: EventNotificationConfig): WalletNofiticationRow = {
1✔
250
      WalletNofiticationRow(
251
        id = config.id,
252
        walletId = config.walletId,
253
        url = config.url,
254
        customHeaders = config.customHeaders.asJson.noSpacesSortKeys,
1✔
255
        createdAt = config.createdAt,
256
      )
257
    }
258
  }
259

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