Skip to content

Commit

Permalink
PIN-4658 BKE - purpose process - Add route reject purpose
Browse files Browse the repository at this point in the history
  • Loading branch information
nttdata-rtorsoli committed Mar 9, 2024
1 parent f0b43f1 commit b26a697
Show file tree
Hide file tree
Showing 15 changed files with 292 additions and 22 deletions.
2 changes: 1 addition & 1 deletion project/Versions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ object Versions {
object PagopaVersions {
lazy val agreementManagementVersion = "1.0.x-SNAPSHOT"
lazy val authorizationManagementVersion = "1.0.x-SNAPSHOT"
lazy val purposeManagementVersion = "1.0.x-SNAPSHOT"
lazy val purposeManagementVersion = "PIN-4657-SNAPSHOT"//"1.0.x-SNAPSHOT"
lazy val catalogManagementVersion = "1.0.x-SNAPSHOT"
lazy val tenantManagementVersion = "1.0.x-SNAPSHOT"
lazy val commonsVersion = "1.0.x-SNAPSHOT"
Expand Down
59 changes: 59 additions & 0 deletions src/main/resources/interface-specification.yml
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,54 @@ paths:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
/purposes/{purposeId}/versions/{versionId}/reject:
parameters:
- $ref: '#/components/parameters/CorrelationIdHeader'
- name: purposeId
in: path
required: true
schema:
type: string
format: uuid
- name: versionId
in: path
required: true
schema:
type: string
format: uuid
post:
summary: Rejected Purpose Version
operationId: rejectPurposeVersion
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/RejectPurposeVersionPayload'
required: true
responses:
'204':
description: Purpose Version Rejected
'400':
description: Bad Request
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'403':
description: Forbidden
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'404':
description: Purpose not found
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
description: reject the purpose version by id
tags:
- purpose
/purposes/{purposeId}/versions/{versionId}/activate:
parameters:
- $ref: '#/components/parameters/CorrelationIdHeader'
Expand Down Expand Up @@ -741,6 +789,14 @@ components:
schema:
type: string
schemas:
RejectPurposeVersionPayload:
type: object
description: models the reject payload for this purpose version.
properties:
rejectionReason:
type: string
required:
- rejectionReason
TenantKind:
type: string
description: Tenant Kind
Expand Down Expand Up @@ -1104,6 +1160,8 @@ components:
minimum: 0
riskAnalysis:
$ref: '#/components/schemas/PurposeVersionDocument'
rejectionReason:
type: string
required:
- id
- state
Expand All @@ -1119,6 +1177,7 @@ components:
- SUSPENDED
- WAITING_FOR_APPROVAL
- ARCHIVED
- REJECTED
PurposeVersionDocument:
type: object
required:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,8 @@ object Adapters {
expectedApprovalDate = version.expectedApprovalDate,
riskAnalysis = version.riskAnalysis.map(_.toPersistent),
dailyCalls = version.dailyCalls,
suspendedAt = version.suspendedAt
suspendedAt = version.suspendedAt,
rejectionReason = version.rejectionReason
)
}

Expand All @@ -433,6 +434,7 @@ object Adapters {
case PurposeVersionState.ACTIVE => Persistent.Active
case PurposeVersionState.DRAFT => Persistent.Draft
case PurposeVersionState.SUSPENDED => Persistent.Suspended
case PurposeVersionState.REJECTED => Persistent.Rejected
case PurposeVersionState.WAITING_FOR_APPROVAL => Persistent.WaitingForApproval
case PurposeVersionState.ARCHIVED => Persistent.Archived
}
Expand All @@ -445,6 +447,7 @@ object Adapters {
case Management.PurposeVersionState.ACTIVE => PurposeVersionState.ACTIVE
case Management.PurposeVersionState.DRAFT => PurposeVersionState.DRAFT
case Management.PurposeVersionState.SUSPENDED => PurposeVersionState.SUSPENDED
case Management.PurposeVersionState.REJECTED => PurposeVersionState.REJECTED
case Management.PurposeVersionState.WAITING_FOR_APPROVAL => PurposeVersionState.WAITING_FOR_APPROVAL
case Management.PurposeVersionState.ARCHIVED => PurposeVersionState.ARCHIVED
}
Expand All @@ -454,6 +457,7 @@ object Adapters {
case Management.PurposeVersionState.ACTIVE => Persistent.Active
case Management.PurposeVersionState.DRAFT => Persistent.Draft
case Management.PurposeVersionState.SUSPENDED => Persistent.Suspended
case Management.PurposeVersionState.REJECTED => Persistent.Rejected
case Management.PurposeVersionState.WAITING_FOR_APPROVAL => Persistent.WaitingForApproval
case Management.PurposeVersionState.ARCHIVED => Persistent.Archived
}
Expand All @@ -466,6 +470,7 @@ object Adapters {
case Persistent.Active => PurposeVersionState.ACTIVE
case Persistent.Draft => PurposeVersionState.DRAFT
case Persistent.Suspended => PurposeVersionState.SUSPENDED
case Persistent.Rejected => PurposeVersionState.REJECTED
case Persistent.WaitingForApproval => PurposeVersionState.WAITING_FOR_APPROVAL
case Persistent.Archived => PurposeVersionState.ARCHIVED
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,7 @@ object PurposeApiMarshallerImpl extends PurposeApiMarshaller with SprayJsonSuppo

override implicit def fromEntityUnmarshallerPurposeCloneSeed: FromEntityUnmarshaller[PurposeCloneSeed] =
sprayJsonUnmarshaller[PurposeCloneSeed]

override implicit def fromEntityUnmarshallerRejectPurposeVersionPayload
: FromEntityUnmarshaller[RejectPurposeVersionPayload] = sprayJsonUnmarshaller[RejectPurposeVersionPayload]
}
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,42 @@ final case class PurposeApiServiceImpl(
onComplete(result) { suspendPurposeVersionResponse[PurposeVersion](operationLabel)(suspendPurposeVersion200) }
}

override def rejectPurposeVersion(purposeId: String, versionId: String, payload: RejectPurposeVersionPayload)(implicit
contexts: Seq[(String, String)],
toEntityMarshallerProblem: ToEntityMarshaller[Problem]
): Route =
authorize(ADMIN_ROLE) {
val operationLabel = s"Rejecting Version $versionId of Purpose $purposeId"
logger.info(operationLabel)

val result: Future[Unit] = for {
purposeUUID <- purposeId.toFutureUUID
versionUUID <- versionId.toFutureUUID
organizationId <- getOrganizationIdFutureUUID(contexts)
purpose <- purposeManagementService.getPurposeById(purposeUUID)
_ <- assertOrganizationIsAProducer(organizationId, purpose.eserviceId)
_ <- getVersion(purpose, versionUUID)
_ <- purposeManagementService.rejectPurposeVersion(
purposeUUID,
versionUUID,
PurposeManagementDependency.RejectPurposeVersionPayload(
rejectionReason = payload.rejectionReason,
stateChangeDetails = PurposeManagementDependency.StateChangeDetails(
PurposeManagementDependency.ChangedBy.PRODUCER,
dateTimeSupplier.get()
)
)
)
_ <- authorizationManagementService.updateStateOnClients(
purposeId = purposeUUID,
versionId = versionUUID,
state = AuthorizationManagementDependency.ClientComponentState.INACTIVE
)
} yield ()

onComplete(result) { rejectPurposeVersionResponse[Unit](operationLabel)(_ => rejectPurposeVersion204) }
}

override def archivePurposeVersion(purposeId: String, versionId: String)(implicit
contexts: Seq[(String, String)],
toEntityMarshallerPurposeVersion: ToEntityMarshaller[PurposeVersion],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,17 @@ object ResponseHandlers extends AkkaResponses {
case Failure(ex) => internalServerError(ex, logMessage)
}

def rejectPurposeVersionResponse[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: OrganizationIsNotTheProducer) => forbidden(ex, logMessage)
case Failure(ex: PurposeNotFound) => notFound(ex, logMessage)
case Failure(ex: PurposeVersionNotFound) => notFound(ex, logMessage)
case Failure(ex) => internalServerError(ex, logMessage)
}

def updateDraftPurposeVersionResponse[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 @@ -19,25 +19,27 @@ package object impl extends SprayJsonSupport with DefaultJsonProtocol {
implicit def purposeVersionDocumentFormat: RootJsonFormat[PurposeVersionDocument] =
jsonFormat4(PurposeVersionDocument)
implicit def purposeFormat: RootJsonFormat[Purpose] = jsonFormat14(Purpose)
implicit def purposeVersionFormat: RootJsonFormat[PurposeVersion] = jsonFormat9(PurposeVersion)
implicit def purposeVersionFormat: RootJsonFormat[PurposeVersion] = jsonFormat10(PurposeVersion)
implicit def purposesFormat: RootJsonFormat[Purposes] = jsonFormat2(Purposes)
implicit def purposeSeedFormat: RootJsonFormat[PurposeSeed] = jsonFormat8(PurposeSeed)
implicit def purposeUpdateContentFormat: RootJsonFormat[PurposeUpdateContent] = jsonFormat6(PurposeUpdateContent)
implicit def reversePurposeUpdateContentFormat: RootJsonFormat[ReversePurposeUpdateContent] =
jsonFormat5(ReversePurposeUpdateContent)
implicit def purposeVersionSeedFormat: RootJsonFormat[PurposeVersionSeed] = jsonFormat1(PurposeVersionSeed)
implicit def problemErrorFormat: RootJsonFormat[ProblemError] = jsonFormat2(ProblemError)
implicit def problemFormat: RootJsonFormat[Problem] = jsonFormat6(Problem)
implicit def purposeVersionSeedFormat: RootJsonFormat[PurposeVersionSeed] = jsonFormat1(PurposeVersionSeed)
implicit def problemErrorFormat: RootJsonFormat[ProblemError] = jsonFormat2(ProblemError)
implicit def problemFormat: RootJsonFormat[Problem] = jsonFormat6(Problem)
implicit def waitingForApprovalPurposeVersionUpdateFormat
: RootJsonFormat[WaitingForApprovalPurposeVersionUpdateContent] =
jsonFormat1(WaitingForApprovalPurposeVersionUpdateContent)
implicit def dependencyResponseFormat: RootJsonFormat[DependencyResponse] =
implicit def rejectPurposeVersionPayloadFormat: RootJsonFormat[RejectPurposeVersionPayload] =
jsonFormat1(RejectPurposeVersionPayload)
implicit def dependencyResponseFormat: RootJsonFormat[DependencyResponse] =
jsonFormat2(DependencyResponse)
implicit def localizedTextResponseFormat: RootJsonFormat[LocalizedTextResponse] =
implicit def localizedTextResponseFormat: RootJsonFormat[LocalizedTextResponse] =
jsonFormat2(LocalizedTextResponse)
implicit def labeledValueResponseFormat: RootJsonFormat[LabeledValueResponse] =
implicit def labeledValueResponseFormat: RootJsonFormat[LabeledValueResponse] =
jsonFormat2(LabeledValueResponse)
implicit def hideOptionResponseFormat: RootJsonFormat[HideOptionResponse] =
implicit def hideOptionResponseFormat: RootJsonFormat[HideOptionResponse] =
jsonFormat2(HideOptionResponse)
implicit def validationOptionResponseFormat: RootJsonFormat[ValidationOptionResponse] =
jsonFormat1(ValidationOptionResponse)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ trait PurposeManagementService {
contexts: Seq[(String, String)]
): Future[PurposeVersion]

def rejectPurposeVersion(purposeId: UUID, versionId: UUID, payload: RejectPurposeVersionPayload)(implicit
contexts: Seq[(String, String)]
): Future[Unit]

def suspendPurposeVersion(purposeId: UUID, versionId: UUID, stateChangeDetails: StateChangeDetails)(implicit
contexts: Seq[(String, String)]
): Future[PurposeVersion]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,17 @@ final case class PurposeManagementServiceImpl(invoker: PurposeManagementInvoker,
)
}

def rejectPurposeVersion(purposeId: UUID, versionId: UUID, payload: RejectPurposeVersionPayload)(implicit
contexts: Seq[(String, String)]
): Future[Unit] = withHeaders { (bearerToken, correlationId) =>
val request =
api.rejectPurposeVersion(xCorrelationId = correlationId, purposeId, versionId, payload)(BearerToken(bearerToken))
invoker.invoke(
request,
s"Rejecting Version $versionId of Purpose $purposeId with reason ${payload.rejectionReason}"
)
}

override def suspendPurposeVersion(purposeId: UUID, versionId: UUID, stateChangeDetails: StateChangeDetails)(implicit
contexts: Seq[(String, String)]
): Future[PurposeVersion] = withHeaders { (bearerToken, correlationId) =>
Expand Down
7 changes: 7 additions & 0 deletions src/test/resources/authz.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@
],
"route": "activatePurposeVersion"
},
{
"verb": "POST",
"roles": [
"admin"
],
"route": "rejectPurposeVersion"
},
{
"verb": "POST",
"roles": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ class PurposeApiServiceSpec extends AnyWordSpecLike with SpecHelper with Scalate
firstActivationAt = None,
suspendedAt = None,
expectedApprovalDate = None,
riskAnalysis = None
riskAnalysis = None,
rejectionReason = None
)
),
suspendedByConsumer = None,
Expand Down Expand Up @@ -141,7 +142,8 @@ class PurposeApiServiceSpec extends AnyWordSpecLike with SpecHelper with Scalate
expectedApprovalDate = None,
dailyCalls = 100,
riskAnalysis = None,
suspendedAt = None
suspendedAt = None,
rejectionReason = None
),
PersistentPurposeVersion(
id = UUID.randomUUID(),
Expand All @@ -152,7 +154,8 @@ class PurposeApiServiceSpec extends AnyWordSpecLike with SpecHelper with Scalate
expectedApprovalDate = None,
dailyCalls = 50,
riskAnalysis = None,
suspendedAt = None
suspendedAt = None,
rejectionReason = None
)
),
suspendedByConsumer = None,
Expand Down Expand Up @@ -245,7 +248,8 @@ class PurposeApiServiceSpec extends AnyWordSpecLike with SpecHelper with Scalate
expectedApprovalDate = None,
dailyCalls = 50,
riskAnalysis = None,
suspendedAt = None
suspendedAt = None,
rejectionReason = None
),
PersistentPurposeVersion(
id = UUID.randomUUID(),
Expand All @@ -256,7 +260,8 @@ class PurposeApiServiceSpec extends AnyWordSpecLike with SpecHelper with Scalate
expectedApprovalDate = None,
dailyCalls = 100,
riskAnalysis = None,
suspendedAt = None
suspendedAt = None,
rejectionReason = None
)
),
suspendedByConsumer = None,
Expand Down Expand Up @@ -349,7 +354,8 @@ class PurposeApiServiceSpec extends AnyWordSpecLike with SpecHelper with Scalate
expectedApprovalDate = None,
dailyCalls = 500,
riskAnalysis = None,
suspendedAt = None
suspendedAt = None,
rejectionReason = None
)
),
suspendedByConsumer = None,
Expand Down Expand Up @@ -507,7 +513,8 @@ class PurposeApiServiceSpec extends AnyWordSpecLike with SpecHelper with Scalate
expectedApprovalDate = None,
dailyCalls = 1000,
riskAnalysis = None,
suspendedAt = None
suspendedAt = None,
rejectionReason = None
)
),
suspendedByConsumer = None,
Expand Down Expand Up @@ -2192,7 +2199,8 @@ class PurposeApiServiceSpec extends AnyWordSpecLike with SpecHelper with Scalate
dailyCalls = 2000,
riskAnalysis = Some(document),
firstActivationAt = Some(SpecData.timestamp),
suspendedAt = None
suspendedAt = None,
rejectionReason = None
)

mockPurposeRetrieve(purposeId, purpose)
Expand Down Expand Up @@ -2286,7 +2294,8 @@ class PurposeApiServiceSpec extends AnyWordSpecLike with SpecHelper with Scalate
dailyCalls = 2000,
riskAnalysis = None,
firstActivationAt = Some(SpecData.timestamp),
suspendedAt = None
suspendedAt = None,
rejectionReason = None
)

mockPurposeRetrieve(purposeId, purpose)
Expand Down
Loading

0 comments on commit b26a697

Please sign in to comment.