Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/origin/main' into beta
Browse files Browse the repository at this point in the history
# Conflicts:
#	.github/workflows/release.yml
#	version.sbt
  • Loading branch information
yshyn-iohk committed Aug 30, 2024
2 parents 45e725f + b19f514 commit 20144fe
Show file tree
Hide file tree
Showing 30 changed files with 275 additions and 243 deletions.
1 change: 0 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ jobs:
ref: ${{ github.event.inputs.release-branch }}
fetch-depth: 0


- name: Setup Java and Scala
uses: olafurpg/setup-scala@v14
with:
Expand Down
8 changes: 1 addition & 7 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -303,12 +303,6 @@ lazy val D_Pollux = new {

lazy val D_Pollux_VC_JWT = new {

private lazy val circeJsonSchema = ("net.reactivecore" %% "circe-json-schema" % "0.4.1")
.cross(CrossVersion.for3Use2_13)
.exclude("io.circe", "circe-core_2.13")
.exclude("io.circe", "circe-generic_2.13")
.exclude("io.circe", "circe-parser_2.13")

val zio = "dev.zio" %% "zio" % V.zio
val zioPrelude = "dev.zio" %% "zio-prelude" % V.zioPreludeVersion

Expand All @@ -321,7 +315,7 @@ lazy val D_Pollux_VC_JWT = new {
// Dependency Modules
val zioDependencies: Seq[ModuleID] = Seq(zio, zioPrelude, zioTest, zioTestSbt, zioTestMagnolia)
val baseDependencies: Seq[ModuleID] =
zioDependencies :+ D.jwtCirce :+ circeJsonSchema :+ networkntJsonSchemaValidator :+ D.nimbusJwt :+ D.scalaTest
zioDependencies :+ D.jwtCirce :+ networkntJsonSchemaValidator :+ D.nimbusJwt :+ D.scalaTest

// Project Dependencies
lazy val polluxVcJwtDependencies: Seq[ModuleID] = baseDependencies
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ pollux {
syncRevocationStatusesBgJobProcessingParallelism = ${?SYNC_REVOCATION_STATUSES_BG_JOB_PROCESSING_PARALLELISM}
credential.sdJwt.expiry = 30 days
credential.sdJwt.expiry = ${?CREDENTIAL_SD_JWT_EXPIRY}
presentationInvitationExpiry = 300 seconds
presentationInvitationExpiry = ${?PRESENTATION_INVITATION_EXPIRY}
}

connect {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ final case class PolluxConfig(
presentationBgJobProcessingParallelism: Int,
syncRevocationStatusesBgJobRecurrenceDelay: Duration,
syncRevocationStatusesBgJobProcessingParallelism: Int,
presentationInvitationExpiry: Duration,
)
final case class ConnectConfig(
database: DatabaseConfig,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import org.hyperledger.identus.castor.core.model.error.DIDResolutionError as Cas
import org.hyperledger.identus.castor.core.service.DIDService
import org.hyperledger.identus.mercury.*
import org.hyperledger.identus.mercury.model.*
import org.hyperledger.identus.mercury.protocol.invitation.v2.Invitation
import org.hyperledger.identus.mercury.protocol.presentproof.*
import org.hyperledger.identus.mercury.protocol.reportproblem.v2.{ProblemCode, ReportProblem}
import org.hyperledger.identus.pollux.core.model.*
Expand Down Expand Up @@ -436,7 +437,7 @@ object PresentBackgroundJobs extends BackgroundJobsHelper {
_,
PresentationReceived,
credentialFormat,
_,
invitation,
Some(requestPresentation),
_,
Some(presentation),
Expand All @@ -450,7 +451,7 @@ object PresentBackgroundJobs extends BackgroundJobsHelper {
_
) => // Verifier
ZIO.logDebug("PresentationRecord: PresentationReceived") *> ZIO.unit
Verifier.PresentationReceived.handle(id, requestPresentation, presentation, credentialFormat)
Verifier.PresentationReceived.handle(id, requestPresentation, presentation, credentialFormat, invitation)

case PresentationRecord(
id,
Expand Down Expand Up @@ -893,29 +894,51 @@ object PresentBackgroundJobs extends BackgroundJobsHelper {
id: DidCommID,
requestPresentation: RequestPresentation,
presentation: Presentation,
credentialFormat: CredentialFormat
credentialFormat: CredentialFormat,
invitation: Option[Invitation]
): ZIO[
AppConfig & JwtDidResolver & COMMON_RESOURCES & MESSAGING_RESOURCES,
Failure,
Unit
] = {
val result =
credentialFormat match {
case CredentialFormat.JWT => handleJWT(id, requestPresentation, presentation)
case CredentialFormat.SDJWT => handleSDJWT(id, presentation)
case CredentialFormat.AnonCreds => handleAnoncred(id, requestPresentation, presentation)
case CredentialFormat.JWT => handleJWT(id, requestPresentation, presentation, invitation)
case CredentialFormat.SDJWT => handleSDJWT(id, presentation, invitation)
case CredentialFormat.AnonCreds => handleAnoncred(id, requestPresentation, presentation, invitation)
}
result @@ metric
}

private def handleJWT(id: DidCommID, requestPresentation: RequestPresentation, presentation: Presentation): ZIO[
private def checkInvitationExpiry(
id: DidCommID,
invitation: Option[Invitation]
): ZIO[PresentationService & WalletAccessContext, PresentationError, Unit] = {
invitation.flatMap(_.expires_time) match {
case Some(expiryTime) if Instant.now().getEpochSecond > expiryTime =>
for {
service <- ZIO.service[PresentationService]
_ <- service.markPresentationInvitationExpired(id)
_ <- ZIO.fail(PresentationError.InvitationExpired(s"Invitation has expired. Expiry time: $expiryTime"))
} yield ()
case _ => ZIO.unit
}
}

private def handleJWT(
id: DidCommID,
requestPresentation: RequestPresentation,
presentation: Presentation,
invitation: Option[Invitation]
): ZIO[
AppConfig & JwtDidResolver & COMMON_RESOURCES & MESSAGING_RESOURCES,
Failure,
Unit
] = {
val clock = java.time.Clock.system(ZoneId.systemDefault)
for {
walletAccessContext <- buildWalletAccessContextLayer(presentation.to)
_ <- checkInvitationExpiry(id, invitation).provideSomeLayer(ZLayer.succeed(walletAccessContext))
result <- for {
didResolverService <- ZIO.service[JwtDidResolver]
credentialsClaimsValidationResult <- presentation.attachments.head.data match {
Expand Down Expand Up @@ -1022,13 +1045,14 @@ object PresentBackgroundJobs extends BackgroundJobsHelper {
} yield result
}

private def handleSDJWT(id: DidCommID, presentation: Presentation): ZIO[
private def handleSDJWT(id: DidCommID, presentation: Presentation, invitation: Option[Invitation]): ZIO[
JwtDidResolver & COMMON_RESOURCES & MESSAGING_RESOURCES,
Failure,
Unit
] = {
for {
walletAccessContext <- buildWalletAccessContextLayer(presentation.to)
_ <- checkInvitationExpiry(id, invitation).provideSomeLayer(ZLayer.succeed(walletAccessContext))
result <- for {
didResolverService <- ZIO.service[JwtDidResolver]
credentialsClaimsValidationResult <- presentation.attachments.head.data match {
Expand Down Expand Up @@ -1090,20 +1114,22 @@ object PresentBackgroundJobs extends BackgroundJobsHelper {
private def handleAnoncred(
id: DidCommID,
requestPresentation: RequestPresentation,
presentation: Presentation
presentation: Presentation,
invitation: Option[Invitation]
): ZIO[
PresentationService & DIDNonSecretStorage & MESSAGING_RESOURCES,
PresentationError | DIDSecretStorageError,
Unit
] = {
for {
walletAccessContext <- buildWalletAccessContextLayer(presentation.to)
presReceivedToProcessedAspect = CustomMetricsAspect.endRecordingTime(
s"${id}_present_proof_flow_verifier_presentation_received_to_verification_success_or_failure_ms_gauge",
"present_proof_flow_verifier_presentation_received_to_verification_success_or_failure_ms_gauge"
)
_ <- checkInvitationExpiry(id, invitation).provideSomeLayer(ZLayer.succeed(walletAccessContext))
result <- for {
service <- ZIO.service[PresentationService]
presReceivedToProcessedAspect = CustomMetricsAspect.endRecordingTime(
s"${id}_present_proof_flow_verifier_presentation_received_to_verification_success_or_failure_ms_gauge",
"present_proof_flow_verifier_presentation_received_to_verification_success_or_failure_ms_gauge"
)
_ <- (service
.verifyAnoncredPresentation(presentation, requestPresentation, id)
.provideSomeLayer(ZLayer.succeed(walletAccessContext)) @@ presReceivedToProcessedAspect)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,9 @@ case class OIDCCredentialIssuerServiceImpl(
maybeCredentialStatus = None, // TODO: Add credential status
maybeRefreshService = None, // TODO: Add refresh service
maybeEvidence = None, // TODO: Add evidence
maybeTermsOfUse = None // TODO: Add terms of use
maybeTermsOfUse = None, // TODO: Add terms of use,
maybeValidFrom = None, // TODO: Add ValidFrom
maybeValidUntil = None // TODO: Add ValidUntil
)

ZIO.succeed(credential) // TODO: there might be other calls to fill the VC claims from the session, etc
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class PresentProofControllerImpl(
req.claims,
req.anoncredPresentationRequest,
None,
None,
None
)
case req: OOBRequestPresentationInput =>
Expand All @@ -92,7 +93,8 @@ class PresentProofControllerImpl(
req.claims,
req.anoncredPresentationRequest,
req.goalCode,
req.goal
req.goal,
Some(appConfig.pollux.presentationInvitationExpiry)
)
}
}
Expand All @@ -107,7 +109,8 @@ class PresentProofControllerImpl(
claims: Option[zio.json.ast.Json.Obj],
anoncredPresentationRequest: Option[AnoncredPresentationRequestV1],
goalCode: Option[String],
goal: Option[String]
goal: Option[String],
expirationDuration: Option[Duration],
): ZIO[WalletAccessContext, PresentationError, PresentationRecord] = {
val format = credentialFormat.map(CredentialFormat.valueOf).getOrElse(CredentialFormat.JWT)
format match {
Expand All @@ -126,7 +129,8 @@ class PresentProofControllerImpl(
},
options = options,
goalCode = goalCode,
goal = goal
goal = goal,
expirationDuration = expirationDuration,
)
case CredentialFormat.SDJWT =>
claims match {
Expand All @@ -146,7 +150,8 @@ class PresentProofControllerImpl(
claimsToDisclose = claimsToDisclose,
options = options,
goalCode = goalCode,
goal = goal
goal = goal,
expirationDuration = expirationDuration,
)
case None =>
ZIO.fail(
Expand All @@ -165,7 +170,8 @@ class PresentProofControllerImpl(
connectionId = connectionId,
presentationRequest = presentationRequest,
goalCode = goalCode,
goal = goal
goal = goal,
expirationDuration = expirationDuration,
)
case None =>
ZIO.fail(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ object VcVerificationControllerImplSpec extends ZIOSpecDefault with VcVerificati
issuer = issuer.did,
issuanceDate = Instant.parse("2010-01-01T00:00:00Z"),
maybeExpirationDate = Some(Instant.parse("2010-01-12T00:00:00Z")),
maybeValidFrom = Some(Instant.parse("2010-01-12T00:00:00Z")),
maybeValidUntil = Some(Instant.parse("2010-01-12T00:00:00Z")),
maybeCredentialSchema = Some(
CredentialSchema(
id = "did:work:MDP8AsFhHzhwUvGNuYkX7T;id=06e126d1-fa44-4882-a243-1e326fbe21db;version=1.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,55 +1,39 @@
package org.hyperledger.identus.agent.walletapi.sql

import doobie.*
import doobie.implicits.*
import doobie.postgres.implicits.*
import io.getquill.JsonValue
import org.hyperledger.identus.agent.walletapi.sql.model.GenericSecretSql
import org.hyperledger.identus.agent.walletapi.sql.model as db
import org.hyperledger.identus.agent.walletapi.storage.{GenericSecret, GenericSecretStorage}
import org.hyperledger.identus.shared.db.ContextAwareTask
import org.hyperledger.identus.shared.db.Implicits.*
import org.hyperledger.identus.shared.models.WalletAccessContext
import zio.*
import zio.json.ast.Json

import java.time.Instant

class JdbcGenericSecretStorage(xa: Transactor[ContextAwareTask]) extends GenericSecretStorage {

override def set[K, V](key: K, secret: V)(implicit ev: GenericSecret[K, V]): RIO[WalletAccessContext, Unit] = {
val keyPath = ev.keyPath(key)
val payload = ev.encodeValue(secret)
val cxnIO = (now: Instant) => sql"""
| INSERT INTO public.generic_secret(
| key,
| payload,
| created_at,
| wallet_id
| ) values (
| ${keyPath},
| ${payload},
| ${now},
| current_setting('app.current_wallet_id')::UUID
| )
""".stripMargin.update

for {
now <- Clock.instant
_ <- cxnIO(now).run.transactWallet(xa)
walletId <- ZIO.serviceWith[WalletAccessContext](_.walletId)
s = db.GenericSecret(key = keyPath, payload = JsonValue(payload), createdAt = now, walletId = walletId)
_ <- GenericSecretSql
.insert(s)
.transactWallet(xa)
} yield ()
}

override def get[K, V](key: K)(implicit ev: GenericSecret[K, V]): RIO[WalletAccessContext, Option[V]] = {
val keyPath = ev.keyPath(key)
val cxnIO = sql"""
| SELECT payload
| FROM public.generic_secret
| WHERE key = ${keyPath}
""".stripMargin
.query[Json]
.option

cxnIO
GenericSecretSql
.findByKey(keyPath)
.transactWallet(xa)
.flatMap(_.fold(ZIO.none)(json => ZIO.fromTry(ev.decodeValue(json)).asSome))
.flatMap(
_.headOption
.fold(ZIO.none)(row => ZIO.fromTry(ev.decodeValue(row.payload.value)).asSome)
)
}

}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.hyperledger.identus.agent.walletapi.sql.model

import io.getquill.{SnakeCase, *}
import io.getquill.context.json.PostgresJsonExtensions
import io.getquill.doobie.DoobieContext
import org.hyperledger.identus.shared.models.WalletId
import zio.json.ast.Json

import java.time.Instant

final case class GenericSecret(
key: String,
payload: JsonValue[Json],
createdAt: Instant,
walletId: WalletId
)

object GenericSecretSql extends DoobieContext.Postgres(SnakeCase), PostgresJsonExtensions {
def insert(secret: GenericSecret) = run {
quote(
query[GenericSecret].insertValue(lift(secret))
)
}

def findByKey(key: String) = run {
quote(
query[GenericSecret].filter(_.key == lift(key)).take(1)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ object Wallet {
}

object WalletSql extends DoobieContext.Postgres(SnakeCase) {

def insert(wallet: Wallet) = run {
quote(
query[Wallet]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ final case class Invitation(
`type`: PIURI = Invitation.`type`,
from: DidId,
body: Invitation.Body,
attachments: Option[Seq[AttachmentDescriptor]] = None
attachments: Option[Seq[AttachmentDescriptor]] = None,
created_time: Option[Long] = None,
expires_time: Option[Long] = None,
) {
assert(`type` == "https://didcomm.org/out-of-band/2.0/invitation")
def toBase64: String = java.util.Base64.getUrlEncoder.encodeToString(this.asJson.deepDropNullValues.noSpaces.getBytes)

}

object Invitation {
Expand Down
Loading

0 comments on commit 20144fe

Please sign in to comment.