Skip to content

Commit

Permalink
feat(prism-agent) update schema logic - agent part. ATL-3164 (#452)
Browse files Browse the repository at this point in the history
* feat(pollux): Implement basic logic for credential schema update.

* feat(pollux): Implement basic logic for credential schema update. #2

* feat(prism-agent): Implement basic logic for credential schema update at the agent side

* feat(prism-agent): fix e2e tests

* feat(prism-agent): fix e2e tests #2

* feat(prism-agent): fix formatting issue
  • Loading branch information
yshyn-iohk committed Mar 20, 2023
1 parent f2e619c commit d3a8d15
Show file tree
Hide file tree
Showing 11 changed files with 135 additions and 15 deletions.
48 changes: 48 additions & 0 deletions prism-agent/service/api/http/prism-agent-openapi-spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,54 @@ paths:
"500":
$ref: "./shared/responses.yaml#/components/responses/InternalServerError"

/schema-registry/{author}/{id}:
put:
tags:
- Schema Registry
summary: Publish the new version of the credential schema to the schema registry
description:
Publish the new version of the credential schema record with metadata
and internal JSON Schema on behalf of Cloud Agent. The credential schema will
be signed by the keys of Cloud Agent and issued by the DID that corresponds
to it.
operationId: updateSchema
parameters:
- name: author
in: path
description:
DID of the identity which authored the credential schema. A piece
of Metadata.
required: true
schema:
type: string
- name: id
in: path
description:
A locally unique identifier to address the schema. UUID is generated
by the backend.
required: true
schema:
type: string
format: uuid
requestBody:
description: JSON object required for the credential schema update
content:
application/json:
schema:
$ref: "./pollux/schemas.yaml#/components/schemas/CredentialSchemaInput"
required: true
responses:
"200":
description: The credential schema record is successfully updated
content:
application/json:
schema:
$ref: "./pollux/schemas.yaml#/components/schemas/CredentialSchemaResponse"
"400":
$ref: "./shared/responses.yaml#/components/responses/BadRequest"
"500":
$ref: "./shared/responses.yaml#/components/responses/InternalServerError"

/schema-registry/schemas/{guid}:
get:
tags:
Expand Down
2 changes: 1 addition & 1 deletion prism-agent/service/project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ object Dependencies {
val akka = "2.6.20"
val akkaHttp = "10.2.9"
val castor = "0.8.1"
val pollux = "0.41.0"
val pollux = "0.42.0"
val connect = "0.12.0"
val bouncyCastle = "1.70"
val logback = "1.4.5"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,24 @@ import io.iohk.atala.agent.server.http.marshaller.*
import io.iohk.atala.agent.server.http.service.*
import io.iohk.atala.agent.server.http.{HttpRoutes, HttpServer}
import io.iohk.atala.pollux.core.service.{
CredentialSchemaService,
CredentialSchemaServiceImpl,
CredentialService,
CredentialServiceImpl,
PresentationService,
PresentationServiceImpl,
VerificationPolicyService,
VerificationPolicyServiceImpl,
CredentialSchemaService,
CredentialSchemaServiceImpl
VerificationPolicyServiceImpl
}
import io.iohk.atala.pollux.credentialschema.controller.{CredentialSchemaController, CredentialSchemaControllerImpl}
import io.iohk.atala.iris.proto.service.IrisServiceGrpc
import io.iohk.atala.iris.proto.service.IrisServiceGrpc.IrisServiceStub
import io.iohk.atala.pollux.core.repository.CredentialRepository
import io.iohk.atala.pollux.sql.repository.{
JdbcCredentialRepository,
JdbcCredentialSchemaRepository,
JdbcPresentationRepository,
JdbcVerificationPolicyRepository,
JdbcCredentialSchemaRepository,
DbConfig as PolluxDbConfig
}
import io.iohk.atala.connect.sql.repository.DbConfig as ConnectDbConfig
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,42 @@ object SchemaRegistryEndpoints {
)
.tag("Schema Registry")

val updateSchemaEndpoint: PublicEndpoint[
(RequestContext, String, UUID, CredentialSchemaInput),
FailureResponse,
CredentialSchemaResponse,
Any
] =
endpoint.put
.in(extractFromRequest[RequestContext](RequestContext.apply))
.in(
"schema-registry" /
path[String]("author").description(CredentialSchemaResponse.annotations.author.description) /
path[UUID]("id").description(CredentialSchemaResponse.annotations.id.description)
)
.in(
jsonBody[CredentialSchemaInput]
.description(
"JSON object required for the credential schema update"
)
)
.out(
statusCode(StatusCode.Ok)
.description(
"The credential schema record is successfully updated"
)
)
.out(jsonBody[CredentialSchemaResponse])
.description("Credential schema record")
.errorOut(basicFailures)
.name("updateSchema")
.summary("Publish the new version of the credential schema to the schema registry")
.description(
"Publish the new version of the credential schema record with metadata and internal JSON Schema on behalf of Cloud Agent. " +
"The credential schema will be signed by the keys of Cloud Agent and issued by the DID that corresponds to it."
)
.tag("Schema Registry")

val getSchemaByIdEndpoint: PublicEndpoint[
(RequestContext, UUID),
FailureResponse,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import io.iohk.atala.api.http.model.{CollectionStats, Order, Pagination, Paginat
import io.iohk.atala.api.http.{FailureResponse, InternalServerError, NotFound, RequestContext}
import io.iohk.atala.pollux.credentialschema.SchemaRegistryEndpoints.{
createSchemaEndpoint,
updateSchemaEndpoint,
getSchemaByIdEndpoint,
lookupSchemasByQueryEndpoint,
testEndpoint
Expand Down Expand Up @@ -35,6 +36,12 @@ class SchemaRegistryServerEndpoints(
credentialSchemaController.createSchema(schemaInput)(ctx)
}

val updateSchemaServerEndpoint: ZServerEndpoint[Any, Any] =
updateSchemaEndpoint.zServerLogic {
case (ctx: RequestContext, author: String, id: UUID, schemaInput: CredentialSchemaInput) =>
credentialSchemaController.updateSchema(author, id, schemaInput)(ctx)
}

val getSchemaByIdServerEndpoint: ZServerEndpoint[Any, Any] =
getSchemaByIdEndpoint.zServerLogic { case (ctx: RequestContext, guid: UUID) =>
credentialSchemaController.getSchemaByGuid(guid)(ctx)
Expand All @@ -61,6 +68,7 @@ class SchemaRegistryServerEndpoints(
val all: List[ZServerEndpoint[Any, Any]] =
List(
createSchemaServerEndpoint,
updateSchemaServerEndpoint,
getSchemaByIdServerEndpoint,
lookupSchemasByQueryServerEndpoint,
testServerEndpoint
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ trait CredentialSchemaController {
def createSchema(in: CredentialSchemaInput)(implicit
rc: RequestContext
): IO[FailureResponse, CredentialSchemaResponse]

def updateSchema(author: String, id: UUID, in: CredentialSchemaInput)(implicit
rc: RequestContext
): IO[FailureResponse, CredentialSchemaResponse]

def getSchemaByGuid(id: UUID)(implicit
rc: RequestContext
): IO[FailureResponse, CredentialSchemaResponse]
Expand All @@ -43,8 +48,13 @@ object CredentialSchemaController {
error match {
case RepositoryError(cause: Throwable) =>
InternalServerError(cause.getMessage)
case NotFoundError(guid: UUID) =>
NotFound(s"CredentialSchema is not found by guid $guid")
case NotFoundError(_, _, message) =>
NotFound(message)
case UpdateError(id, version, author, message) =>
BadRequest(
msg = s"Credential schema update error: id=$id, version=$version",
errors = List(message)
)
case UnexpectedError(msg: String) => InternalServerError(msg)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import io.iohk.atala.pollux.credentialschema.http.CredentialSchemaInput.toDomain
import io.iohk.atala.pollux.credentialschema.http.CredentialSchemaResponse.fromDomain
import io.iohk.atala.pollux.credentialschema.http.{
CredentialSchemaInput,
CredentialSchemaResponsePage,
CredentialSchemaResponse,
CredentialSchemaResponsePage,
FilterInput
}
import zio.{IO, Task, URLayer, ZIO, ZLayer}
Expand All @@ -29,6 +29,14 @@ class CredentialSchemaControllerImpl(service: CredentialSchemaService) extends C
.map(cs => fromDomain(cs).withBaseUri(rc.request.uri))
}

override def updateSchema(author: String, id: UUID, in: CredentialSchemaInput)(implicit
rc: RequestContext
): IO[FailureResponse, CredentialSchemaResponse] = {
service
.update(id, toDomain(in).copy(author = author))
.map(cs => fromDomain(cs).withBaseUri(rc.request.uri))
}

override def getSchemaByGuid(guid: UUID)(implicit
rc: RequestContext
): IO[FailureResponse, CredentialSchemaResponse] = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ case class CredentialSchemaInput(
@description(annotations.tags.description)
@encodedExample(annotations.tags.example)
tags: Seq[String],
@description(annotations.author.description)
@encodedExample(annotations.author.example)
@validate(pattern(DIDRefRegex))
author: String
)
object CredentialSchemaInput {
def toDomain(in: CredentialSchemaInput): Input =
Expand All @@ -42,7 +46,7 @@ object CredentialSchemaInput {
description = in.description.getOrElse(""),
`type` = in.`type`,
schema = in.schema,
author = "did:prism:agent",
author = in.author,
authored = None
)
given encoder: JsonEncoder[CredentialSchemaInput] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ object CredentialSchemaBasicSpec extends ZIOSpecDefault with CredentialSchemaTes
.fromJson[zio.json.ast.Json]
.toOption
.get,
tags = List("test")
tags = List("test"),
author = "did:prism:agent"
)

def spec = (
Expand Down Expand Up @@ -94,7 +95,8 @@ object CredentialSchemaBasicSpec extends ZIOSpecDefault with CredentialSchemaTes
description = Option(credentialSchema.description),
`type` = credentialSchema.`type`,
schema = credentialSchema.schema,
tags = credentialSchema.tags
tags = credentialSchema.tags,
author = credentialSchema.author
)

credentialSchemaIsCreated = assert(schemaInput)(equalTo(actualFields))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,19 +111,22 @@ trait CredentialSchemaGen {
val schemaTags: Gen[Any, List[String]] =
Gen.setOfBounded(0, 3)(schemaTag).map(_.toList)

val schemaAuthor = Gen.alphaNumericStringBounded(64, 64).map(id => s"did:prism:$id")

val schemaInput = for {
name <- schemaName
version <- schemaVersion
description <- schemaDescription
attributes <- schemaAttributes
author <- schemaAuthor
tags <- schemaTags
} yield CredentialSchemaInput(
name = name,
version = version,
description = Some(description),
`type` = "json",
schema = Arr(Obj("first_name" -> Str("String"))),
tags = tags
tags = tags,
author = author
)
}

Expand Down
5 changes: 3 additions & 2 deletions tests/e2e-tests/src/test/kotlin/common/CredentialSchemas.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.ObjectMapper
import java.util.*

object CredentialSchemas {

val CREDENTIAL_SCHEMA_TYPE = "https://w3c-ccg.github.io/vc-json-schemas/schema/2.0/schema.json"

val SCHEMA_TYPE = "https://json-schema.org/draft/2019-09/schema"
Expand All @@ -28,7 +29,7 @@ object CredentialSchemas {

fun generate_with_name_suffix(suffix: String): CredentialSchema {
return CredentialSchema(
author = "University",
author = "did:prism:agent",
name = "${UUID.randomUUID()} $suffix",
description = "Simple student credentials schema",
type = CREDENTIAL_SCHEMA_TYPE,
Expand All @@ -39,7 +40,7 @@ object CredentialSchemas {
}

val STUDENT_SCHEMA = CredentialSchema(
author = "University",
author = "did:prism:agent",
name = UUID.randomUUID().toString(),
description = "Simple student credentials schema",
type = CREDENTIAL_SCHEMA_TYPE,
Expand Down

0 comments on commit d3a8d15

Please sign in to comment.