Skip to content

Commit

Permalink
feat: credential configuration impl
Browse files Browse the repository at this point in the history
  • Loading branch information
patlo-iog committed May 7, 2024
1 parent 911d817 commit 0116ea4
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 24 deletions.
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package org.hyperledger.identus.pollux.core.model.oidc4vc

import org.hyperledger.identus.pollux.core.model.CredentialFormat
import zio.json.ast.Json

import java.net.URI
import java.time.Instant

final case class CredentialConfiguration(
configurationId: String,
format: CredentialFormat,
schemaId: URI,
dereferencedSchema: Json
createdAt: Instant
) {
def scope: String = configurationId
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ trait OIDC4VCIssuerMetadataRepository {
def updateIssuer(issuerId: UUID, authorizationServer: Option[URL] = None): URIO[WalletAccessContext, Unit]
def deleteIssuer(issuerId: UUID): URIO[WalletAccessContext, Unit]
def createCredentialConfiguration(issuerId: UUID, config: CredentialConfiguration): URIO[WalletAccessContext, Unit]
def findAllCredentialConfigurations(issuerId: UUID): UIO[Seq[CredentialConfiguration]]
def findCredentialConfigurationsByIssuer(issuerId: UUID): UIO[Seq[CredentialConfiguration]]
def deleteCredentialConfiguration(issuerId: UUID, configurationId: String): URIO[WalletAccessContext, Unit]
}

Expand Down Expand Up @@ -83,7 +83,7 @@ class InMemoryOIDC4VCIssuerMetadataRepository(
} yield ()
}

override def findAllCredentialConfigurations(
override def findCredentialConfigurationsByIssuer(
issuerId: UUID
): UIO[Seq[CredentialConfiguration]] =
credentialConfigStore.get.map { m =>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.hyperledger.identus.pollux.core.service

import org.hyperledger.identus.pollux.core.model.CredentialFormat
import org.hyperledger.identus.pollux.core.model.error.CredentialSchemaError.CredentialSchemaParsingError
import org.hyperledger.identus.pollux.core.model.error.CredentialSchemaError.SchemaError
import org.hyperledger.identus.pollux.core.model.error.CredentialSchemaError.URISyntaxError
import org.hyperledger.identus.pollux.core.model.oidc4vc.CredentialConfiguration
import org.hyperledger.identus.pollux.core.model.oidc4vc.CredentialIssuer
Expand All @@ -10,6 +12,7 @@ import org.hyperledger.identus.pollux.core.service.OIDC4VCIssuerMetadataServiceE
import org.hyperledger.identus.pollux.core.service.OIDC4VCIssuerMetadataServiceError.InvalidSchemaId
import org.hyperledger.identus.pollux.core.service.OIDC4VCIssuerMetadataServiceError.IssuerIdNotFound
import org.hyperledger.identus.pollux.core.service.OIDC4VCIssuerMetadataServiceError.UnsupportedCredentialFormat
import org.hyperledger.identus.shared.db.Errors.UnexpectedAffectedRow
import org.hyperledger.identus.shared.models.Failure
import org.hyperledger.identus.shared.models.StatusCode
import org.hyperledger.identus.shared.models.WalletAccessContext
Expand All @@ -18,7 +21,6 @@ import zio.*
import java.net.URI
import java.net.URL
import java.util.UUID
import org.hyperledger.identus.shared.db.Errors.UnexpectedAffectedRow

sealed trait OIDC4VCIssuerMetadataServiceError(
val statusCode: StatusCode,
Expand Down Expand Up @@ -123,17 +125,20 @@ class OIDC4VCIssuerMetadataServiceImpl(repository: OIDC4VCIssuerMetadataReposito
case f => ZIO.fail(UnsupportedCredentialFormat(f))
}
schemaUri <- ZIO.attempt(new URI(schemaId)).mapError(t => InvalidSchemaId(schemaId, t.getMessage))
jsonSchema <- CredentialSchema
.resolveJWTSchema(schemaUri, uriDereferencer)
_ <- CredentialSchema
.validSchemaValidator(schemaUri.toString(), uriDereferencer)
.catchAll {
case e: URISyntaxError => ZIO.fail(InvalidSchemaId(schemaId, e.message))
case e => ZIO.dieMessage(s"Unexpected error when resolving schema $schemaId: $e")
case _: CredentialSchemaParsingError | _: SchemaError =>
ZIO.fail(InvalidSchemaId(schemaId, "The schema URI does not contain a valid schema response"))
case e => ZIO.dieMessage(s"Unexpected error when resolving schema $schemaId: $e")
}
now <- ZIO.clockWith(_.instant)
config = CredentialConfiguration(
configurationId = configurationId,
format = CredentialFormat.JWT,
schemaId = schemaUri,
dereferencedSchema = jsonSchema
createdAt = now
)
_ <- repository.createCredentialConfiguration(issuerId, config)
} yield config
Expand All @@ -145,21 +150,17 @@ class OIDC4VCIssuerMetadataServiceImpl(repository: OIDC4VCIssuerMetadataReposito
repository
.findIssuerById(issuerId)
.someOrFail(IssuerIdNotFound(issuerId))
.flatMap(_ => repository.findAllCredentialConfigurations(issuerId))
.flatMap(_ => repository.findCredentialConfigurationsByIssuer(issuerId))

override def deleteCredentialConfiguration(
issuerId: UUID,
configurationId: String
): ZIO[WalletAccessContext, IssuerIdNotFound | CredentialConfigurationNotFound, Unit] =
for {
_ <- getCredentialIssuer(issuerId)
configs <- getCredentialConfigurations(issuerId)
_ <- ZIO
.fail(CredentialConfigurationNotFound(issuerId, configurationId))
.unless(configs.map(_.configurationId).contains(configurationId))
_ <- repository.deleteCredentialConfiguration(issuerId, configurationId)
} yield ()

repository
.deleteCredentialConfiguration(issuerId, configurationId)
.catchSomeDefect { case _: UnexpectedAffectedRow =>
ZIO.fail(CredentialConfigurationNotFound(issuerId, configurationId))
}
}

object OIDC4VCIssuerMetadataServiceImpl {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
CREATE TABLE public.issuer_metadata (
id UUID PRIMARY KEY,
authorization_server VARCHAR(1000) NOT NULL,
authorization_server VARCHAR(500) NOT NULL,
created_at TIMESTAMP WITH TIME ZONE NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE NOT NULL,
wallet_id UUID NOT NULL
Expand All @@ -10,7 +10,7 @@ CREATE TABLE public.issuer_credential_configuration (
configuration_id VARCHAR(100) NOT NULL,
issuer_id UUID NOT NULL,
format VARCHAR(9) NOT NULL,
schema_id VARCHAR(36) NOT NULL,
schema_id VARCHAR(500) NOT NULL,
created_at TIMESTAMP WITH TIME ZONE NOT NULL,
UNIQUE (configuration_id, issuer_id),
CONSTRAINT fk_issuer FOREIGN KEY (issuer_id) REFERENCES public.issuer_metadata(id) ON DELETE CASCADE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,9 @@ given statusPurposePut: Put[StatusPurpose] = Put[String].contramap {

given urlGet: Get[URL] = Get[String].map(s => URI.create(s).toURL())
given urlPut: Put[URL] = Put[String].contramap(_.toString())

given uriGet: Get[URI] = Get[String].map(s => URI.create(s))
given uriPut: Put[URI] = Put[String].contramap(_.toString())

given credFormatGet: Get[CredentialFormat] = Get[String].map(CredentialFormat.valueOf)
given credFormatPut: Put[CredentialFormat] = Put[String].contramap(_.toString())
Original file line number Diff line number Diff line change
Expand Up @@ -112,17 +112,62 @@ class JdbcOIDC4VCIssuerMetadataRepository(xa: Transactor[ContextAwareTask], xb:
.ensureOneAffectedRowOrDie
}

override def findAllCredentialConfigurations(issuerId: UUID): UIO[Seq[CredentialConfiguration]] = ???
override def findCredentialConfigurationsByIssuer(issuerId: UUID): UIO[Seq[CredentialConfiguration]] = {
val cxnIO = sql"""
|SELECT
| configuration_id,
| format,
| schema_id,
| created_at
|FROM public.issuer_credential_configuration
|WHERE issuer_id = $issuerId
""".stripMargin
.query[CredentialConfiguration]
.to[Seq]

cxnIO
.transact(xb)
.orDie
}

override def createCredentialConfiguration(
issuerId: UUID,
config: CredentialConfiguration
): URIO[WalletAccessContext, Unit] = ???
): URIO[WalletAccessContext, Unit] = {
val cxnIO = sql"""
|INSERT INTO public.issuer_credential_configuration (
| configuration_id,
| issuer_id,
| format,
| schema_id,
| created_at
|) VALUES (
| ${config.configurationId},
| ${issuerId},
| ${config.format},
| ${config.schemaId},
| ${config.createdAt}
|)
""".stripMargin.update

cxnIO.run
.transactWallet(xa)
.ensureOneAffectedRowOrDie
}

override def deleteCredentialConfiguration(
issuerId: UUID,
configurationId: String
): URIO[WalletAccessContext, Unit] = ???
): URIO[WalletAccessContext, Unit] = {
val cxnIO = sql"""
| DELETE FROM public.issuer_credential_configuration
| WHERE issuer_id = $issuerId AND configuration_id = $configurationId
""".stripMargin.update

cxnIO.run
.transactWallet(xa)
.ensureOneAffectedRowOrDie
}

}

Expand Down

0 comments on commit 0116ea4

Please sign in to comment.