From 8875ac645286b90fa5960c75155f296a0066c852 Mon Sep 17 00:00:00 2001 From: Riccardo Torsoli <122275960+nttdata-rtorsoli@users.noreply.github.com> Date: Mon, 21 Aug 2023 10:28:38 +0200 Subject: [PATCH] PIN-3794 Prevent the creation of the EService for not IPA organization (#203) Co-authored-by: nttdata-rtorsoli --- .../resources/interface-specification.yml | 6 +++ .../api/impl/ProcessApiServiceImpl.scala | 6 ++- .../api/impl/ResponseHandlers.scala | 1 + .../errors/CatalogProcessErrors.scala | 3 ++ .../catalogprocess/CatalogProcessSpec.scala | 38 +++++++++++++++++-- 5 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/main/resources/interface-specification.yml b/src/main/resources/interface-specification.yml index 3fb4d77c..756829ac 100644 --- a/src/main/resources/interface-specification.yml +++ b/src/main/resources/interface-specification.yml @@ -140,6 +140,12 @@ paths: application/problem+json: schema: $ref: '#/components/schemas/Problem' + '403': + description: Forbidden + content: + application/problem+json: + schema: + $ref: '#/components/schemas/Problem' '409': description: Name Conflict content: 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 8b2e8dd2..00fb01f5 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 @@ -18,7 +18,7 @@ import it.pagopa.interop.commons.cqrs.service.ReadModelService import it.pagopa.interop.commons.files.service.FileManager import it.pagopa.interop.commons.jwt._ import it.pagopa.interop.commons.logging.{CanLogContextFields, ContextFieldsToLog} -import it.pagopa.interop.commons.utils.AkkaUtils.getOrganizationIdFutureUUID +import it.pagopa.interop.commons.utils.AkkaUtils._ import it.pagopa.interop.commons.utils.OpenapiUtils.parseArrayParameters import it.pagopa.interop.commons.utils.TypeConversions._ import it.pagopa.interop.commons.utils.errors.GenericComponentErrors @@ -49,6 +49,8 @@ final case class ProcessApiServiceImpl( implicit val logger: LoggerTakingImplicit[ContextFieldsToLog] = Logger.takingImplicit[ContextFieldsToLog](this.getClass) + val IPA = "IPA" + override def createEService(eServiceSeed: EServiceSeed)(implicit contexts: Seq[(String, String)], toEntityMarshallerProblem: ToEntityMarshaller[Problem], @@ -59,6 +61,8 @@ final case class ProcessApiServiceImpl( val result: Future[EService] = for { organizationId <- getOrganizationIdFutureUUID(contexts) + origin <- getExternalIdOriginFuture(contexts) + _ <- if (origin == IPA) Future.unit else Future.failed(OriginIsNotCompliant(IPA)) clientSeed = eServiceSeed.toDependency(organizationId) maybeEservice <- catalogManagementService .getEServices( 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 5839eb8e..00a74051 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 @@ -43,6 +43,7 @@ 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: OriginIsNotCompliant) => forbidden(ex, logMessage) case Failure(ex: DuplicatedEServiceName) => conflict(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 360cf31e..5bcaa849 100644 --- a/src/main/scala/it/pagopa/interop/catalogprocess/errors/CatalogProcessErrors.scala +++ b/src/main/scala/it/pagopa/interop/catalogprocess/errors/CatalogProcessErrors.scala @@ -43,4 +43,7 @@ object CatalogProcessErrors { final case class DuplicatedEServiceName(name: String) extends ComponentError("0010", s"EService with name: $name already in use") + final case class OriginIsNotCompliant(origin: String) + extends ComponentError("0011", s"Requester has not origin: $origin") + } diff --git a/src/test/scala/it/pagopa/interop/catalogprocess/CatalogProcessSpec.scala b/src/test/scala/it/pagopa/interop/catalogprocess/CatalogProcessSpec.scala index 613f6e8a..daaa4314 100644 --- a/src/test/scala/it/pagopa/interop/catalogprocess/CatalogProcessSpec.scala +++ b/src/test/scala/it/pagopa/interop/catalogprocess/CatalogProcessSpec.scala @@ -8,7 +8,7 @@ import it.pagopa.interop.catalogmanagement.client.model.AgreementApprovalPolicy. import it.pagopa.interop.catalogmanagement.client.{model => CatalogManagementDependency} import it.pagopa.interop.catalogprocess.api.impl.Converter._ import it.pagopa.interop.catalogprocess.api.impl._ -import it.pagopa.interop.commons.utils.{ORGANIZATION_ID_CLAIM, USER_ROLES} +import it.pagopa.interop.commons.utils._ import it.pagopa.interop.commons.cqrs.service.ReadModelService import it.pagopa.interop.catalogprocess.errors.CatalogProcessErrors.{EServiceNotFound, DescriptorDocumentNotFound} import it.pagopa.interop.catalogmanagement.model.{ @@ -274,7 +274,13 @@ class CatalogProcessSpec extends SpecHelper with AnyWordSpecLike with ScalatestR val catalogItems: Seq[CatalogItem] = Seq.empty implicit val context: Seq[(String, String)] = - Seq("bearer" -> bearerToken, USER_ROLES -> "admin", ORGANIZATION_ID_CLAIM -> requesterId.toString) + Seq( + "bearer" -> bearerToken, + USER_ROLES -> "admin", + ORGANIZATION_ID_CLAIM -> requesterId.toString, + ORGANIZATION_EXTERNAL_ID_ORIGIN -> "IPA", + ORGANIZATION_EXTERNAL_ID_VALUE -> "12345" + ) val apiSeed: EServiceSeed = EServiceSeed(name = "MyService", description = "My Service", technology = EServiceTechnology.REST) @@ -380,7 +386,13 @@ class CatalogProcessSpec extends SpecHelper with AnyWordSpecLike with ScalatestR val requesterId = UUID.randomUUID() implicit val context: Seq[(String, String)] = - Seq("bearer" -> bearerToken, USER_ROLES -> "admin", ORGANIZATION_ID_CLAIM -> requesterId.toString) + Seq( + "bearer" -> bearerToken, + USER_ROLES -> "admin", + ORGANIZATION_ID_CLAIM -> requesterId.toString, + ORGANIZATION_EXTERNAL_ID_ORIGIN -> "IPA", + ORGANIZATION_EXTERNAL_ID_VALUE -> "12345" + ) val catalogItems: Seq[CatalogItem] = Seq(SpecData.catalogItem) @@ -406,6 +418,26 @@ class CatalogProcessSpec extends SpecHelper with AnyWordSpecLike with ScalatestR status shouldEqual StatusCodes.Conflict } } + "fail with forbidden requester origin is not IPA" in { + + val requesterId = UUID.randomUUID() + + implicit val context: Seq[(String, String)] = + Seq( + "bearer" -> bearerToken, + USER_ROLES -> "admin", + ORGANIZATION_ID_CLAIM -> requesterId.toString, + ORGANIZATION_EXTERNAL_ID_ORIGIN -> "NOT_IPA", + ORGANIZATION_EXTERNAL_ID_VALUE -> "12345" + ) + + val apiSeed: EServiceSeed = + EServiceSeed(name = "MyService", description = "My Service", technology = EServiceTechnology.REST) + + Post() ~> service.createEService(apiSeed) ~> check { + status shouldEqual StatusCodes.Forbidden + } + } } "EService update" should { "succeed" in {