Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PIN-3985 Implemented Creation of the RiskAnalisys #207

Merged
merged 38 commits into from
Sep 29, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
af43c72
PIN-3985 Implemented createRiskAnalisys
Sep 27, 2023
a6c59bd
Merge branch 'PIN-3984' into PIN-3985
Sep 27, 2023
254f49a
Merge branch 'PIN-3984' into PIN-3985
Sep 27, 2023
fc49d65
Merge branch 'PIN-3984' into PIN-3985
Sep 27, 2023
334139f
PIN-4020 Implemented Update Risk Analisys
Sep 27, 2023
9ebd123
Merge branch 'PIN-3984' into PIN-3985
Sep 27, 2023
8eb6833
Merge branch 'PIN-3985' into PIN-4020
nttdata-rtorsoli Sep 27, 2023
edcb3a8
PIN-3985 Cleaning
Sep 27, 2023
b54154b
Merge branch 'PIN-3985' into PIN-4020
nttdata-rtorsoli Sep 27, 2023
506d9cd
PIN-4023 Implemented Delete Risk Analysis
Sep 27, 2023
19399ac
PIN-4020 Add 403 on openapi
Sep 27, 2023
b9672be
PIN-395 Add 403 to openapi
Sep 27, 2023
ecb56cf
Merge branch 'PIN-3985' into PIN-4020
nttdata-rtorsoli Sep 27, 2023
13bd7ee
Merge branch 'PIN-4020' into PIN-4023
nttdata-rtorsoli Sep 27, 2023
89ad830
PIN-3985 Resolved PR issues
Sep 27, 2023
2de6778
Merge branch 'PIN-3985' into PIN-4020
nttdata-rtorsoli Sep 27, 2023
b7f3b07
Merge branch 'PIN-4020' into PIN-4023
nttdata-rtorsoli Sep 27, 2023
9e6fa24
PIN-3996 Check when EService is published
Sep 28, 2023
ada4c7e
PR-4023 Resolved PR issue, added check of the receive mode for eService
Sep 28, 2023
efc0eac
Merge branch 'PIN-4023' into PIN-3996
nttdata-rtorsoli Sep 28, 2023
444dfd9
PR-3996 Resolved PR issues
Sep 28, 2023
c9593e8
PIN-3985 Resolved PR issues
Sep 29, 2023
b25f259
PIN-4021 Resolved PR issues
Sep 29, 2023
137b466
Merge branch 'PIN-3985' into PIN-4020
nttdata-rtorsoli Sep 29, 2023
ef1bd13
Merge branch 'PIN-4020' into PIN-4023
nttdata-rtorsoli Sep 29, 2023
eddb376
Merge branch 'PIN-4023' into PIN-3996
nttdata-rtorsoli Sep 29, 2023
706f1d1
PIN-3996 Resolved PR issues
Sep 29, 2023
4aff227
PIN-4020 Resolved PR issue
Sep 29, 2023
856e38e
Merge branch 'PIN-4020' into PIN-4023
nttdata-rtorsoli Sep 29, 2023
fba2147
Merge branch 'PIN-4023' into PIN-3996
nttdata-rtorsoli Sep 29, 2023
dd5f3a4
PIN-3996 Resolved PR issue
Sep 29, 2023
dd4b746
PIN-4020 Resolved endpoint in camel case
Sep 29, 2023
a5ab8a0
Merge branch 'PIN-4020' into PIN-4023
nttdata-rtorsoli Sep 29, 2023
4332f00
Merge branch 'PIN-4023' into PIN-3996
nttdata-rtorsoli Sep 29, 2023
dcb791e
PIN-3996 Cleaning
Sep 29, 2023
67f26fc
Merge pull request #210 from pagopa/PIN-3996
nttdata-rtorsoli Sep 29, 2023
72e4a1a
Merge pull request #209 from pagopa/PIN-4023
nttdata-rtorsoli Sep 29, 2023
4d39187
Merge pull request #208 from pagopa/PIN-4020
nttdata-rtorsoli Sep 29, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ object Dependencies {

lazy val catalogManagementClient =
namespace %% "interop-be-catalog-management-client" % catalogManagementVersion

lazy val tenantManagementModels =
namespace %% "interop-be-tenant-management-models" % tenantManagementVersion

lazy val catalogManagementModels =
namespace %% "interop-be-catalog-management-models" % catalogManagementVersion

Expand All @@ -80,10 +84,11 @@ object Dependencies {
lazy val authorizationManagementClient =
namespace %% "interop-be-authorization-management-client" % authorizationManagementVersion

lazy val commonsUtils = namespace %% "interop-commons-utils" % commonsVersion
lazy val fileManager = namespace %% "interop-commons-file-manager" % commonsVersion
lazy val commonsJWT = namespace %% "interop-commons-jwt" % commonsVersion
lazy val commonsCqrs = namespace %% "interop-commons-cqrs" % commonsVersion
lazy val commonsUtils = namespace %% "interop-commons-utils" % commonsVersion
lazy val fileManager = namespace %% "interop-commons-file-manager" % commonsVersion
lazy val commonsJWT = namespace %% "interop-commons-jwt" % commonsVersion
lazy val commonsCqrs = namespace %% "interop-commons-cqrs" % commonsVersion
lazy val riskAnalysis = namespace %% "interop-commons-risk-analysis" % commonsVersion
}

object Jars {
Expand All @@ -109,10 +114,12 @@ object Dependencies {
pagopa.catalogManagementModels % Compile,
pagopa.agreementManagementModels % Compile,
pagopa.authorizationManagementClient % Compile,
pagopa.tenantManagementModels % Compile,
pagopa.commonsUtils % Compile,
pagopa.fileManager % Compile,
pagopa.commonsJWT % Compile,
pagopa.commonsCqrs % Compile,
pagopa.riskAnalysis % Compile,
akka.testkit % Test,
akka.httpTestkit % Test,
scalatest.core % Test,
Expand Down
95 changes: 95 additions & 0 deletions src/main/resources/interface-specification.yml
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,53 @@ paths:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
/eservices/{eServiceId}/riskAnalysis:
parameters:
- $ref: '#/components/parameters/CorrelationIdHeader'
- $ref: '#/components/parameters/IpAddress'
post:
security:
- bearerAuth: []
tags:
- process
summary: Create an e-service risk analysis
operationId: createRiskAnalysis
parameters:
- name: eServiceId
in: path
description: the eservice id
required: true
schema:
type: string
format: uuid
requestBody:
description: A payload containing the risk analysis
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/EServiceRiskAnalysisSeed'
responses:
'204':
description: EService Risk Analysis created.
'403':
description: Forbidden
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'404':
description: EService not found
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'400':
description: Bad request
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
/status:
get:
security: []
Expand Down Expand Up @@ -1106,6 +1153,54 @@ components:
format: uuid
name:
type: string
EServiceRiskAnalysisSeed:
type: object
required:
- name
- riskAnalysisForm
properties:
name:
type: string
riskAnalysisForm:
$ref: '#/components/schemas/EServiceRiskAnalysisFormSeed'
EServiceRiskAnalysisFormSeed:
type: object
required:
- version
- singleAnswers
- multiAnswers
properties:
version:
type: string
singleAnswers:
type: array
items:
$ref: '#/components/schemas/EServiceRiskAnalysisSingleAnswerSeed'
multiAnswers:
type: array
items:
$ref: '#/components/schemas/EServiceRiskAnalysisMultiAnswerSeed'
EServiceRiskAnalysisSingleAnswerSeed:
type: object
required:
- key
properties:
key:
type: string
value:
type: string
EServiceRiskAnalysisMultiAnswerSeed:
type: object
required:
- key
- values
properties:
key:
type: string
values:
type: array
items:
type: string
EService:
type: object
required:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package it.pagopa.interop.catalogprocess.api.impl
import it.pagopa.interop.agreementmanagement.model.{agreement => AgreementPersistenceModel}
import it.pagopa.interop.catalogmanagement.client.{model => CatalogManagementDependency}
import it.pagopa.interop.catalogmanagement.{model => readmodel}
import it.pagopa.interop.commons.riskanalysis.{model => Commons}
import it.pagopa.interop.catalogprocess.model._
import it.pagopa.interop.catalogprocess.common.readmodel.Consumers
import it.pagopa.interop.tenantmanagement.model.tenant.PersistentTenantKind
import it.pagopa.interop.catalogmanagement.model.{Deliver, Receive}

import java.util.UUID
Expand Down Expand Up @@ -99,6 +101,48 @@ object Converter {
)
}

implicit class EServiceRiskAnalysisSeedWrapper(private val seed: EServiceRiskAnalysisSeed) extends AnyVal {
def toDependency: CatalogManagementDependency.RiskAnalysisSeed = CatalogManagementDependency.RiskAnalysisSeed(
name = seed.name,
riskAnalysisForm = seed.riskAnalysisForm.toDependency
)
}

implicit class EServiceRiskAnalysisFormSeedWrapper(private val seed: EServiceRiskAnalysisFormSeed) extends AnyVal {
def toDependency: CatalogManagementDependency.RiskAnalysisFormSeed =
CatalogManagementDependency.RiskAnalysisFormSeed(
version = seed.version,
singleAnswers = seed.singleAnswers.map(_.toDependency),
multiAnswers = seed.multiAnswers.map(_.toDependency)
)
def toTemplate: Commons.RiskAnalysisForm = Commons.RiskAnalysisForm(
version = seed.version,
answers = (seed.singleAnswers.map(_.toTemplate).flatten ++ seed.multiAnswers.map(_.toTemplate).flatten).toMap
)
}

implicit class PersistentTenantKindrapper(private val kind: PersistentTenantKind) extends AnyVal {
def toTemplate: Commons.RiskAnalysisTenantKind = kind match {
case PersistentTenantKind.PA => Commons.RiskAnalysisTenantKind.PA
case PersistentTenantKind.GSP => Commons.RiskAnalysisTenantKind.GSP
case PersistentTenantKind.PRIVATE => Commons.RiskAnalysisTenantKind.PRIVATE
}
}

implicit class EServiceRiskAnalysisSingleAnswerSeedWrapper(private val seed: EServiceRiskAnalysisSingleAnswerSeed)
extends AnyVal {
def toDependency: CatalogManagementDependency.RiskAnalysisSingleAnswerSeed =
CatalogManagementDependency.RiskAnalysisSingleAnswerSeed(key = seed.key, value = seed.value)
def toTemplate: Map[String, Seq[String]] = Map(seed.key -> seed.value.toSeq)
}

implicit class EServiceRiskAnalysisMultiAnswerSeedWrapper(private val seed: EServiceRiskAnalysisMultiAnswerSeed)
extends AnyVal {
def toDependency: CatalogManagementDependency.RiskAnalysisMultiAnswerSeed =
CatalogManagementDependency.RiskAnalysisMultiAnswerSeed(key = seed.key, values = seed.values)
def toTemplate: Map[String, Seq[String]] = Map(seed.key -> seed.values)
}

implicit class EServiceDescriptorDocumentSeedWrapper(private val seed: UpdateEServiceDescriptorDocumentSeed)
extends AnyVal {
def toDependency: CatalogManagementDependency.UpdateEServiceDescriptorDocumentSeed =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,6 @@ object ProcessApiMarshallerImpl extends ProcessApiMarshaller with SprayJsonSuppo
override implicit def toEntityMarshallerEServiceConsumers: ToEntityMarshaller[EServiceConsumers] =
sprayJsonMarshaller[EServiceConsumers]

override implicit def fromEntityUnmarshallerEServiceRiskAnalysisSeed
: FromEntityUnmarshaller[EServiceRiskAnalysisSeed] = sprayJsonUnmarshaller[EServiceRiskAnalysisSeed]
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ 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
import it.pagopa.interop.commons.riskanalysis.api.impl.RiskAnalysisValidation
import it.pagopa.interop.commons.riskanalysis.{model => Commons}

import java.util.UUID
import scala.concurrent.{ExecutionContext, Future}
Expand All @@ -33,13 +35,15 @@ import it.pagopa.interop.catalogmanagement.model.{
Published,
Draft,
Suspended,
Deprecated
Deprecated,
Receive
}

final case class ProcessApiServiceImpl(
catalogManagementService: CatalogManagementService,
agreementManagementService: AgreementManagementService,
authorizationManagementService: AuthorizationManagementService,
tenantManagementService: TenantManagementService,
fileManager: FileManager
)(implicit ec: ExecutionContext, readModel: ReadModelService)
extends ProcessApiService {
Expand Down Expand Up @@ -648,6 +652,31 @@ final case class ProcessApiServiceImpl(
suspendDescriptorResponse[Unit](operationLabel)(_ => archiveDescriptor204)
}
}

override def createRiskAnalysis(eServiceId: String, seed: EServiceRiskAnalysisSeed)(implicit
contexts: Seq[(String, String)],
toEntityMarshallerProblem: ToEntityMarshaller[Problem]
): Route = authorize(ADMIN_ROLE, API_ROLE) {
val operationLabel = s"Create Risk Analysis for EService $eServiceId"
logger.info(operationLabel)

val result = for {
organizationId <- getOrganizationIdFutureUUID(contexts)
eServiceUuid <- eServiceId.toFutureUUID
catalogItem <- catalogManagementService.getEServiceById(eServiceUuid)
_ <- isDraftEService(catalogItem)
_ <- isReceiveEService(catalogItem)
_ <- assertRequesterAllowed(catalogItem.producerId)(organizationId)
tenant <- tenantManagementService.getTenantById(organizationId)
tenantKind <- tenant.kind.toFuture(TenantKindNotFound(tenant.id))
_ <- isRiskAnalysisFormValid(seed.riskAnalysisForm.toTemplate, schemaOnlyValidation = true)(tenantKind.toTemplate)
_ <- catalogManagementService.createRiskAnalysis(eServiceUuid, seed.toDependency)
} yield ()

onComplete(result) {
createRiskAnalysisResponse[Unit](operationLabel)(_ => createRiskAnalysis204)
}
}
}

object ProcessApiServiceImpl {
Expand All @@ -662,6 +691,25 @@ object ProcessApiServiceImpl {
case _ => Future.failed(NotValidDescriptor(descriptor.id.toString, descriptor.state.toString))
}

def isRiskAnalysisFormValid(riskAnalysisForm: Commons.RiskAnalysisForm, schemaOnlyValidation: Boolean)(
kind: Commons.RiskAnalysisTenantKind
): Future[Unit] =
if (
RiskAnalysisValidation
.validate(riskAnalysisForm, schemaOnlyValidation)(kind)
.isValid
) Future.unit
else Future.failed(RiskAnalysisNotValid)

def isReceiveEService(eService: CatalogItem): Future[Unit] =
if (eService.mode == Receive) Future.unit else Future.failed(EServiceNotInReceiveMode(eService.id))

def isDraftEService(eService: CatalogItem): Future[Unit] =
if (eService.descriptors.map(_.state) == Seq(Draft)) Future.unit
else
Future
.failed(EServiceNotInDraftState(eService.id))

def assertRequesterAllowed(resourceId: UUID)(requesterId: UUID)(implicit ec: ExecutionContext): Future[Unit] =
Future.failed(GenericComponentErrors.OperationForbidden).unlessA(resourceId == requesterId)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,19 @@ object ResponseHandlers extends AkkaResponses {
case Failure(ex) => internalServerError(ex, logMessage)
}

def createRiskAnalysisResponse[T](logMessage: String)(
success: T => Route
)(result: Try[T])(implicit contexts: Seq[(String, String)], logger: LoggerTakingImplicit[ContextFieldsToLog]): Route =
result match {
case Success(s) => success(s)
case Failure(ex: OperationForbidden.type) => forbidden(ex, logMessage)
case Failure(ex: EServiceNotFound) => notFound(ex, logMessage)
case Failure(ex: EServiceNotInDraftState) => badRequest(ex, logMessage)
case Failure(ex: EServiceNotInReceiveMode) => badRequest(ex, logMessage)
case Failure(ex: RiskAnalysisNotValid.type) => badRequest(ex, logMessage)
case Failure(ex) => internalServerError(ex, logMessage)
}

def updateEServiceByIdResponse[T](logMessage: String)(
success: T => Route
)(result: Try[T])(implicit contexts: Seq[(String, String)], logger: LoggerTakingImplicit[ContextFieldsToLog]): Route =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@ package object impl extends SprayJsonSupport with DefaultJsonProtocol {
implicit val createEServiceDescriptorDocumentSeedFormat: RootJsonFormat[CreateEServiceDescriptorDocumentSeed] =
jsonFormat8(CreateEServiceDescriptorDocumentSeed)

implicit val riskAnalysisMultiAnswerSeedFormat: RootJsonFormat[EServiceRiskAnalysisMultiAnswerSeed] = jsonFormat2(
EServiceRiskAnalysisMultiAnswerSeed
)
implicit val riskAnalysisSingleAnswerSeedFormat: RootJsonFormat[EServiceRiskAnalysisSingleAnswerSeed] = jsonFormat2(
EServiceRiskAnalysisSingleAnswerSeed
)
implicit val riskAnalysisFormSeedFormat: RootJsonFormat[EServiceRiskAnalysisFormSeed] = jsonFormat3(
EServiceRiskAnalysisFormSeed
)
implicit val riskAnalysisSeedFormat: RootJsonFormat[EServiceRiskAnalysisSeed] = jsonFormat2(EServiceRiskAnalysisSeed)

implicit val flatAgreementFormat: RootJsonFormat[FlatAgreement] = jsonFormat2(FlatAgreement)
implicit val flatAttributeFormat: RootJsonFormat[FlatAttribute] = jsonFormat1(FlatAttribute)
implicit val flatAttributesFormat: RootJsonFormat[FlatAttributes] = jsonFormat1(FlatAttributes)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package it.pagopa.interop.catalogprocess.common.readmodel

import it.pagopa.interop.commons.cqrs.service.ReadModelService
import it.pagopa.interop.tenantmanagement.model.persistence.JsonFormats._
import it.pagopa.interop.tenantmanagement.model.tenant.PersistentTenant
import org.mongodb.scala.model.Filters

import java.util.UUID
import scala.concurrent.{ExecutionContext, Future}

object ReadModelTenantQueries extends ReadModelQuery {
def getTenantById(
tenantId: UUID
)(implicit ec: ExecutionContext, readModel: ReadModelService): Future[Option[PersistentTenant]] =
readModel.findOne[PersistentTenant]("tenants", Filters.eq("data.id", tenantId.toString))
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package it.pagopa.interop.catalogprocess.errors

import it.pagopa.interop.commons.utils.errors.ComponentError
import java.util.UUID

object CatalogProcessErrors {

Expand Down Expand Up @@ -46,4 +47,17 @@ object CatalogProcessErrors {
final case class OriginIsNotCompliant(origin: String)
extends ComponentError("0011", s"Requester has not origin: $origin")

final case class EServiceNotInDraftState(eServiceId: UUID)
extends ComponentError("0012", s"EService $eServiceId is not draft")

final case class EServiceNotInReceiveMode(eServiceId: UUID)
extends ComponentError("0013", s"EService $eServiceId is not in receive mode")

final case class TenantNotFound(tenantId: UUID)
extends ComponentError("0014", s"Tenant ${tenantId.toString} not found")

final case class TenantKindNotFound(tenantId: UUID)
extends ComponentError("0015", s"Tenant kind for tenant ${tenantId.toString} not found")

final case object RiskAnalysisNotValid extends ComponentError("0016", s"Risk Analysis did not pass validation")
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ trait Dependencies {
catalogManagementService = catalogManagementService(blockingEc),
AgreementManagementServiceImpl,
authorizationManagementService = authorizationManagementService(blockingEc),
fileManager = fileManager
fileManager = fileManager,
tenantManagementService = TenantManagementServiceImpl
),
ProcessApiMarshallerImpl,
jwtReader.OAuth2JWTValidatorAsContexts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,8 @@ trait CatalogManagementService {
limit: Int,
exactMatchOnName: Boolean = false
)(implicit ec: ExecutionContext, readModel: ReadModelService): Future[PaginatedResult[CatalogItem]]

def createRiskAnalysis(eServiceId: UUID, riskAnalysisSeed: RiskAnalysisSeed)(implicit
contexts: Seq[(String, String)]
): Future[Unit]
}
Loading
Loading