From a14152a2e5fae3322049915ba827df0d856b078b Mon Sep 17 00:00:00 2001 From: Oliver <20188437+olivergrabinski@users.noreply.github.com> Date: Wed, 3 Apr 2024 17:43:27 +0200 Subject: [PATCH] Make `ValidatePriority` a trait (#4832) --- .../nexus/delta/wiring/ResolversModule.scala | 1 + .../delta/routes/ResolversRoutesSpec.scala | 3 ++ .../nexus/delta/sdk/resolvers/Resolvers.scala | 4 +- .../delta/sdk/resolvers/ResolversImpl.scala | 22 ++--------- .../sdk/resolvers/ValidatePriority.scala | 37 +++++++++++++++++++ .../resolvers/ResolversEvaluateSuite.scala | 2 +- .../sdk/resolvers/ResolversImplSpec.scala | 3 ++ .../nexus/ship/resolvers/ResolverWiring.scala | 6 ++- 8 files changed, 54 insertions(+), 24 deletions(-) create mode 100644 delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/ValidatePriority.scala diff --git a/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/wiring/ResolversModule.scala b/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/wiring/ResolversModule.scala index 8c186bccbd..d0401089e5 100644 --- a/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/wiring/ResolversModule.scala +++ b/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/wiring/ResolversModule.scala @@ -46,6 +46,7 @@ object ResolversModule extends ModuleDef { ResolversImpl( fetchContext, resolverContextResolution, + ValidatePriority.priorityAlreadyExists(xas), config.resolvers.eventLog, xas, clock diff --git a/delta/app/src/test/scala/ch/epfl/bluebrain/nexus/delta/routes/ResolversRoutesSpec.scala b/delta/app/src/test/scala/ch/epfl/bluebrain/nexus/delta/routes/ResolversRoutesSpec.scala index 4df3ae03b9..f095722ab5 100644 --- a/delta/app/src/test/scala/ch/epfl/bluebrain/nexus/delta/routes/ResolversRoutesSpec.scala +++ b/delta/app/src/test/scala/ch/epfl/bluebrain/nexus/delta/routes/ResolversRoutesSpec.scala @@ -87,9 +87,12 @@ class ResolversRoutesSpec extends BaseRouteSpec { case _ => IO.none } + private lazy val validatePriority = ValidatePriority.priorityAlreadyExists(xas) + private lazy val resolvers = ResolversImpl( fetchContext, resolverContextResolution, + validatePriority, eventLogConfig, xas, clock diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/Resolvers.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/Resolvers.scala index 89fed1764e..a0e15997b4 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/Resolvers.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/Resolvers.scala @@ -168,8 +168,6 @@ trait Resolvers { object Resolvers { - type ValidatePriority = (ProjectRef, Iri, Priority) => IO[Unit] - /** * The resolver entity type. */ @@ -256,7 +254,7 @@ object Resolvers { IO.raiseWhen(missing.nonEmpty)(InvalidIdentities(missing)) } case _ => IO.unit - }) >> validatePriority(project, id, value.priority) + }) >> validatePriority.validate(project, id, value.priority) def create(c: CreateResolver): IO[ResolverCreated] = state match { // Create a resolver diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/ResolversImpl.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/ResolversImpl.scala index 033963d0c2..e1b80e3746 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/ResolversImpl.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/ResolversImpl.scala @@ -20,12 +20,11 @@ import ch.epfl.bluebrain.nexus.delta.sdk.projects.FetchContext import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.Resolvers.{entityType, expandIri} import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.ResolversImpl.ResolversLog import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.model.ResolverCommand.{CreateResolver, DeprecateResolver, UpdateResolver} -import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.model.ResolverRejection.{FetchByTagNotSupported, PriorityAlreadyExists, ResolverNotFound, RevisionNotFound} +import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.model.ResolverRejection.{FetchByTagNotSupported, ResolverNotFound, RevisionNotFound} import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.model._ import ch.epfl.bluebrain.nexus.delta.sourcing._ import ch.epfl.bluebrain.nexus.delta.sourcing.config.EventLogConfig import ch.epfl.bluebrain.nexus.delta.sourcing.model.{Identity, ProjectRef} -import doobie.implicits._ import io.circe.Json final class ResolversImpl private ( @@ -157,6 +156,7 @@ object ResolversImpl { def apply( fetchContext: FetchContext, contextResolution: ResolverContextResolution, + validatePriority: ValidatePriority, config: EventLogConfig, xas: Transactors, clock: Clock[IO] @@ -164,24 +164,8 @@ object ResolversImpl { api: JsonLdApi, uuidF: UUIDF ): Resolvers = { - def priorityAlreadyExists(ref: ProjectRef, self: Iri, priority: Priority): IO[Unit] = { - sql"""SELECT id FROM scoped_states - WHERE type = ${Resolvers.entityType} - AND org = ${ref.organization} AND project = ${ref.project} - AND id != $self - AND (value->'deprecated')::boolean = false - AND (value->'value'->'priority')::int = ${priority.value}""" - .query[Iri] - .option - .transact(xas.read) - .flatMap { - case Some(other) => IO.raiseError(PriorityAlreadyExists(ref, other, priority)) - case None => IO.unit - } - } - new ResolversImpl( - ScopedEventLog(Resolvers.definition(priorityAlreadyExists, clock), config, xas), + ScopedEventLog(Resolvers.definition(validatePriority, clock), config, xas), fetchContext, new JsonLdSourceResolvingDecoder[ResolverValue]( contexts.resolvers, diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/ValidatePriority.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/ValidatePriority.scala new file mode 100644 index 0000000000..74ad7444b7 --- /dev/null +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/ValidatePriority.scala @@ -0,0 +1,37 @@ +package ch.epfl.bluebrain.nexus.delta.sdk.resolvers + +import cats.effect.IO +import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri +import ch.epfl.bluebrain.nexus.delta.sdk.implicits._ +import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.model.Priority +import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.model.ResolverRejection.PriorityAlreadyExists +import ch.epfl.bluebrain.nexus.delta.sourcing.Transactors +import ch.epfl.bluebrain.nexus.delta.sourcing.model.ProjectRef +import doobie.implicits._ + +trait ValidatePriority { + + /** Validate that a resolver with the given self & priority can be created in the provided project */ + def validate(ref: ProjectRef, self: Iri, priority: Priority): IO[Unit] + +} + +object ValidatePriority { + + /** Provides a [[ValidatePriority]] instance that ensure there is no active resolver with the given priority */ + def priorityAlreadyExists(xas: Transactors): ValidatePriority = (ref: ProjectRef, self: Iri, priority: Priority) => + sql"""SELECT id FROM scoped_states + WHERE type = ${Resolvers.entityType} + AND org = ${ref.organization} AND project = ${ref.project} + AND id != $self + AND (value->'deprecated')::boolean = false + AND (value->'value'->'priority')::int = ${priority.value}""" + .query[Iri] + .option + .transact(xas.read) + .flatMap { + case Some(other) => IO.raiseError(PriorityAlreadyExists(ref, other, priority)) + case None => IO.unit + } + +} diff --git a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/ResolversEvaluateSuite.scala b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/ResolversEvaluateSuite.scala index 000dd39498..30c56579ca 100644 --- a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/ResolversEvaluateSuite.scala +++ b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/ResolversEvaluateSuite.scala @@ -3,7 +3,7 @@ package ch.epfl.bluebrain.nexus.delta.sdk.resolvers import cats.data.NonEmptyList import cats.effect.IO import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.nxv -import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.Resolvers.{evaluate, ValidatePriority} +import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.Resolvers.evaluate import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.model.IdentityResolution.{ProvidedIdentities, UseCurrentCaller} import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.model.Priority import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.model.ResolverCommand.{CreateResolver, DeprecateResolver, UpdateResolver} diff --git a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/ResolversImplSpec.scala b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/ResolversImplSpec.scala index 11af18e0e1..ec23e1d313 100644 --- a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/ResolversImplSpec.scala +++ b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/ResolversImplSpec.scala @@ -73,9 +73,12 @@ class ResolversImplSpec extends CatsEffectSpec with DoobieScalaTestFixture with Set(deprecatedProject.ref) ) + private lazy val validatePriority = ValidatePriority.priorityAlreadyExists(xas) + private lazy val resolvers: Resolvers = ResolversImpl( fetchContext, resolverContextResolution, + validatePriority, eventLogConfig, xas, clock diff --git a/ship/src/main/scala/ch/epfl/bluebrain/nexus/ship/resolvers/ResolverWiring.scala b/ship/src/main/scala/ch/epfl/bluebrain/nexus/ship/resolvers/ResolverWiring.scala index f04f9813eb..639f2d1ce3 100644 --- a/ship/src/main/scala/ch/epfl/bluebrain/nexus/ship/resolvers/ResolverWiring.scala +++ b/ship/src/main/scala/ch/epfl/bluebrain/nexus/ship/resolvers/ResolverWiring.scala @@ -5,7 +5,7 @@ import cats.effect.kernel.Clock import ch.epfl.bluebrain.nexus.delta.kernel.utils.UUIDF import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.api.JsonLdApi import ch.epfl.bluebrain.nexus.delta.sdk.projects.FetchContext -import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.{ResolverContextResolution, Resolvers, ResolversImpl} +import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.{ResolverContextResolution, Resolvers, ResolversImpl, ValidatePriority} import ch.epfl.bluebrain.nexus.delta.sourcing.Transactors import ch.epfl.bluebrain.nexus.delta.sourcing.config.EventLogConfig import ch.epfl.bluebrain.nexus.ship.FailingUUID @@ -16,10 +16,14 @@ object ResolverWiring { jsonLdApi: JsonLdApi ): Resolvers = { implicit val uuidF: UUIDF = FailingUUID + + val alwaysValidatePriority: ValidatePriority = (_, _, _) => IO.unit + ResolversImpl( fetchContext, // We rely on the parsed values and not on the original value ResolverContextResolution.never, + alwaysValidatePriority, config, xas, clock