Skip to content

Commit

Permalink
PIN-4332 - Update of daily calls with the same value of the previous …
Browse files Browse the repository at this point in the history
…version is not allowed (#196)
  • Loading branch information
nttdata-rtorsoli authored Jan 15, 2024
1 parent 3c15b99 commit f5c7d7f
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ final case class PurposeApiServiceImpl(
purposeUUID <- purposeId.toFutureUUID
purpose <- purposeManagementService.getPurposeById(purposeUUID)
_ <- assertOrganizationIsAConsumer(organizationId, purpose.consumerId)
_ <- assertDailyCallsIsDifferentThanBefore(purpose, seed.dailyCalls)
version <- purposeManagementService.createPurposeVersion(purposeUUID, seed.toManagement)
published <- publish(organizationId, purpose, version.toPersistent)
} yield published.toApi
Expand Down Expand Up @@ -734,6 +735,15 @@ final case class PurposeApiServiceImpl(
else Future.failed(PurposeNotInDraftState(purpose.id))
}

private def assertDailyCallsIsDifferentThanBefore(purpose: PersistentPurpose, dailyCalls: Int): Future[Unit] = {
val ordering: Ordering[OffsetDateTime] = Ordering(Ordering.by[OffsetDateTime, Long](_.toEpochSecond).reverse)
val previousDailyCalls = purpose.versions.sortBy(_.createdAt)(ordering).map(_.dailyCalls).headOption
previousDailyCalls match {
case Some(x) if x == dailyCalls => Future.failed(UnchangedDailyCalls(purpose.id))
case _ => Future.successful(())
}
}

private def isRiskAnalysisFormValid(
riskAnalysisForm: Option[RiskAnalysisForm],
schemaOnlyValidation: Boolean = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,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: UnchangedDailyCalls) => badRequest(ex, logMessage)
case Failure(ex: OrganizationIsNotTheConsumer) => forbidden(ex, logMessage)
case Failure(ex: PurposeNotFound) => notFound(ex, logMessage)
case Failure(ex: PurposeVersionConflict) => conflict(ex, logMessage)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,5 +91,6 @@ object PurposeProcessErrors {
extends ComponentError("0026", s"EService ${eServiceId.toString} has not Receive mode")
final case class RiskAnalysisNotFound(eServiceId: UUID, riskAnalysisId: UUID)
extends ComponentError("0027", s"EService $eServiceId does not contain Risk Analysis $riskAnalysisId")

final case class UnchangedDailyCalls(purposeId: UUID)
extends ComponentError("0028", s"Creation of new version without changing daily calls for purpose $purposeId")
}
Original file line number Diff line number Diff line change
Expand Up @@ -2156,19 +2156,20 @@ class PurposeApiServiceSpec extends AnyWordSpecLike with SpecHelper with Scalate
implicit val context: Seq[(String, String)] =
Seq("bearer" -> bearerToken, USER_ROLES -> "admin", ORGANIZATION_ID_CLAIM -> consumerId.toString)

val version2_1 = SpecData.purposeVersion.copy(id = UUID.randomUUID(), state = Active, dailyCalls = 1000)
val version2_1 = SpecData.purposeVersion.copy(id = UUID.randomUUID(), state = Active, dailyCalls = 1002)
val purpose2 = SpecData.purpose.copy(eserviceId = eserviceId, consumerId = consumerId, versions = Seq(version2_1))

val path: String = "/here/there/foo/bar.pdf"
val document: PersistentPurposeVersionDocument =
PersistentPurposeVersionDocument(documentId, "application/pdf", path, SpecData.timestamp)

val version1_1 = SpecData.purposeVersion.copy(id = purposeVersionId1, state = Active)
val version1_1 = SpecData.purposeVersion.copy(id = purposeVersionId1, state = Active, dailyCalls = 1000)
val version1_2 = SpecData.purposeVersion.copy(
id = purposeVersionId2,
state = WaitingForApproval,
riskAnalysis = Some(document),
firstActivationAt = Some(SpecData.timestamp)
firstActivationAt = Some(SpecData.timestamp),
dailyCalls = 1001
)

val purpose =
Expand All @@ -2180,15 +2181,15 @@ class PurposeApiServiceSpec extends AnyWordSpecLike with SpecHelper with Scalate
)

val purposes = Seq(purpose, purpose2)
val seed: PurposeVersionSeed = PurposeVersionSeed(dailyCalls = 1000)
val seed: PurposeVersionSeed = PurposeVersionSeed(dailyCalls = 2000)

val purposeVersion = PersistentPurposeVersion(
id = purposeVersionId3,
state = Active,
createdAt = SpecData.timestamp,
updatedAt = None,
expectedApprovalDate = None,
dailyCalls = seed.dailyCalls,
dailyCalls = 2000,
riskAnalysis = Some(document),
firstActivationAt = Some(SpecData.timestamp),
suspendedAt = None
Expand Down Expand Up @@ -2216,7 +2217,8 @@ class PurposeApiServiceSpec extends AnyWordSpecLike with SpecHelper with Scalate
riskAnalysis = Some(
PurposeManagementDependency.PurposeVersionDocument(documentId, "application/pdf", path, SpecData.timestamp)
),
firstActivationAt = Some(SpecData.timestamp)
firstActivationAt = Some(SpecData.timestamp),
dailyCalls = 2000
)

mockVersionFirstActivation(purposeId, purposeVersionId3, eService.producerId, purpose.consumerId, updatedVersion)
Expand Down Expand Up @@ -2248,7 +2250,7 @@ class PurposeApiServiceSpec extends AnyWordSpecLike with SpecHelper with Scalate
implicit val context: Seq[(String, String)] =
Seq("bearer" -> bearerToken, USER_ROLES -> "admin", ORGANIZATION_ID_CLAIM -> consumerId.toString)

val version2_1 = SpecData.purposeVersion.copy(id = UUID.randomUUID(), state = Active, dailyCalls = 1000)
val version2_1 = SpecData.purposeVersion.copy(id = UUID.randomUUID(), state = Active, dailyCalls = 1002)
val purpose2 = SpecData.purpose.copy(eserviceId = eserviceId, consumerId = consumerId, versions = Seq(version2_1))

val path: String = "/here/there/foo/bar.pdf"
Expand All @@ -2260,7 +2262,8 @@ class PurposeApiServiceSpec extends AnyWordSpecLike with SpecHelper with Scalate
id = purposeVersionId2,
state = WaitingForApproval,
riskAnalysis = Some(document),
firstActivationAt = Some(SpecData.timestamp)
firstActivationAt = Some(SpecData.timestamp),
dailyCalls = 1001
)

val purpose =
Expand All @@ -2272,15 +2275,15 @@ class PurposeApiServiceSpec extends AnyWordSpecLike with SpecHelper with Scalate
)

val purposes = Seq(purpose, purpose2)
val seed: PurposeVersionSeed = PurposeVersionSeed(dailyCalls = 1000)
val seed: PurposeVersionSeed = PurposeVersionSeed(dailyCalls = 2000)

val purposeVersion = PersistentPurposeVersion(
id = purposeVersionId3,
state = WaitingForApproval,
createdAt = SpecData.timestamp,
updatedAt = None,
expectedApprovalDate = None,
dailyCalls = seed.dailyCalls,
dailyCalls = 2000,
riskAnalysis = None,
firstActivationAt = Some(SpecData.timestamp),
suspendedAt = None
Expand All @@ -2306,7 +2309,8 @@ class PurposeApiServiceSpec extends AnyWordSpecLike with SpecHelper with Scalate
id = purposeVersionId3,
state = PurposeManagementDependency.PurposeVersionState.WAITING_FOR_APPROVAL,
riskAnalysis = None,
firstActivationAt = Some(SpecData.timestamp)
firstActivationAt = Some(SpecData.timestamp),
dailyCalls = 2000
)

val payload = PurposeManagementDependency.StateChangeDetails(
Expand All @@ -2325,7 +2329,51 @@ class PurposeApiServiceSpec extends AnyWordSpecLike with SpecHelper with Scalate
responseAs[PurposeVersion] shouldEqual expected
}
}
"fail in case of version with the same dailyCalls than previous version" in {

val consumerId = UUID.randomUUID()
val documentId = UUID.randomUUID()
val purposeId = UUID.randomUUID()
val purposeVersionId1 = UUID.randomUUID()
val purposeVersionId2 = UUID.randomUUID()
val eserviceId = UUID.randomUUID()

implicit val context: Seq[(String, String)] =
Seq("bearer" -> bearerToken, USER_ROLES -> "admin", ORGANIZATION_ID_CLAIM -> consumerId.toString)

val path: String = "/here/there/foo/bar.pdf"
val document: PersistentPurposeVersionDocument =
PersistentPurposeVersionDocument(documentId, "application/pdf", path, SpecData.timestamp)

val version1_1 = SpecData.purposeVersion.copy(id = purposeVersionId1, state = Draft, dailyCalls = 1000)
val version1_2 = SpecData.purposeVersion.copy(
id = purposeVersionId2,
state = WaitingForApproval,
riskAnalysis = Some(document),
firstActivationAt = None,
createdAt = SpecData.timestamp.plusDays(1),
dailyCalls = 1001
)

val purpose =
SpecData.purpose.copy(
id = purposeId,
versions = Seq(version1_1, version1_2),
consumerId = consumerId,
eserviceId = eserviceId
)

val seed: PurposeVersionSeed = PurposeVersionSeed(dailyCalls = 1001)

mockPurposeRetrieve(purposeId, purpose)

Get() ~> service.createPurposeVersion(purposeId.toString, seed) ~> check {
status shouldEqual StatusCodes.BadRequest
val problem = responseAs[Problem]
problem.status shouldBe StatusCodes.BadRequest.intValue
problem.errors.head.code shouldBe "012-0028"
}
}
"fail if Purpose does not exist" in {

val purposeId = UUID.randomUUID()
Expand Down

0 comments on commit f5c7d7f

Please sign in to comment.