From 60d10827d56ca7897ecbd389c12c4ea4d940b586 Mon Sep 17 00:00:00 2001 From: Riccardo Torsoli <122275960+nttdata-rtorsoli@users.noreply.github.com> Date: Tue, 23 Apr 2024 11:42:46 +0200 Subject: [PATCH] PIN-4804: check purpose version state when adding client purpose (#242) Co-authored-by: nttdata-rtorsoli --- .../api/impl/ClientApiServiceImpl.scala | 7 +- .../error/AuthorizationProcessErrors.scala | 1 - .../PurposeOperationSpec.scala | 100 +++++++++++++++++- 3 files changed, 101 insertions(+), 7 deletions(-) diff --git a/src/main/scala/it/pagopa/interop/authorizationprocess/api/impl/ClientApiServiceImpl.scala b/src/main/scala/it/pagopa/interop/authorizationprocess/api/impl/ClientApiServiceImpl.scala index 237af1e..34299e7 100644 --- a/src/main/scala/it/pagopa/interop/authorizationprocess/api/impl/ClientApiServiceImpl.scala +++ b/src/main/scala/it/pagopa/interop/authorizationprocess/api/impl/ClientApiServiceImpl.scala @@ -32,9 +32,12 @@ import it.pagopa.interop.commons.utils.TypeConversions.{EitherOps, OptionOps, St import it.pagopa.interop.commons.utils.service.OffsetDateTimeSupplier import it.pagopa.interop.purposemanagement.model.purpose.{ Archived, + Rejected, + Draft, PersistentPurposeVersion, PersistentPurposeVersionState, - Active => ActiveState + Active => ActiveState, + WaitingForApproval } import java.util.UUID @@ -330,7 +333,7 @@ final case class ClientApiServiceImpl( Set[PersistentAgreementState](Active, Suspended) val invalidPurposeStates: Set[PersistentPurposeVersionState] = - Set(Archived) + Set(Archived, Rejected, Draft, WaitingForApproval) def descriptorToComponentState( descriptor: CatalogDescriptor diff --git a/src/main/scala/it/pagopa/interop/authorizationprocess/error/AuthorizationProcessErrors.scala b/src/main/scala/it/pagopa/interop/authorizationprocess/error/AuthorizationProcessErrors.scala index e3153d8..6f49265 100644 --- a/src/main/scala/it/pagopa/interop/authorizationprocess/error/AuthorizationProcessErrors.scala +++ b/src/main/scala/it/pagopa/interop/authorizationprocess/error/AuthorizationProcessErrors.scala @@ -63,5 +63,4 @@ object AuthorizationProcessErrors { "0024", s"The number of the keys ${size.toString} for the client ${clientId.toString} exceed maximun allowed" ) - } diff --git a/src/test/scala/it/pagopa/interop/authorizationprocess/PurposeOperationSpec.scala b/src/test/scala/it/pagopa/interop/authorizationprocess/PurposeOperationSpec.scala index 6bc9851..673cb3c 100644 --- a/src/test/scala/it/pagopa/interop/authorizationprocess/PurposeOperationSpec.scala +++ b/src/test/scala/it/pagopa/interop/authorizationprocess/PurposeOperationSpec.scala @@ -10,7 +10,13 @@ import it.pagopa.interop.authorizationprocess.util.SpecUtilsWithImplicit import it.pagopa.interop.authorizationprocess.error.AuthorizationProcessErrors._ import it.pagopa.interop.commons.cqrs.service.ReadModelService import it.pagopa.interop.catalogmanagement.model.Published -import it.pagopa.interop.purposemanagement.model.purpose.{Draft, Active => ActivePurpose, Archived} +import it.pagopa.interop.purposemanagement.model.purpose.{ + Active => ActivePurpose, + WaitingForApproval, + Archived, + Draft, + Suspended => SuspendedPurpose +} import it.pagopa.interop.agreementmanagement.model.agreement.{Pending, Active, Suspended} import org.scalamock.scalatest.MockFactory import org.scalatest.matchers.should.Matchers._ @@ -31,7 +37,7 @@ class PurposeOperationSpec extends AnyWordSpecLike with MockFactory with SpecUti )(ExecutionContext.global, mockReadModel) "Purpose add to Client" should { - "succeed" in { + "succeed if Purpose has Active versions" in { val purposeSeed = AuthorizationManagementDependency.PurposeSeed(states = AuthorizationManagementDependency.ClientStatesChainSeed( @@ -191,7 +197,7 @@ class PurposeOperationSpec extends AnyWordSpecLike with MockFactory with SpecUti } } - "succeed even if Purpose has only draft versions" in { + "succeed even if Purpose has Suspended versions" in { (mockAuthorizationManagementService .getClient(_: UUID)(_: ExecutionContext, _: ReadModelService)) @@ -206,7 +212,56 @@ class PurposeOperationSpec extends AnyWordSpecLike with MockFactory with SpecUti .returns( Future.successful( purpose - .copy(consumerId = consumerId, versions = Seq(purposeVersion.copy(state = Draft))) + .copy(consumerId = consumerId, versions = Seq(purposeVersion.copy(state = SuspendedPurpose))) + ) + ) + + (mockCatalogManagementService + .getEServiceById(_: UUID)(_: ExecutionContext, _: ReadModelService)) + .expects(eService.id, *, *) + .once() + .returns(Future.successful(eService.copy(descriptors = Seq(activeDescriptor.copy(state = Published))))) + + (mockAgreementManagementService + .getAgreements(_: UUID, _: UUID)(_: ExecutionContext, _: ReadModelService)) + .expects(eService.id, consumer.id, *, *) + .once() + .returns(Future.successful(Seq(agreement.copy(state = Active)))) + + (mockAuthorizationManagementService + .addClientPurpose(_: UUID, _: AuthorizationManagementDependency.PurposeSeed)(_: Seq[(String, String)])) + .expects(persistentClient.id, *, *) + .once() + .returns(Future.successful(clientPurpose)) + + Post() ~> service.addClientPurpose(persistentClient.id.toString, PurposeAdditionDetails(purpose.id)) ~> check { + status shouldEqual StatusCodes.NoContent + } + } + + "succeed even if Purpose has Waiting for Approval versions" in { + + (mockAuthorizationManagementService + .getClient(_: UUID)(_: ExecutionContext, _: ReadModelService)) + .expects(persistentClient.id, *, *) + .once() + .returns(Future.successful(persistentClient.copy(consumerId = consumerId))) + + (mockPurposeManagementService + .getPurposeById(_: UUID)(_: ExecutionContext, _: ReadModelService)) + .expects(purpose.id, *, *) + .once() + .returns( + Future.successful( + purpose + .copy( + consumerId = consumerId, + versions = Seq( + purposeVersion + .copy(id = UUID.randomUUID(), state = ActivePurpose, createdAt = timestamp.minusDays(5)), + purposeVersion.copy(state = WaitingForApproval) + ) + ) ) ) @@ -270,4 +325,41 @@ class PurposeOperationSpec extends AnyWordSpecLike with MockFactory with SpecUti } } } + + "fail if Purpose has only draft versions" in { + + (mockAuthorizationManagementService + .getClient(_: UUID)(_: ExecutionContext, _: ReadModelService)) + .expects(persistentClient.id, *, *) + .once() + .returns(Future.successful(persistentClient.copy(consumerId = consumerId))) + + (mockPurposeManagementService + .getPurposeById(_: UUID)(_: ExecutionContext, _: ReadModelService)) + .expects(purpose.id, *, *) + .once() + .returns( + Future.successful( + purpose + .copy(consumerId = consumerId, versions = Seq(purposeVersion.copy(state = Draft))) + ) + ) + + (mockCatalogManagementService + .getEServiceById(_: UUID)(_: ExecutionContext, _: ReadModelService)) + .expects(eService.id, *, *) + .once() + .returns(Future.successful(eService.copy(descriptors = Seq(activeDescriptor.copy(state = Published))))) + + (mockAgreementManagementService + .getAgreements(_: UUID, _: UUID)(_: ExecutionContext, _: ReadModelService)) + .expects(eService.id, consumer.id, *, *) + .once() + .returns(Future.successful(Seq(agreement.copy(state = Active)))) + + Post() ~> service.addClientPurpose(persistentClient.id.toString, PurposeAdditionDetails(purpose.id)) ~> check { + status shouldEqual StatusCodes.BadRequest + responseAs[Problem].errors.head.code shouldEqual "007-0015" + } + } }