diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/credentialschema/SchemaRegistryServerEndpoints.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/credentialschema/SchemaRegistryServerEndpoints.scala index a6be73f5c4..75c8f4b1ec 100644 --- a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/credentialschema/SchemaRegistryServerEndpoints.scala +++ b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/credentialschema/SchemaRegistryServerEndpoints.scala @@ -61,21 +61,15 @@ class SchemaRegistryServerEndpoints( lookupSchemasByQueryEndpoint .zServerSecurityLogic(SecurityLogic.authorizeWalletAccessWith(_)(authenticator, authorizer)) .serverLogic { wac => - { - case ( - ctx: RequestContext, - filter: FilterInput, - paginationInput: PaginationInput, - order: Option[Order] - ) => - credentialSchemaController - .lookupSchemas( - filter, - paginationInput.toPagination, - order - )(ctx) - .provideSomeLayer(ZLayer.succeed(wac)) - .logTrace(ctx) + { case (ctx: RequestContext, filter: FilterInput, paginationInput: PaginationInput, order: Option[Order]) => + credentialSchemaController + .lookupSchemas( + filter, + paginationInput.toPagination, + order + )(ctx) + .provideSomeLayer(ZLayer.succeed(wac)) + .logTrace(ctx) } } diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/credentialschema/controller/CredentialSchemaController.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/credentialschema/controller/CredentialSchemaController.scala index 303dbe1b4d..89b87d16b5 100644 --- a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/credentialschema/controller/CredentialSchemaController.scala +++ b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/credentialschema/controller/CredentialSchemaController.scala @@ -3,7 +3,7 @@ package org.hyperledger.identus.pollux.credentialschema.controller import org.hyperledger.identus.api.http.* import org.hyperledger.identus.api.http.model.{Order, Pagination} import org.hyperledger.identus.pollux.core.service.CredentialSchemaService -import org.hyperledger.identus.pollux.core.service.CredentialSchemaService.Error.* +import org.hyperledger.identus.pollux.core.service.CredentialSchemaService.* import org.hyperledger.identus.pollux.credentialschema.http.{ CredentialSchemaInput, CredentialSchemaResponse, @@ -50,23 +50,7 @@ trait CredentialSchemaController { object CredentialSchemaController { def domainToHttpError( error: CredentialSchemaService.Error - ): ErrorResponse = { - error match { - case RepositoryError(cause: Throwable) => - ErrorResponse.internalServerError("RepositoryError", detail = Option(cause.toString)) - case NotFoundError(_, _, message) => - ErrorResponse.notFound(detail = Option(message)) - case UpdateError(id, version, author, message) => - ErrorResponse.badRequest( - title = "CredentialSchemaUpdateError", - detail = Option(s"Credential schema update error: id=$id, version=$version, author=$author, msg=$message") - ) - case UnexpectedError(msg: String) => - ErrorResponse.internalServerError(detail = Option(msg)) - case CredentialSchemaValidationError(cause) => - ErrorResponse.badRequest(detail = Some(cause.message)) - } - } + ): ErrorResponse = error implicit def domainToHttpErrorIO[R, T]( domainIO: ZIO[R, CredentialSchemaService.Error, T] diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/credentialschema/controller/CredentialSchemaControllerImpl.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/credentialschema/controller/CredentialSchemaControllerImpl.scala index 30bb53e064..d1407f7101 100644 --- a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/credentialschema/controller/CredentialSchemaControllerImpl.scala +++ b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/credentialschema/controller/CredentialSchemaControllerImpl.scala @@ -7,7 +7,7 @@ import org.hyperledger.identus.api.http.model.{CollectionStats, Order, Paginatio import org.hyperledger.identus.castor.core.model.did.{LongFormPrismDID, PrismDID} import org.hyperledger.identus.pollux.core.model.schema.CredentialSchema.FilteredEntries import org.hyperledger.identus.pollux.core.service.CredentialSchemaService -import org.hyperledger.identus.pollux.core.service.CredentialSchemaService.Error.* +import org.hyperledger.identus.pollux.core.service.CredentialSchemaService.* import org.hyperledger.identus.pollux.credentialschema.controller.CredentialSchemaController.domainToHttpErrorIO import org.hyperledger.identus.pollux.credentialschema.http.{ CredentialSchemaInput, @@ -30,29 +30,23 @@ class CredentialSchemaControllerImpl(service: CredentialSchemaService, managedDI )(implicit rc: RequestContext ): ZIO[WalletAccessContext, ErrorResponse, CredentialSchemaResponse] = { - (for { + for { validated <- validatePrismDID(in.author) result <- service .create(toDomain(in)) .map(cs => fromDomain(cs).withBaseUri(rc.request.uri)) - } yield result).mapError { - case e: ErrorResponse => e - case e: CredentialSchemaService.Error => CredentialSchemaController.domainToHttpError(e) - } + } yield result } override def updateSchema(author: String, id: UUID, in: CredentialSchemaInput)(implicit rc: RequestContext ): ZIO[WalletAccessContext, ErrorResponse, CredentialSchemaResponse] = { - (for { + for { _ <- validatePrismDID(in.author) result <- service .update(id, toDomain(in).copy(author = author)) .map(cs => fromDomain(cs).withBaseUri(rc.request.uri)) - } yield result).mapError { - case e: ErrorResponse => e - case e: CredentialSchemaService.Error => CredentialSchemaController.domainToHttpError(e) - } + } yield result } override def getSchemaByGuid(guid: UUID)(implicit @@ -112,7 +106,7 @@ class CredentialSchemaControllerImpl(service: CredentialSchemaService, managedDI for { authorDID <- ZIO .fromEither(PrismDID.fromString(author)) - .mapError(_ => ErrorResponse.badRequest(detail = Some(s"Unable to parse as a Prism DID: ${author}"))) + .mapError(ex => ErrorResponse.badRequest(detail = Some(s"Unable to parse Prism DID from '${author}' due: $ex"))) longFormPrismDID <- getLongForm(authorDID, true) } yield longFormPrismDID @@ -125,7 +119,7 @@ class CredentialSchemaControllerImpl(service: CredentialSchemaService, managedDI .getManagedDIDState(did.asCanonical) .mapError(e => ErrorResponse.internalServerError(detail = - Some(s"Error occurred while getting did from wallet: ${e.toString}") + Some(s"Error occurred while getting DID from wallet: ${e.toString}") ) ) .someOrFail(ErrorResponse.notFound(detail = Some(s"Issuer DID does not exist in the wallet: $did"))) diff --git a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/credentialschema/controller/CredentialSchemaControllerLogic.scala b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/credentialschema/controller/CredentialSchemaControllerLogic.scala index a57c5e3186..b4afaf255e 100644 --- a/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/credentialschema/controller/CredentialSchemaControllerLogic.scala +++ b/cloud-agent/service/server/src/main/scala/org/hyperledger/identus/pollux/credentialschema/controller/CredentialSchemaControllerLogic.scala @@ -13,10 +13,10 @@ case class CredentialSchemaControllerLogic( stats: CollectionStats ) { - def composeNextUri(uri: Uri): Option[Uri] = + private def composeNextUri(uri: Uri): Option[Uri] = PaginationUtils.composeNextUri(uri, page.contents, pagination, stats) - def composePreviousUri(uri: Uri): Option[Uri] = + private def composePreviousUri(uri: Uri): Option[Uri] = PaginationUtils.composePreviousUri(uri, page.contents, pagination, stats) def result: CredentialSchemaResponsePage = { diff --git a/cloud-agent/service/server/src/test/scala/org/hyperledger/identus/pollux/schema/CredentialSchemaAnoncredSpec.scala b/cloud-agent/service/server/src/test/scala/org/hyperledger/identus/pollux/schema/CredentialSchemaAnoncredSpec.scala index 03ad6e43ed..439baffed6 100644 --- a/cloud-agent/service/server/src/test/scala/org/hyperledger/identus/pollux/schema/CredentialSchemaAnoncredSpec.scala +++ b/cloud-agent/service/server/src/test/scala/org/hyperledger/identus/pollux/schema/CredentialSchemaAnoncredSpec.scala @@ -108,7 +108,17 @@ object CredentialSchemaAnoncredSpec extends ZIOSpecDefault with CredentialSchema for { response <- createResponse[ErrorResponse]("WrongSchema") } yield assert(response.body)( - isRight(hasField("detail", _.detail, isSome(equalTo("Unsupported VC Schema type WrongSchema")))) + isRight( + hasField( + "detail", + _.detail, + isSome( + equalTo( + "Credential Schema Validation Error=UnsupportedCredentialSchemaType(Unsupported VC Schema type WrongSchema)" + ) + ) + ) + ) ) } ) @@ -121,7 +131,7 @@ object CredentialSchemaAnoncredSpec extends ZIOSpecDefault with CredentialSchema response <- createResponse[ErrorResponse](CredentialJsonSchemaType.`type`) } yield assert(response.body)( isRight( - hasField("detail", _.detail, isSome(containsString("required property '$schema' not found;"))) + hasField("detail", _.detail, isSome(containsString("required property '$schema' not found"))) ) ) } diff --git a/cloud-agent/service/server/src/test/scala/org/hyperledger/identus/pollux/schema/CredentialSchemaMultiTenancySpec.scala b/cloud-agent/service/server/src/test/scala/org/hyperledger/identus/pollux/schema/CredentialSchemaMultiTenancySpec.scala index 382a5c5661..b05834e52e 100644 --- a/cloud-agent/service/server/src/test/scala/org/hyperledger/identus/pollux/schema/CredentialSchemaMultiTenancySpec.scala +++ b/cloud-agent/service/server/src/test/scala/org/hyperledger/identus/pollux/schema/CredentialSchemaMultiTenancySpec.scala @@ -105,10 +105,10 @@ object CredentialSchemaMultiTenancySpec extends ZIOSpecDefault with CredentialSc .exit aliceCannotUpdateBobsVCSchema = assert(notFoundSchemaAError)( - fails(isSubtype[CredentialSchemaService.Error.NotFoundError](anything)) + fails(isSubtype[CredentialSchemaService.GuidNotFoundError](anything)) ) bobCannotUpdateAlicesVCSchema = assert(notFoundSchemaBError)( - fails(isSubtype[CredentialSchemaService.Error.NotFoundError](anything)) + fails(isSubtype[CredentialSchemaService.GuidNotFoundError](anything)) ) fetchedSchemaAbyB <- service.getByGUID(updatedSchemaA.guid).provideLayer(Bob.wacLayer) diff --git a/cloud-agent/service/server/src/test/scala/org/hyperledger/identus/pollux/schema/CredentialSchemaTestTools.scala b/cloud-agent/service/server/src/test/scala/org/hyperledger/identus/pollux/schema/CredentialSchemaTestTools.scala index 91965a9dc3..2c3f148e54 100644 --- a/cloud-agent/service/server/src/test/scala/org/hyperledger/identus/pollux/schema/CredentialSchemaTestTools.scala +++ b/cloud-agent/service/server/src/test/scala/org/hyperledger/identus/pollux/schema/CredentialSchemaTestTools.scala @@ -113,11 +113,11 @@ trait CredentialSchemaTestTools extends PostgresTestContainerSupport { backend } - def deleteAllCredentialSchemas: RIO[CredentialSchemaRepository & WalletAccessContext, Long] = { + def deleteAllCredentialSchemas: RIO[CredentialSchemaRepository & WalletAccessContext, Unit] = { for { repository <- ZIO.service[CredentialSchemaRepository] - count <- repository.deleteAll() - } yield count + result <- repository.deleteAll() + } yield result } } diff --git a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/model/schema/CredentialDefinition.scala b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/model/schema/CredentialDefinition.scala index 4193073032..d6d97a45d6 100644 --- a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/model/schema/CredentialDefinition.scala +++ b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/model/schema/CredentialDefinition.scala @@ -86,7 +86,7 @@ object CredentialDefinition { definition: Definition, proofSchemaId: String, proof: CorrectnessProof - ): ZIO[Any, Nothing, CredentialDefinition] = { + ): UIO[CredentialDefinition] = { for { id <- zio.Random.nextUUID cs <- make(id, in, definitionSchemaId, definition, proofSchemaId, proof) @@ -100,7 +100,7 @@ object CredentialDefinition { definition: Definition, keyCorrectnessProofSchemaId: String, keyCorrectnessProof: CorrectnessProof - ): ZIO[Any, Nothing, CredentialDefinition] = { + ): UIO[CredentialDefinition] = { for { ts <- zio.Clock.currentDateTime.map( _.atZoneSameInstant(ZoneOffset.UTC).toOffsetDateTime diff --git a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/model/schema/CredentialSchema.scala b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/model/schema/CredentialSchema.scala index aabbeb6af7..6b9246b3dd 100644 --- a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/model/schema/CredentialSchema.scala +++ b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/model/schema/CredentialSchema.scala @@ -65,13 +65,13 @@ object CredentialSchema { def makeGUID(author: String, id: UUID, version: String) = UUID.nameUUIDFromBytes(makeLongId(author, id, version).getBytes) - def make(in: Input): ZIO[Any, Nothing, CredentialSchema] = { + def make(in: Input): UIO[CredentialSchema] = { for { id <- zio.Random.nextUUID cs <- make(id, in) } yield cs } - def make(id: UUID, in: Input): ZIO[Any, Nothing, CredentialSchema] = { + def make(id: UUID, in: Input): UIO[CredentialSchema] = { for { ts <- zio.Clock.currentDateTime.map( _.atZoneSameInstant(ZoneOffset.UTC).toOffsetDateTime diff --git a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/repository/CredentialDefinitionRepositoryInMemory.scala b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/repository/CredentialDefinitionRepositoryInMemory.scala index dd70e656c9..3b28a99339 100644 --- a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/repository/CredentialDefinitionRepositoryInMemory.scala +++ b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/repository/CredentialDefinitionRepositoryInMemory.scala @@ -98,7 +98,7 @@ class CredentialDefinitionRepositoryInMemory( override def search( query: Repository.SearchQuery[CredentialDefinition.Filter] - ): RIO[WalletAccessContext, Repository.SearchResult[CredentialDefinition]] = { + ): URIO[WalletAccessContext, Repository.SearchResult[CredentialDefinition]] = { walletStoreRef.flatMap { storeRef => storeRef.get.map { store => val filtered = store.values.filter { credDef => diff --git a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/repository/CredentialSchemaRepository.scala b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/repository/CredentialSchemaRepository.scala index bcbbbc62cc..d3fa782ba8 100644 --- a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/repository/CredentialSchemaRepository.scala +++ b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/repository/CredentialSchemaRepository.scala @@ -4,22 +4,22 @@ import org.hyperledger.identus.pollux.core.model.schema.CredentialSchema import org.hyperledger.identus.pollux.core.model.schema.CredentialSchema.* import org.hyperledger.identus.pollux.core.repository.Repository.SearchCapability import org.hyperledger.identus.shared.models.WalletAccessContext -import zio.{RIO, Task} +import zio.{UIO, URIO} import java.util.UUID trait CredentialSchemaRepository extends Repository[WalletTask, CredentialSchema] with SearchCapability[WalletTask, CredentialSchema.Filter, CredentialSchema] { - def create(cs: CredentialSchema): RIO[WalletAccessContext, CredentialSchema] + def create(cs: CredentialSchema): URIO[WalletAccessContext, CredentialSchema] - def getByGuid(guid: UUID): Task[Option[CredentialSchema]] + def findByGuid(guid: UUID): UIO[Option[CredentialSchema]] - def update(cs: CredentialSchema): RIO[WalletAccessContext, Option[CredentialSchema]] + def update(cs: CredentialSchema): URIO[WalletAccessContext, CredentialSchema] - def getAllVersions(id: UUID, author: String): RIO[WalletAccessContext, Seq[String]] + def getAllVersions(id: UUID, author: String): URIO[WalletAccessContext, List[String]] - def delete(guid: UUID): RIO[WalletAccessContext, Option[CredentialSchema]] + def delete(guid: UUID): URIO[WalletAccessContext, CredentialSchema] - def deleteAll(): RIO[WalletAccessContext, Long] + def deleteAll(): URIO[WalletAccessContext, Unit] } diff --git a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/repository/repository.scala b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/repository/repository.scala index 5b8f422039..8de5400c4c 100644 --- a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/repository/repository.scala +++ b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/repository/repository.scala @@ -1,11 +1,11 @@ package org.hyperledger.identus.pollux.core.repository import org.hyperledger.identus.shared.models.WalletAccessContext -import zio.RIO +import zio.URIO trait Repository[F[_], T] -type WalletTask[T] = RIO[WalletAccessContext, T] +type WalletTask[T] = URIO[WalletAccessContext, T] object Repository { case class SearchQuery[Filter](filter: Filter, skip: Int, limit: Int) diff --git a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/CredentialDefinitionServiceImpl.scala b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/CredentialDefinitionServiceImpl.scala index 263d4d139f..0f793d7bd0 100644 --- a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/CredentialDefinitionServiceImpl.scala +++ b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/CredentialDefinitionServiceImpl.scala @@ -101,7 +101,6 @@ class CredentialDefinitionServiceImpl( override def lookup(filter: CredentialDefinition.Filter, skip: Int, limit: Int): Result[FilteredEntries] = { credentialDefinitionRepository .search(SearchQuery(filter, skip, limit)) - .mapError(t => RepositoryError(t)) .map(sr => FilteredEntries(sr.entries, sr.count.toInt, sr.totalCount.toInt)) } diff --git a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/CredentialSchemaService.scala b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/CredentialSchemaService.scala index dbe40c6115..de077fb042 100644 --- a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/CredentialSchemaService.scala +++ b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/CredentialSchemaService.scala @@ -3,12 +3,12 @@ package org.hyperledger.identus.pollux.core.service import org.hyperledger.identus.pollux.core.model.error.CredentialSchemaError import org.hyperledger.identus.pollux.core.model.schema.CredentialSchema import org.hyperledger.identus.pollux.core.model.schema.CredentialSchema.* -import org.hyperledger.identus.shared.models.WalletAccessContext +import org.hyperledger.identus.shared.models.{Failure, StatusCode, WalletAccessContext} import zio.{IO, ZIO} import java.util.UUID trait CredentialSchemaService { - type Result[T] = ZIO[WalletAccessContext, CredentialSchemaService.Error, T] + private[service] type Result[T] = ZIO[WalletAccessContext, CredentialSchemaService.Error, T] /** @param in * CredentialSchema form for creating the instance @@ -32,26 +32,28 @@ trait CredentialSchemaService { } object CredentialSchemaService { - sealed trait Error - - object Error { - def apply(throwable: Throwable): Error = RepositoryError(throwable) - - final case class RepositoryError(cause: Throwable) extends Error - - final case class NotFoundError(guid: Option[UUID] = None, id: Option[UUID] = None, message: String) extends Error - - object NotFoundError { - def byGuid(guid: UUID): NotFoundError = - NotFoundError(guid = Option(guid), message = s"Credential schema record cannot be found by `guid`=$guid") - def byId(id: UUID): NotFoundError = - NotFoundError(id = Option(id), message = s"Credential schema record cannot be found by `id`=$id") - } - - final case class UpdateError(id: UUID, version: String, author: String, message: String) extends Error - - final case class UnexpectedError(msg: String) extends Error - - final case class CredentialSchemaValidationError(cause: CredentialSchemaError) extends Error + sealed trait Error( + val statusCode: StatusCode, + val userFacingMessage: String + ) extends Failure { + override val namespace = "CredentialSchema" } + + final case class GuidNotFoundError(guid: UUID) + extends Error( + StatusCode.NotFound, + s"Credential Schema record cannot be found by `guid`=$guid" + ) + + final case class UpdateError(id: UUID, version: String, author: String, message: String) + extends Error( + StatusCode.BadRequest, + s"Credential schema update error: id=$id, version=$version, author=$author, msg=$message" + ) + + final case class CredentialSchemaValidationError(cause: CredentialSchemaError) + extends Error( + StatusCode.BadRequest, + s"Credential Schema Validation Error=$cause" + ) } diff --git a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/CredentialSchemaServiceImpl.scala b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/CredentialSchemaServiceImpl.scala index fc29d9b80a..3b499c9f62 100644 --- a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/CredentialSchemaServiceImpl.scala +++ b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/CredentialSchemaServiceImpl.scala @@ -5,9 +5,9 @@ import org.hyperledger.identus.pollux.core.model.schema.CredentialSchema import org.hyperledger.identus.pollux.core.model.schema.CredentialSchema.FilteredEntries import org.hyperledger.identus.pollux.core.repository.CredentialSchemaRepository import org.hyperledger.identus.pollux.core.repository.Repository.SearchQuery -import org.hyperledger.identus.pollux.core.service.CredentialSchemaService.Error.* +import org.hyperledger.identus.pollux.core.service.CredentialSchemaService.* +import zio.* import zio.{IO, URLayer, ZLayer} -import zio.ZIO.{fail, getOrFailWith, succeed} import java.util.UUID @@ -18,21 +18,17 @@ class CredentialSchemaServiceImpl( for { credentialSchema <- CredentialSchema.make(in) _ <- CredentialSchema.validateCredentialSchema(credentialSchema) - createdCredentialSchema <- credentialSchemaRepository - .create(credentialSchema) + createdCredentialSchema <- credentialSchemaRepository.create(credentialSchema) } yield createdCredentialSchema - }.mapError { - case e: CredentialSchemaError => CredentialSchemaValidationError(e) - case t: Throwable => RepositoryError(t) + }.mapError { (e: CredentialSchemaError) => + CredentialSchemaValidationError(e) } override def getByGUID(guid: UUID): IO[CredentialSchemaService.Error, CredentialSchema] = { - credentialSchemaRepository - .getByGuid(guid) - .mapError[CredentialSchemaService.Error](t => RepositoryError(t)) - .flatMap( - getOrFailWith(NotFoundError.byGuid(guid))(_) - ) + for { + resultOpt <- credentialSchemaRepository.findByGuid(guid) + result <- ZIO.fromOption(resultOpt).mapError(_ => GuidNotFoundError(guid)) + } yield result } def getBy( @@ -44,58 +40,44 @@ class CredentialSchemaServiceImpl( } override def update( - id: UUID, + guid: UUID, in: CredentialSchema.Input ): Result[CredentialSchema] = { for { - cs <- CredentialSchema.make(id, in) + cs <- CredentialSchema.make(guid, in) _ <- CredentialSchema.validateCredentialSchema(cs).mapError(CredentialSchemaValidationError.apply) - existingVersions <- credentialSchemaRepository - .getAllVersions(id, in.author) - .mapError[CredentialSchemaService.Error](RepositoryError.apply) - _ <- existingVersions.headOption match { - case None => - fail(NotFoundError.byId(id)) - case _ => - succeed(cs) - } + existingVersions <- credentialSchemaRepository.getAllVersions(guid, in.author) + _ <- ZIO.fromOption(existingVersions.headOption).mapError(_ => GuidNotFoundError(guid)) _ <- existingVersions.find(_ > in.version) match { case Some(higherVersion) => - fail( + ZIO.fail( UpdateError( - id, + guid, in.version, in.author, s"Higher version is found: $higherVersion" ) ) case None => - succeed(cs) + ZIO.succeed(cs) } _ <- existingVersions.find(_ == in.version) match { case Some(existingVersion) => - fail( + ZIO.fail( UpdateError( - id, + guid, in.version, in.author, s"The version already exists: $existingVersion" ) ) - case None => succeed(cs) + case None => ZIO.succeed(cs) } - updated <- credentialSchemaRepository - .create(cs) - .mapError[CredentialSchemaService.Error](RepositoryError.apply) + updated <- credentialSchemaRepository.create(cs) } yield updated } override def delete(guid: UUID): Result[CredentialSchema] = { - for { - deleted_row_opt <- credentialSchemaRepository - .delete(guid) - .mapError(RepositoryError.apply) - deleted_row <- getOrFailWith(NotFoundError.byGuid(guid))(deleted_row_opt) - } yield deleted_row + credentialSchemaRepository.delete(guid) } override def lookup( @@ -105,7 +87,6 @@ class CredentialSchemaServiceImpl( ): Result[CredentialSchema.FilteredEntries] = { credentialSchemaRepository .search(SearchQuery(filter, skip, limit)) - .mapError(t => RepositoryError(t)) .map(sr => FilteredEntries(sr.entries, sr.count.toInt, sr.totalCount.toInt)) } } diff --git a/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/verification/CredentialSchemaServiceError.scala b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/verification/CredentialSchemaServiceError.scala new file mode 100644 index 0000000000..d94ac24d60 --- /dev/null +++ b/pollux/core/src/main/scala/org/hyperledger/identus/pollux/core/service/verification/CredentialSchemaServiceError.scala @@ -0,0 +1,33 @@ +package org.hyperledger.identus.pollux.core.service.verification + +import org.hyperledger.identus.pollux.core.model.error.CredentialSchemaError +import org.hyperledger.identus.pollux.core.model.schema.CredentialSchema +import org.hyperledger.identus.pollux.core.model.schema.CredentialSchema.* +import org.hyperledger.identus.shared.models.{Failure, StatusCode} + +import java.util.UUID + +sealed trait CredentialSchemaServiceError( + val statusCode: StatusCode, + val userFacingMessage: String +) extends Failure { + override val namespace = "CredentialSchema" +} + +final case class GuidNotFoundError(guid: UUID) + extends CredentialSchemaServiceError( + StatusCode.NotFound, + s"Credential Schema record cannot be found by `guid`=$guid" + ) + +final case class UpdateError(id: UUID, version: String, author: String, message: String) + extends CredentialSchemaServiceError( + StatusCode.BadRequest, + s"Credential schema update error: id=$id, version=$version, author=$author, msg=$message" + ) + +final case class CredentialSchemaValidationError(cause: CredentialSchemaError) + extends CredentialSchemaServiceError( + StatusCode.BadRequest, + s"Credential Schema Validation Error=${cause.message}" + ) diff --git a/pollux/sql-doobie/src/main/scala/org/hyperledger/identus/pollux/sql/repository/JdbcCredentialDefinitionRepository.scala b/pollux/sql-doobie/src/main/scala/org/hyperledger/identus/pollux/sql/repository/JdbcCredentialDefinitionRepository.scala index dd69969de2..29d05db502 100644 --- a/pollux/sql-doobie/src/main/scala/org/hyperledger/identus/pollux/sql/repository/JdbcCredentialDefinitionRepository.scala +++ b/pollux/sql-doobie/src/main/scala/org/hyperledger/identus/pollux/sql/repository/JdbcCredentialDefinitionRepository.scala @@ -71,7 +71,7 @@ case class JdbcCredentialDefinitionRepository(xa: Transactor[ContextAwareTask], override def search( query: SearchQuery[CredentialDefinition.Filter] - ): RIO[WalletAccessContext, SearchResult[CredentialDefinition]] = { + ): URIO[WalletAccessContext, SearchResult[CredentialDefinition]] = { for { filteredRows <- CredentialDefinitionSql .lookup( @@ -83,6 +83,7 @@ case class JdbcCredentialDefinitionRepository(xa: Transactor[ContextAwareTask], limit = query.limit ) .transactWallet(xa) + .orDie entries = filteredRows.map(CredentialDefinitionRow.toModel) filteredRowsCount <- CredentialDefinitionSql @@ -93,8 +94,9 @@ case class JdbcCredentialDefinitionRepository(xa: Transactor[ContextAwareTask], tagOpt = query.filter.tag ) .transactWallet(xa) + .orDie - totalRowsCount <- CredentialDefinitionSql.totalCount.transactWallet(xa) + totalRowsCount <- CredentialDefinitionSql.totalCount.transactWallet(xa).orDie } yield SearchResult(entries, filteredRowsCount, totalRowsCount) } } diff --git a/pollux/sql-doobie/src/main/scala/org/hyperledger/identus/pollux/sql/repository/JdbcCredentialSchemaRepository.scala b/pollux/sql-doobie/src/main/scala/org/hyperledger/identus/pollux/sql/repository/JdbcCredentialSchemaRepository.scala index e624cf4800..606a1e577d 100644 --- a/pollux/sql-doobie/src/main/scala/org/hyperledger/identus/pollux/sql/repository/JdbcCredentialSchemaRepository.scala +++ b/pollux/sql-doobie/src/main/scala/org/hyperledger/identus/pollux/sql/repository/JdbcCredentialSchemaRepository.scala @@ -17,57 +17,62 @@ import java.util.UUID case class JdbcCredentialSchemaRepository(xa: Transactor[ContextAwareTask], xb: Transactor[Task]) extends CredentialSchemaRepository { import CredentialSchemaSql.* - override def create(cs: CredentialSchema): RIO[WalletAccessContext, CredentialSchema] = { + override def create(cs: CredentialSchema): URIO[WalletAccessContext, CredentialSchema] = { ZIO.serviceWithZIO[WalletAccessContext](ctx => CredentialSchemaSql .insert(CredentialSchemaRow.fromModel(cs, ctx.walletId)) .transactWallet(xa) + .orDie .map(CredentialSchemaRow.toModel) ) } - override def getByGuid(guid: UUID): Task[Option[CredentialSchema]] = { + override def findByGuid(guid: UUID): UIO[Option[CredentialSchema]] = { CredentialSchemaSql .findByGUID(guid) .transact(xb) + .orDie .map( _.headOption .map(CredentialSchemaRow.toModel) ) } - override def update(cs: CredentialSchema): RIO[WalletAccessContext, Option[CredentialSchema]] = { + override def update(cs: CredentialSchema): URIO[WalletAccessContext, CredentialSchema] = { ZIO.serviceWithZIO[WalletAccessContext](ctx => CredentialSchemaSql .update(CredentialSchemaRow.fromModel(cs, ctx.walletId)) .transactWallet(xa) - .map(Option.apply) - .map(_.map(CredentialSchemaRow.toModel)) + .orDie + .map(CredentialSchemaRow.toModel) ) } - def getAllVersions(id: UUID, author: String): RIO[WalletAccessContext, Seq[String]] = { + def getAllVersions(id: UUID, author: String): URIO[WalletAccessContext, List[String]] = { CredentialSchemaSql .getAllVersions(id, author) .transactWallet(xa) + .orDie } - override def delete(guid: UUID): RIO[WalletAccessContext, Option[CredentialSchema]] = { + override def delete(guid: UUID): URIO[WalletAccessContext, CredentialSchema] = { CredentialSchemaSql .delete(guid) .transactWallet(xa) - .map(Option.apply) - .map(_.map(CredentialSchemaRow.toModel)) + .orDie + .map(CredentialSchemaRow.toModel) } - def deleteAll(): RIO[WalletAccessContext, Long] = { + def deleteAll(): URIO[WalletAccessContext, Unit] = { CredentialSchemaSql.deleteAll .transactWallet(xa) + .orDie + .flatMap(count => ZIO.unit) } override def search( query: SearchQuery[CredentialSchema.Filter] - ): RIO[WalletAccessContext, SearchResult[CredentialSchema]] = { + ): URIO[WalletAccessContext, SearchResult[CredentialSchema]] = { for { filteredRows <- CredentialSchemaSql .lookup( @@ -79,6 +84,7 @@ case class JdbcCredentialSchemaRepository(xa: Transactor[ContextAwareTask], xb: limit = query.limit ) .transactWallet(xa) + .orDie entries = filteredRows.map(CredentialSchemaRow.toModel) filteredRowsCount <- CredentialSchemaSql @@ -89,8 +95,8 @@ case class JdbcCredentialSchemaRepository(xa: Transactor[ContextAwareTask], xb: tagOpt = query.filter.tags ) .transactWallet(xa) - - totalRowsCount <- CredentialSchemaSql.totalCount.transactWallet(xa) + .orDie + totalRowsCount <- CredentialSchemaSql.totalCount.transactWallet(xa).orDie } yield SearchResult(entries, filteredRowsCount, totalRowsCount) } }