diff --git a/ship/src/main/scala/ch/epfl/bluebrain/nexus/ship/config/FileProcessingConfig.scala b/ship/src/main/scala/ch/epfl/bluebrain/nexus/ship/config/FileProcessingConfig.scala index 392df12816..958f025b9d 100644 --- a/ship/src/main/scala/ch/epfl/bluebrain/nexus/ship/config/FileProcessingConfig.scala +++ b/ship/src/main/scala/ch/epfl/bluebrain/nexus/ship/config/FileProcessingConfig.scala @@ -11,7 +11,7 @@ final case class FileProcessingConfig( importBucket: String, targetBucket: String, prefix: Option[Path], - locationPrefixToStripOpt: Option[Uri], + locationPrefixToStrip: Option[Uri], skipFileEvents: Boolean, mediaTypeDetector: MediaTypeDetectorConfig ) diff --git a/ship/src/main/scala/ch/epfl/bluebrain/nexus/ship/resources/DistributionPatcher.scala b/ship/src/main/scala/ch/epfl/bluebrain/nexus/ship/resources/DistributionPatcher.scala index 420cacebd3..1d2c6f0d6a 100644 --- a/ship/src/main/scala/ch/epfl/bluebrain/nexus/ship/resources/DistributionPatcher.scala +++ b/ship/src/main/scala/ch/epfl/bluebrain/nexus/ship/resources/DistributionPatcher.scala @@ -69,10 +69,29 @@ final class DistributionPatcher( } private def stripLocationOnUnknownFile(json: Json): Json = { + + def strip(original: String, locationPrefixToStrip: String) = original.replaceFirst(locationPrefixToStrip, "file://") + locationPrefixToStripOpt.fold(json) { locationPrefixToStrip => - root.atLocation.location.string.modify { location => - location.replaceFirst(locationPrefixToStrip.toString, "file://") - }(json) + val locationPrefixToStripString = locationPrefixToStrip.toString + val matchingContentUrl = root.contentUrl.string.getOption(json).filter(_.startsWith(locationPrefixToStripString)) + + matchingContentUrl match { + case Some(value) => + // If there is a contentUrl matching the prefix it had the priority, we strip the path and apply it to contentUrl, location and url + val patchedValue = strip(value, locationPrefixToStripString) + setContentUrl(patchedValue).andThen(setLocation(patchedValue)).andThen(setUrl(patchedValue))(json) + case None => + // We fallback to a location matching the prefix, we patch the location and the url + val matchedLocation = + root.atLocation.location.string.getOption(json).filter(_.startsWith(locationPrefixToStripString)) + matchedLocation match { + case Some(value) => + val patchedValue = strip(value, locationPrefixToStripString) + setLocation(patchedValue).andThen(setUrl(patchedValue))(json) + case None => json + } + } } } @@ -95,6 +114,7 @@ final class DistributionPatcher( private def setContentUrl(newContentUrl: String) = root.contentUrl.string.replace(newContentUrl) private def setLocation(newLocation: String) = (json: Json) => json.deepMerge(Json.obj("atLocation" := Json.obj("location" := newLocation))) + private def setUrl(newUrl: String) = (json: Json) => json.deepMerge(Json.obj("url" := newUrl)) private def setContentSize(newSize: Long) = (json: Json) => json.deepMerge(Json.obj("contentSize" := Json.obj("unitCode" := "bytes", "value" := newSize))) private def setEncodingFormat(contentType: Option[ContentType]) = (json: Json) => diff --git a/ship/src/main/scala/ch/epfl/bluebrain/nexus/ship/resources/SourcePatcher.scala b/ship/src/main/scala/ch/epfl/bluebrain/nexus/ship/resources/SourcePatcher.scala index b90ea2f46a..5d40cab3c5 100644 --- a/ship/src/main/scala/ch/epfl/bluebrain/nexus/ship/resources/SourcePatcher.scala +++ b/ship/src/main/scala/ch/epfl/bluebrain/nexus/ship/resources/SourcePatcher.scala @@ -64,7 +64,7 @@ object SourcePatcher { projectMapper, iriPatcher, targetBase, - config.files.locationPrefixToStripOpt, + config.files.locationPrefixToStrip, fetchFileAttributes ) new SourcePatcher(distributionPatcher, iriPatcher) diff --git a/ship/src/test/scala/ch/epfl/bluebrain/nexus/ship/resources/DistributionPatcherSuite.scala b/ship/src/test/scala/ch/epfl/bluebrain/nexus/ship/resources/DistributionPatcherSuite.scala index 28868bc983..ce79193f26 100644 --- a/ship/src/test/scala/ch/epfl/bluebrain/nexus/ship/resources/DistributionPatcherSuite.scala +++ b/ship/src/test/scala/ch/epfl/bluebrain/nexus/ship/resources/DistributionPatcherSuite.scala @@ -260,7 +260,7 @@ class DistributionPatcherSuite extends NexusSuite { .map(distrubutionDigest) .assertEquals(jobj"""{ "algorithm": "SHA-256", - "value": "${digest}" + "value": "$digest" }""") } @@ -279,20 +279,72 @@ class DistributionPatcherSuite extends NexusSuite { patcher.patchAll(input).assertEquals(expected) } - test("Patch and strip the distribution location when it matches the given prefix") { + test("Patch and strip the distribution contentUrl when it matches the prefix and set the value to location and url") { val input = json"""{ "distribution": { + "contentUrl": "file:///location_to_strip/project/a/b/c/d/file.txt" + } + }""" + + val expected = json"""{ + "distribution": { + "atLocation": { + "location": "file:///project/a/b/c/d/file.txt" + }, + "contentUrl": "file:///project/a/b/c/d/file.txt", + "url": "file:///project/a/b/c/d/file.txt" + } + }""" + + patcher.patchAll(input).assertEquals(expected) + } + + test("Do not patch the distribution contentUrl when it does not match the prefix") { + val input = + json"""{ + "distribution": { + "contentUrl": "file:///some/other/location/project/a/b/c/d/file.txt" + } + }""" + + patcher.patchAll(input).assertEquals(input) + } + + test("Patch and strip the distribution location when it matches the prefix, setting the url to the same value") { + val input = + json"""{ + "distribution": { + "url": "XXX", "atLocation": { "location": "file:///location_to_strip/project/a/b/c/d/file.txt" } } }""" - patcher - .patchAll(input) - .map(distributionLocation) - .assertEquals("file:///project/a/b/c/d/file.txt") + val expected = json"""{ + "distribution": { + "url": "file:///project/a/b/c/d/file.txt", + "atLocation": { + "location": "file:///project/a/b/c/d/file.txt" + } + } + }""" + + patcher.patchAll(input).assertEquals(expected) + } + + test("Do not patch the location or the url if the distribution location when it does not match the prefix") { + val input = + json"""{ + "distribution": { + "atLocation": { + "location": "file:///some/other/location/project/a/b/c/d/file.txt" + } + } + }""" + + patcher.patchAll(input).assertEquals(input) } private def distributionContentSize(json: Json): JsonObject = {