From a0d24691ee51acfa7ccdd4cac2cb047e35769381 Mon Sep 17 00:00:00 2001 From: nttdata-rtorsoli Date: Fri, 2 Feb 2024 11:50:23 +0100 Subject: [PATCH] PIN-4486 BKE - Catalog-Process - Endpoint /eservices/{eServiceId} - Applied visibility on retrieve single eservice --- .../api/impl/ProcessApiServiceImpl.scala | 29 +++++- .../catalogprocess/CatalogProcessSpec.scala | 89 ++++++++++++++++++- 2 files changed, 112 insertions(+), 6 deletions(-) diff --git a/src/main/scala/it/pagopa/interop/catalogprocess/api/impl/ProcessApiServiceImpl.scala b/src/main/scala/it/pagopa/interop/catalogprocess/api/impl/ProcessApiServiceImpl.scala index 21aefe8a..ac9c7105 100644 --- a/src/main/scala/it/pagopa/interop/catalogprocess/api/impl/ProcessApiServiceImpl.scala +++ b/src/main/scala/it/pagopa/interop/catalogprocess/api/impl/ProcessApiServiceImpl.scala @@ -318,6 +318,26 @@ final case class ProcessApiServiceImpl( } } + private def applyVisibilityToEService( + catalogItem: CatalogItem, + organizationId: UUID, + role: String + ): Future[CatalogItem] = { + if (Seq(ADMIN_ROLE, API_ROLE).contains(role) && catalogItem.producerId == organizationId) + Future.successful(catalogItem) + else { + catalogItem match { + case CatalogItem(_, _, _, _, _, _, descriptors, _, _, _) if (descriptors.isEmpty) => + Future.failed(EServiceNotFound(catalogItem.id.toString)) + case CatalogItem(_, _, _, _, _, _, descriptors, _, _, _) + if (descriptors.size == 1 && descriptors.exists(_.state == Draft)) => + Future.failed(EServiceNotFound(catalogItem.id.toString)) + case CatalogItem(_, _, _, _, _, _, descriptors, _, _, _) => + Future.successful(catalogItem.copy(descriptors = descriptors.filterNot(_.state == Draft))) + } + } + } + override def getEServiceById(eServiceId: String)(implicit contexts: Seq[(String, String)], toEntityMarshallerProblem: ToEntityMarshaller[Problem], @@ -327,9 +347,12 @@ final case class ProcessApiServiceImpl( logger.info(operationLabel) val result: Future[EService] = for { - eServiceUuid <- eServiceId.toFutureUUID - eService <- catalogManagementService.getEServiceById(eServiceUuid) - } yield eService.toApi + organizationId <- getOrganizationIdFutureUUID(contexts) + eServiceUuid <- eServiceId.toFutureUUID + role <- getUserRolesFuture(contexts) + eService <- catalogManagementService.getEServiceById(eServiceUuid) + catalogItem <- applyVisibilityToEService(eService, organizationId, role) + } yield catalogItem.toApi onComplete(result) { getEServiceByIdResponse[EService](operationLabel)(getEServiceById200) diff --git a/src/test/scala/it/pagopa/interop/catalogprocess/CatalogProcessSpec.scala b/src/test/scala/it/pagopa/interop/catalogprocess/CatalogProcessSpec.scala index bb1e658b..7c023805 100644 --- a/src/test/scala/it/pagopa/interop/catalogprocess/CatalogProcessSpec.scala +++ b/src/test/scala/it/pagopa/interop/catalogprocess/CatalogProcessSpec.scala @@ -34,7 +34,7 @@ import scala.concurrent.{ExecutionContext, Future} class CatalogProcessSpec extends SpecHelper with AnyWordSpecLike with ScalatestRouteTest { "Eservice retrieve" should { - "succeed when found" in { + "succeed when found with role admin and requester is the producer " in { val eServiceId = UUID.randomUUID() val requesterId = UUID.randomUUID() @@ -45,13 +45,29 @@ class CatalogProcessSpec extends SpecHelper with AnyWordSpecLike with ScalatestR .getEServiceById(_: UUID)(_: ExecutionContext, _: ReadModelService)) .expects(eServiceId, *, *) .once() - .returns(Future.successful(SpecData.catalogItem)) + .returns(Future.successful(SpecData.catalogItem.copy(producerId = requesterId))) Get() ~> service.getEServiceById(eServiceId.toString) ~> check { status shouldEqual StatusCodes.OK } } + "succeed when found with role api and requester is the producer " in { + val eServiceId = UUID.randomUUID() + val requesterId = UUID.randomUUID() + implicit val context: Seq[(String, String)] = + Seq("bearer" -> bearerToken, USER_ROLES -> "api", ORGANIZATION_ID_CLAIM -> requesterId.toString) + + (mockCatalogManagementService + .getEServiceById(_: UUID)(_: ExecutionContext, _: ReadModelService)) + .expects(eServiceId, *, *) + .once() + .returns(Future.successful(SpecData.catalogItem.copy(producerId = requesterId))) + + Get() ~> service.getEServiceById(eServiceId.toString) ~> check { + status shouldEqual StatusCodes.OK + } + } "fail with 404 when not found" in { val eServiceId = UUID.randomUUID() val requesterId = UUID.randomUUID() @@ -67,10 +83,77 @@ class CatalogProcessSpec extends SpecHelper with AnyWordSpecLike with ScalatestR Get() ~> service.getEServiceById(eServiceId.toString) ~> check { status shouldEqual StatusCodes.NotFound + val problem = responseAs[Problem] + problem.status shouldBe StatusCodes.NotFound.intValue + problem.errors.head.code shouldBe "009-0007" + } + } + "fail with 404 when eservice has no descriptor and requester is not the producer" in { + val eServiceId = UUID.randomUUID() + + implicit val context: Seq[(String, String)] = + Seq("bearer" -> bearerToken, USER_ROLES -> "admin", ORGANIZATION_ID_CLAIM -> UUID.randomUUID().toString) + + (mockCatalogManagementService + .getEServiceById(_: UUID)(_: ExecutionContext, _: ReadModelService)) + .expects(eServiceId, *, *) + .once() + .returns(Future.successful(SpecData.catalogItem)) + + Get() ~> service.getEServiceById(eServiceId.toString) ~> check { + status shouldEqual StatusCodes.NotFound + val problem = responseAs[Problem] + problem.status shouldBe StatusCodes.NotFound.intValue + problem.errors.head.code shouldBe "009-0007" } } - } + "fail with 404 when eservice has only a draft descriptor and requester is not the producer" in { + val eServiceId = UUID.randomUUID() + implicit val context: Seq[(String, String)] = + Seq("bearer" -> bearerToken, USER_ROLES -> "admin", ORGANIZATION_ID_CLAIM -> UUID.randomUUID().toString) + + (mockCatalogManagementService + .getEServiceById(_: UUID)(_: ExecutionContext, _: ReadModelService)) + .expects(eServiceId, *, *) + .once() + .returns( + Future + .successful(SpecData.catalogItem.copy(descriptors = Seq(SpecData.catalogDescriptor.copy(state = Draft)))) + ) + + Get() ~> service.getEServiceById(eServiceId.toString) ~> check { + status shouldEqual StatusCodes.NotFound + val problem = responseAs[Problem] + problem.status shouldBe StatusCodes.NotFound.intValue + problem.errors.head.code shouldBe "009-0007" + } + } + "succeed when eservice has several descriptors and requester is not the producer" in { + val eServiceId = UUID.randomUUID() + + implicit val context: Seq[(String, String)] = + Seq("bearer" -> bearerToken, USER_ROLES -> "admin", ORGANIZATION_ID_CLAIM -> UUID.randomUUID().toString) + + (mockCatalogManagementService + .getEServiceById(_: UUID)(_: ExecutionContext, _: ReadModelService)) + .expects(eServiceId, *, *) + .once() + .returns( + Future + .successful( + SpecData.catalogItem + .copy(descriptors = Seq(SpecData.catalogDescriptor, SpecData.catalogDescriptor.copy(state = Draft))) + ) + ) + + Get() ~> service.getEServiceById(eServiceId.toString) ~> check { + status shouldEqual StatusCodes.OK + val response: EService = responseAs[EService] + response.descriptors.filterNot(_.state == EServiceDescriptorState.DRAFT).size shouldEqual 1 + } + } + } "EServices retrieve" should { "succeed when Agreement States are empty" in {