diff --git a/src/main/resources/interface-specification.yml b/src/main/resources/interface-specification.yml index 36391474..4becb779 100644 --- a/src/main/resources/interface-specification.yml +++ b/src/main/resources/interface-specification.yml @@ -792,14 +792,20 @@ paths: responses: '204': description: Document deleted. - '404': - description: E-Service descriptor document not found + '400': + description: Bad request content: application/problem+json: schema: - $ref: '#/components/schemas/Problem' - '400': - description: Bad request + $ref: '#/components/schemas/Problem' + '403': + description: Forbidden + content: + application/problem+json: + schema: + $ref: '#/components/schemas/Problem' + '404': + description: E-Service descriptor document not found content: application/problem+json: schema: 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 bd607458..21aefe8a 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 @@ -548,6 +548,8 @@ final case class ProcessApiServiceImpl( documentUuid <- documentId.toFutureUUID catalogItem <- catalogManagementService.getEServiceById(eServiceUuid) _ <- assertRequesterAllowed(catalogItem.producerId)(organizationId) + descriptor <- assertDescriptorExists(catalogItem, descriptorUuid) + _ <- isDraftDescriptor(descriptor) result <- catalogManagementService.deleteEServiceDocument( eServiceUuid.toString, descriptorUuid.toString, 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 88c12e55..cc5ebcad 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 @@ -213,8 +213,10 @@ object ResponseHandlers extends AkkaResponses { )(result: Try[T])(implicit contexts: Seq[(String, String)], logger: LoggerTakingImplicit[ContextFieldsToLog]): Route = result match { case Success(s) => success(s) + case Failure(ex: NotValidDescriptor) => badRequest(ex, logMessage) case Failure(ex: OperationForbidden.type) => forbidden(ex, logMessage) case Failure(ex: EServiceNotFound) => notFound(ex, logMessage) + case Failure(ex: EServiceDescriptorNotFound) => notFound(ex, logMessage) case Failure(ex: DescriptorDocumentNotFound) => 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 f9a9871d..bb1e658b 100644 --- a/src/test/scala/it/pagopa/interop/catalogprocess/CatalogProcessSpec.scala +++ b/src/test/scala/it/pagopa/interop/catalogprocess/CatalogProcessSpec.scala @@ -786,27 +786,40 @@ class CatalogProcessSpec extends SpecHelper with AnyWordSpecLike with ScalatestR } } "EService document deletion" should { - "succeed" in { - val requesterId = UUID.randomUUID() + "succeed only on Draft descriptor" 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 eServiceDoc = SpecData.eServiceDoc - val descriptor = + val eServiceDescriptor = SpecData.eServiceDescriptor.copy( - state = CatalogManagementDependency.EServiceDescriptorState.PUBLISHED, + id = descriptorId, + state = CatalogManagementDependency.EServiceDescriptorState.DRAFT, docs = Seq(eServiceDoc) ) - val eService = SpecData.eService.copy(descriptors = Seq(descriptor), producerId = requesterId) + val eService = SpecData.eService.copy(descriptors = Seq(eServiceDescriptor), producerId = requesterId) + + val descriptor = + SpecData.catalogDescriptor.copy( + id = descriptorId, + docs = Seq(SpecData.catalogDocument.copy(id = eServiceDoc.id)), + state = Draft + ) (mockCatalogManagementService .getEServiceById(_: UUID)(_: ExecutionContext, _: ReadModelService)) .expects(eService.id, *, *) .once() - .returns(Future.successful(SpecData.catalogItem.copy(id = eService.id, producerId = requesterId))) + .returns( + Future.successful( + SpecData.catalogItem.copy(id = eService.id, producerId = requesterId, descriptors = Seq(descriptor)) + ) + ) (mockCatalogManagementService .deleteEServiceDocument(_: String, _: String, _: String)(_: Seq[(String, String)])) @@ -860,6 +873,82 @@ class CatalogProcessSpec extends SpecHelper with AnyWordSpecLike with ScalatestR status shouldEqual StatusCodes.NotFound } } + "fail if descriptor does not exists" in { + val requesterId = UUID.randomUUID() + + implicit val context: Seq[(String, String)] = + Seq("bearer" -> bearerToken, USER_ROLES -> "admin", ORGANIZATION_ID_CLAIM -> requesterId.toString) + + val eService = SpecData.eService.copy(descriptors = Seq.empty, producerId = requesterId) + + val descriptor = + SpecData.catalogDescriptor.copy( + id = UUID.randomUUID(), + docs = Seq(SpecData.catalogDocument.copy(id = SpecData.eServiceDoc.id)), + state = Draft + ) + + (mockCatalogManagementService + .getEServiceById(_: UUID)(_: ExecutionContext, _: ReadModelService)) + .expects(eService.id, *, *) + .once() + .returns( + Future.successful( + SpecData.catalogItem.copy(id = eService.id, producerId = requesterId, descriptors = Seq(descriptor)) + ) + ) + + Delete() ~> service.deleteEServiceDocumentById( + eService.id.toString, + UUID.randomUUID().toString, + SpecData.eServiceDoc.id.toString + ) ~> check { + status shouldEqual StatusCodes.NotFound + } + } + "fail if Descriptor is not Draft" 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 eServiceDoc = SpecData.eServiceDoc + + val eServiceDescriptor = + SpecData.eServiceDescriptor.copy( + id = descriptorId, + state = CatalogManagementDependency.EServiceDescriptorState.PUBLISHED, + docs = Seq(eServiceDoc) + ) + + val eService = SpecData.eService.copy(descriptors = Seq(eServiceDescriptor), producerId = requesterId) + + val descriptor = + SpecData.catalogDescriptor.copy( + id = descriptorId, + docs = Seq(SpecData.catalogDocument.copy(id = eServiceDoc.id)), + state = Published + ) + + (mockCatalogManagementService + .getEServiceById(_: UUID)(_: ExecutionContext, _: ReadModelService)) + .expects(eService.id, *, *) + .once() + .returns( + Future.successful( + SpecData.catalogItem.copy(id = eService.id, producerId = requesterId, descriptors = Seq(descriptor)) + ) + ) + + Delete() ~> service.deleteEServiceDocumentById( + eService.id.toString, + descriptor.id.toString, + eServiceDoc.id.toString + ) ~> check { + status shouldEqual StatusCodes.BadRequest + } + } } "Descriptor creation" should { "succeed" in { @@ -2749,7 +2838,7 @@ class CatalogProcessSpec extends SpecHelper with AnyWordSpecLike with ScalatestR } } "Document deletion" should { - "succeed" in { + "succeed only on Draft Descriptor" in { val requesterId = UUID.randomUUID() val descriptorId = UUID.randomUUID() val documentId = UUID.randomUUID() @@ -2758,7 +2847,11 @@ class CatalogProcessSpec extends SpecHelper with AnyWordSpecLike with ScalatestR Seq("bearer" -> bearerToken, USER_ROLES -> "admin", ORGANIZATION_ID_CLAIM -> requesterId.toString) val descriptor = - SpecData.catalogDescriptor.copy(id = descriptorId, docs = Seq(SpecData.catalogDocument.copy(id = documentId))) + SpecData.catalogDescriptor.copy( + id = descriptorId, + docs = Seq(SpecData.catalogDocument.copy(id = documentId)), + state = Draft + ) val eService = SpecData.catalogItem.copy(descriptors = Seq(descriptor), producerId = requesterId) @@ -2820,6 +2913,67 @@ class CatalogProcessSpec extends SpecHelper with AnyWordSpecLike with ScalatestR status shouldEqual StatusCodes.Forbidden } } + "fail if descriptor does not exists" in { + val requesterId = UUID.randomUUID() + val descriptorId = UUID.randomUUID() + val documentId = 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 = UUID.randomUUID(), + docs = Seq(SpecData.catalogDocument.copy(id = documentId)) + ) + + val eService = SpecData.catalogItem.copy(descriptors = Seq(descriptor), producerId = requesterId) + + (mockCatalogManagementService + .getEServiceById(_: UUID)(_: ExecutionContext, _: ReadModelService)) + .expects(SpecData.catalogItem.id, *, *) + .once() + .returns(Future.successful(eService)) + + Delete() ~> service.deleteEServiceDocumentById( + SpecData.catalogItem.id.toString, + descriptorId.toString, + documentId.toString + ) ~> check { + status shouldEqual StatusCodes.NotFound + } + } + "fail if descriptor is not Draft" in { + val requesterId = UUID.randomUUID() + val descriptorId = UUID.randomUUID() + val documentId = 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, + docs = Seq(SpecData.catalogDocument.copy(id = documentId)), + state = Published + ) + + val eService = SpecData.catalogItem.copy(descriptors = Seq(descriptor), producerId = requesterId) + + (mockCatalogManagementService + .getEServiceById(_: UUID)(_: ExecutionContext, _: ReadModelService)) + .expects(SpecData.catalogItem.id, *, *) + .once() + .returns(Future.successful(eService)) + + Delete() ~> service.deleteEServiceDocumentById( + SpecData.catalogItem.id.toString, + descriptorId.toString, + documentId.toString + ) ~> check { + status shouldEqual StatusCodes.BadRequest + } + } } "Risk Analysis creation" should { "succeed" in {