Skip to content

Commit

Permalink
Patch properly distribution including rev or tag (#5064)
Browse files Browse the repository at this point in the history
Co-authored-by: Simon Dumas <[email protected]>
  • Loading branch information
imsdu and Simon Dumas authored Jul 11, 2024
1 parent 767cc38 commit c233bab
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.model.{Digest, FileAt
import ch.epfl.bluebrain.nexus.delta.plugins.storage.storages.defaultS3StorageId
import ch.epfl.bluebrain.nexus.delta.rdf.utils.UriUtils
import ch.epfl.bluebrain.nexus.delta.sdk.model.{BaseUri, ResourceUris}
import ch.epfl.bluebrain.nexus.delta.sourcing.model.ResourceRef.{Latest, Revision, Tag}
import ch.epfl.bluebrain.nexus.delta.sourcing.model.{ProjectRef, ResourceRef}
import ch.epfl.bluebrain.nexus.ship.{IriPatcher, ProjectMapper}
import ch.epfl.bluebrain.nexus.ship.resources.DistributionPatcher._
Expand Down Expand Up @@ -47,8 +48,7 @@ final class DistributionPatcher(
private def modificationsForFile(originalProject: ProjectRef, resourceRef: ResourceRef): IO[Json => Json] = {
val targetProject = projectMapper.map(originalProject)
val patchedResourceRef = iriPatcher(resourceRef)
val newContentUrl =
ResourceUris("files", targetProject, patchedResourceRef.original).accessUri(targetBase).toString()
val newContentUrl = createContentUrl(targetProject, patchedResourceRef)
val fileAttributeModifications: IO[Json => Json] =
fetchFileAttributes(targetProject, patchedResourceRef).attempt.flatMap {
case Right(attributes) =>
Expand All @@ -63,11 +63,19 @@ final class DistributionPatcher(
IO.pure(identity)
}

fileAttributeModifications.map(_.andThen(setContentUrl(newContentUrl)))
fileAttributeModifications.map(_.andThen(setContentUrl(newContentUrl.toString())))
}

private[resources] def single(json: Json): IO[Json] = {
private def createContentUrl(project: ProjectRef, resourceRef: ResourceRef): Uri = {
val withoutVersioning = ResourceUris("files", project, resourceRef.iri).accessUri(targetBase)
resourceRef match {
case Latest(_) => withoutVersioning
case Revision(_, _, rev) => withoutVersioning.withQuery(Uri.Query("rev" -> rev.toString))
case Tag(_, _, tag) => withoutVersioning.withQuery(Uri.Query("tag" -> tag.toString))
}
}

private[resources] def single(json: Json): IO[Json] = {
for {
ids <- extractIds(json)
fileBasedModifications <- ids match {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ package ch.epfl.bluebrain.nexus.ship.resources

import akka.http.scaladsl.model.Uri
import cats.effect.IO
import ch.epfl.bluebrain.nexus.delta.kernel.utils.UrlUtils
import ch.epfl.bluebrain.nexus.delta.plugins.storage.FileSelf
import ch.epfl.bluebrain.nexus.delta.plugins.storage.FileSelf.ParsingError.InvalidFileId
import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.model.FileAttributes.FileAttributesOrigin
import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.model.FileRejection.FileNotFound
import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.model.{Digest, FileAttributes}
import ch.epfl.bluebrain.nexus.delta.plugins.storage.storages.model.DigestAlgorithm
import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode
import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri
import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.nxv
import ch.epfl.bluebrain.nexus.delta.sdk.model.{BaseUri, ResourceUris}
import ch.epfl.bluebrain.nexus.delta.sdk.projects.FetchContext
import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectContext}
import ch.epfl.bluebrain.nexus.delta.sdk.syntax._
import ch.epfl.bluebrain.nexus.delta.sourcing.model.{Label, ProjectRef, ResourceRef}
import ch.epfl.bluebrain.nexus.delta.sourcing.model.{Identity, Label, ProjectRef, ResourceRef}
import ch.epfl.bluebrain.nexus.ship.{IriPatcher, ProjectMapper}
import ch.epfl.bluebrain.nexus.testkit.mu.NexusSuite
import io.circe.{Json, JsonObject}
Expand Down Expand Up @@ -44,26 +44,22 @@ class DistributionPatcherSuite extends NexusSuite {
private def destinationFileSelf(project: ProjectRef, id: Iri) =
ResourceUris("files", project, id).accessUri(destinationBaseUri)

private val fileSelf = new FileSelf {
override def parse(input: IriOrBNode.Iri): IO[(ProjectRef, ResourceRef)] = {
val path = if (input.startsWith(sourceBaseUri.iriEndpoint)) {
IO.pure(input.stripPrefix(sourceBaseUri.iriEndpoint))
} else if (input.startsWith(destinationBaseUri.iriEndpoint)) {
IO.pure(input.stripPrefix(destinationBaseUri.iriEndpoint))
} else {
IO.raiseError(InvalidFileId(input))
}
path
.map(_.split("/").filter(_.nonEmpty).toList)
.flatMap {
case "files" :: org :: project :: id :: Nil =>
IO.pure(ProjectRef.unsafe(org, project) -> ResourceRef.Latest(Iri.unsafe(UrlUtils.decode(id))))
case _ =>
IO.raiseError(InvalidFileId(input))
}
}
private val projectContext = ProjectContext.unsafe(ApiMappings.empty, nxv.base, nxv.base, enforceSchema = false)

private val fetchContext = new FetchContext {
override def defaultApiMappings: ApiMappings = ApiMappings.empty

override def onRead(ref: ProjectRef): IO[ProjectContext] = IO.pure(projectContext)

override def onCreate(ref: ProjectRef)(implicit subject: Identity.Subject): IO[ProjectContext] =
IO.pure(projectContext)

override def onModify(ref: ProjectRef)(implicit subject: Identity.Subject): IO[ProjectContext] =
IO.pure(projectContext)
}

private val fileSelf = FileSelf(fetchContext)(sourceBaseUri)

private def fileResolver(project: ProjectRef, resourceRef: ResourceRef) = (project, resourceRef) match {
case (`mappedProject`, ResourceRef.Latest(`patchedResource1`)) =>
val digest = Digest.ComputedDigest(
Expand Down Expand Up @@ -146,6 +142,24 @@ class DistributionPatcherSuite extends NexusSuite {
patcher.patchAll(input).map(distributionContentUrl).assertEquals(expectedContentUri)
}

test("Patch a valid file self with a rev on a distribution") {
val input = json"""{ "distribution": { "contentUrl": "${sourceFileSelf(projectNoMapping, resource1)}?rev=2" } }"""
val expected =
json"""{ "distribution": { "contentUrl": "${destinationFileSelf(projectNoMapping, patchedResource1)}?rev=2" } }"""
patcher.patchAll(input).assertEquals(expected)
}

test("Patch a valid file self with a tag on a distribution") {
val input =
json"""{ "distribution": { "contentUrl": "${sourceFileSelf(projectNoMapping, resource1)}?tag=v1.0" } }"""
val expected =
json"""{ "distribution": { "contentUrl": "${destinationFileSelf(
projectNoMapping,
patchedResource1
)}?tag=v1.0" } }"""
patcher.patchAll(input).assertEquals(expected)
}

test("Patch an invalid distribution self should preserve the initial value") {
val input = json"""{ "distribution":"xxx" }"""
patcher.patchAll(input).assertEquals(input)
Expand Down

0 comments on commit c233bab

Please sign in to comment.