From 9d4944baeeae007ddd31c82e34a5ac590a40e12a Mon Sep 17 00:00:00 2001 From: nttdata-rtorsoli Date: Mon, 22 Jan 2024 17:30:52 +0100 Subject: [PATCH 1/2] PIN-4448 Check in case of Interface load if there is already one present --- .../api/impl/ProcessApiServiceImpl.scala | 8 ++++ .../api/impl/ResponseHandlers.scala | 1 + .../errors/CatalogProcessErrors.scala | 3 ++ .../catalogprocess/CatalogProcessSpec.scala | 46 +++++++++++++++++++ 4 files changed, 58 insertions(+) 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 59498d53..53b4cba9 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 @@ -310,6 +310,9 @@ final case class ProcessApiServiceImpl( catalogItem <- catalogManagementService.getEServiceById(eServiceUuid) _ <- assertRequesterAllowed(catalogItem.producerId)(organizationId) descriptor <- assertDescriptorExists(catalogItem, descriptorUuid) + _ <- + if (documentSeed.kind == EServiceDocumentKind.INTERFACE) assertInterfaceDoesNotExists(descriptor) + else Future.unit updated <- catalogManagementService.createEServiceDocument(catalogItem.id, descriptor.id, managementSeed) } yield updated.toApi @@ -818,4 +821,9 @@ object ProcessApiServiceImpl { .find(_.id == descriptorId) .toFuture(EServiceDescriptorNotFound(eService.id.toString, descriptorId.toString)) + def assertInterfaceDoesNotExists(descriptor: CatalogDescriptor): Future[Unit] = + descriptor.interface match { + case Some(_) => Future.failed(InterfaceAlreadyExists(descriptor.id)) + case None => Future.unit + } } diff --git a/src/main/scala/it/pagopa/interop/catalogprocess/api/impl/ResponseHandlers.scala b/src/main/scala/it/pagopa/interop/catalogprocess/api/impl/ResponseHandlers.scala index 1cad3126..17d5825a 100644 --- a/src/main/scala/it/pagopa/interop/catalogprocess/api/impl/ResponseHandlers.scala +++ b/src/main/scala/it/pagopa/interop/catalogprocess/api/impl/ResponseHandlers.scala @@ -198,6 +198,7 @@ object ResponseHandlers extends AkkaResponses { result match { case Success(s) => success(s) case Failure(ex: OperationForbidden.type) => forbidden(ex, logMessage) + case Failure(ex: InterfaceAlreadyExists) => forbidden(ex, logMessage) case Failure(ex: EServiceNotFound) => notFound(ex, logMessage) case Failure(ex: EServiceDescriptorNotFound) => notFound(ex, logMessage) case Failure(ex) => internalServerError(ex, logMessage) diff --git a/src/main/scala/it/pagopa/interop/catalogprocess/errors/CatalogProcessErrors.scala b/src/main/scala/it/pagopa/interop/catalogprocess/errors/CatalogProcessErrors.scala index 3025293d..484ce0db 100644 --- a/src/main/scala/it/pagopa/interop/catalogprocess/errors/CatalogProcessErrors.scala +++ b/src/main/scala/it/pagopa/interop/catalogprocess/errors/CatalogProcessErrors.scala @@ -76,4 +76,7 @@ object CatalogProcessErrors { final case class AttributeNotFound(attributeId: UUID) extends ComponentError("0020", s"Attribute ${attributeId.toString} not found") + final case class InterfaceAlreadyExists(descriptorId: UUID) + extends ComponentError("0021", s"Descriptor ${descriptorId.toString} already has an interface") + } diff --git a/src/test/scala/it/pagopa/interop/catalogprocess/CatalogProcessSpec.scala b/src/test/scala/it/pagopa/interop/catalogprocess/CatalogProcessSpec.scala index 8b9bed4c..d2ad6f3a 100644 --- a/src/test/scala/it/pagopa/interop/catalogprocess/CatalogProcessSpec.scala +++ b/src/test/scala/it/pagopa/interop/catalogprocess/CatalogProcessSpec.scala @@ -2313,6 +2313,52 @@ class CatalogProcessSpec extends SpecHelper with AnyWordSpecLike with ScalatestR status shouldEqual StatusCodes.Forbidden } } + "fail if document is an interface and it already exists" in { + val requesterId = UUID.randomUUID() + val descriptorId = UUID.randomUUID() + implicit val context: Seq[(String, String)] = + Seq("bearer" -> bearerToken, USER_ROLES -> "admin", ORGANIZATION_ID_CLAIM -> requesterId.toString) + + val descriptor = SpecData.catalogDescriptor.copy( + id = descriptorId, + interface = Some( + CatalogDocument( + id = UUID.randomUUID(), + name = "name", + contentType = "application/yaml", + prettyName = "pretty", + path = "path", + checksum = "checksum", + uploadDate = OffsetDateTimeSupplier.get().minusDays(10) + ) + ) + ) + + val eService = SpecData.catalogItem.copy(descriptors = Seq(descriptor), producerId = requesterId) + + val documentId = UUID.randomUUID() + + val seed = CreateEServiceDescriptorDocumentSeed( + documentId = documentId, + kind = EServiceDocumentKind.INTERFACE, + prettyName = "prettyName", + filePath = "filePath", + fileName = "fileName", + contentType = "application/json", + checksum = "checksum", + serverUrls = Seq.empty + ) + + (mockCatalogManagementService + .getEServiceById(_: UUID)(_: ExecutionContext, _: ReadModelService)) + .expects(SpecData.catalogItem.id, *, *) + .once() + .returns(Future.successful(eService)) + + Post() ~> service.createEServiceDocument(SpecData.catalogItem.id.toString, descriptorId.toString, seed) ~> check { + status shouldEqual StatusCodes.Forbidden + } + } } "Document retrieve" should { "succeed" in { From d4b3c109ea0a64ca58fd87b093f658968c862594 Mon Sep 17 00:00:00 2001 From: nttdata-rtorsoli Date: Thu, 25 Jan 2024 16:41:23 +0100 Subject: [PATCH 2/2] PIN-4448 Resolved PR issue --- .../interop/catalogprocess/api/impl/ResponseHandlers.scala | 2 +- .../it/pagopa/interop/catalogprocess/CatalogProcessSpec.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/it/pagopa/interop/catalogprocess/api/impl/ResponseHandlers.scala b/src/main/scala/it/pagopa/interop/catalogprocess/api/impl/ResponseHandlers.scala index 17d5825a..27535f40 100644 --- a/src/main/scala/it/pagopa/interop/catalogprocess/api/impl/ResponseHandlers.scala +++ b/src/main/scala/it/pagopa/interop/catalogprocess/api/impl/ResponseHandlers.scala @@ -198,7 +198,7 @@ object ResponseHandlers extends AkkaResponses { result match { case Success(s) => success(s) case Failure(ex: OperationForbidden.type) => forbidden(ex, logMessage) - case Failure(ex: InterfaceAlreadyExists) => forbidden(ex, logMessage) + case Failure(ex: InterfaceAlreadyExists) => badRequest(ex, logMessage) case Failure(ex: EServiceNotFound) => notFound(ex, logMessage) case Failure(ex: EServiceDescriptorNotFound) => notFound(ex, logMessage) case Failure(ex) => internalServerError(ex, logMessage) diff --git a/src/test/scala/it/pagopa/interop/catalogprocess/CatalogProcessSpec.scala b/src/test/scala/it/pagopa/interop/catalogprocess/CatalogProcessSpec.scala index d2ad6f3a..23af147c 100644 --- a/src/test/scala/it/pagopa/interop/catalogprocess/CatalogProcessSpec.scala +++ b/src/test/scala/it/pagopa/interop/catalogprocess/CatalogProcessSpec.scala @@ -2356,7 +2356,7 @@ class CatalogProcessSpec extends SpecHelper with AnyWordSpecLike with ScalatestR .returns(Future.successful(eService)) Post() ~> service.createEServiceDocument(SpecData.catalogItem.id.toString, descriptorId.toString, seed) ~> check { - status shouldEqual StatusCodes.Forbidden + status shouldEqual StatusCodes.BadRequest } } }