From 9e1f38876ccd33ac60794066405cf237cb343e8d Mon Sep 17 00:00:00 2001 From: Tristan Burch Date: Thu, 7 Jul 2022 16:25:27 -0600 Subject: [PATCH 1/5] Make sure to check that the blob exists before updating or deleting it. Fixes #99. --- src/main/kotlin/jsonblob/api/http/ApiController.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/jsonblob/api/http/ApiController.kt b/src/main/kotlin/jsonblob/api/http/ApiController.kt index afd17e8..22e6f23 100644 --- a/src/main/kotlin/jsonblob/api/http/ApiController.kt +++ b/src/main/kotlin/jsonblob/api/http/ApiController.kt @@ -157,7 +157,7 @@ class ApiController( return false } - private fun delete(blobId: String) = jsonBlobStore.remove(blobId) + private fun delete(blobId: String) = jsonBlobStore.exists(blobId) && jsonBlobStore.remove(blobId) private fun updateFirstBlobFromPath(path: String, json: String): JsonBlob? { val ids = blobIdsFromPath(path) @@ -170,7 +170,7 @@ class ApiController( private fun update(blobId: String, json: String): JsonBlob? { val resolver = idResolvers.firstOrNull { it.handles(blobId) } - return if (resolver != null) { + return if (resolver != null && jsonBlobStore.exists(blobId)) { val created = resolver.resolveTimestamp(blobId) val jsonBlob = JsonBlob( id = blobId, From 6ebec9b3515a3ce3d4c0cc325dc29e64e8bcd32f Mon Sep 17 00:00:00 2001 From: Tristan Burch Date: Thu, 7 Jul 2022 16:26:53 -0600 Subject: [PATCH 2/5] bump version --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 3167bb1..3ff45d1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,7 +6,7 @@ plugins { id("io.micronaut.application") version "2.0.2" } -version = "1.0.1" +version = "1.0.2" group = "com.jsonblob" val kotlinVersion= project.properties["kotlinVersion"] From 94a2eef952a6d9a4be30c55a1c4ba14bcd9590bb Mon Sep 17 00:00:00 2001 From: Tristan Burch Date: Sat, 6 May 2023 10:45:22 -0600 Subject: [PATCH 3/5] Allow PUTs to create blobs as long as the id can be resolved --- .../kotlin/jsonblob/api/http/ApiController.kt | 2 +- .../kotlin/jsonblob/core/store/JsonBlobStore.kt | 2 +- .../core/store/file/FileSystemJsonBlobStore.kt | 2 +- src/test/kotlin/jsonblob/api/http/ApiTest.kt | 17 +++++++++++++++++ 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/jsonblob/api/http/ApiController.kt b/src/main/kotlin/jsonblob/api/http/ApiController.kt index 22e6f23..78ad55a 100644 --- a/src/main/kotlin/jsonblob/api/http/ApiController.kt +++ b/src/main/kotlin/jsonblob/api/http/ApiController.kt @@ -170,7 +170,7 @@ class ApiController( private fun update(blobId: String, json: String): JsonBlob? { val resolver = idResolvers.firstOrNull { it.handles(blobId) } - return if (resolver != null && jsonBlobStore.exists(blobId)) { + return if (resolver != null) { val created = resolver.resolveTimestamp(blobId) val jsonBlob = JsonBlob( id = blobId, diff --git a/src/main/kotlin/jsonblob/core/store/JsonBlobStore.kt b/src/main/kotlin/jsonblob/core/store/JsonBlobStore.kt index 13c7fe2..2f1573f 100644 --- a/src/main/kotlin/jsonblob/core/store/JsonBlobStore.kt +++ b/src/main/kotlin/jsonblob/core/store/JsonBlobStore.kt @@ -32,7 +32,7 @@ abstract class JsonBlobStore( created = created ) }.onFailure { - log.warn { "Couldn't read JsonBlob with id=$id " } + log.debug { "Couldn't read JsonBlob with id=$id " } }.getOrNull() } diff --git a/src/main/kotlin/jsonblob/core/store/file/FileSystemJsonBlobStore.kt b/src/main/kotlin/jsonblob/core/store/file/FileSystemJsonBlobStore.kt index e0a615d..5e80f6d 100644 --- a/src/main/kotlin/jsonblob/core/store/file/FileSystemJsonBlobStore.kt +++ b/src/main/kotlin/jsonblob/core/store/file/FileSystemJsonBlobStore.kt @@ -58,7 +58,7 @@ open class FileSystemJsonBlobStore( lock.unlock() } }.onFailure { - log.warn { "Couldn't retrieve JsonBlob with id=$id " } + log.debug { "Couldn't retrieve JsonBlob with id=$id " } }.getOrNull() } diff --git a/src/test/kotlin/jsonblob/api/http/ApiTest.kt b/src/test/kotlin/jsonblob/api/http/ApiTest.kt index ed8e173..31e20c3 100644 --- a/src/test/kotlin/jsonblob/api/http/ApiTest.kt +++ b/src/test/kotlin/jsonblob/api/http/ApiTest.kt @@ -25,6 +25,7 @@ import org.testcontainers.containers.localstack.LocalStackContainer import org.testcontainers.shaded.com.google.common.io.Files import org.testcontainers.utility.DockerImageName import software.amazon.awssdk.services.s3.S3Client +import java.util.UUID import javax.inject.Inject @@ -129,6 +130,22 @@ class ApiTest: TestPropertyProvider { } } + @Test + fun `blob is created on API PUT`() { + val resp = client + .toBlocking() + .exchange(PUT("/api/jsonBlob/${type1UUIDJsonBlobHandler.generate()}", json).contentType(MediaType.APPLICATION_JSON_TYPE), String::class.java) + assertThat(resp.code()).isEqualTo(200) + } + + @Test + fun `blob is not created on bad API PUT`() { + val resp = client + .toBlocking() + .exchange(PUT("/api/jsonBlob/${UUID.randomUUID()}", json).contentType(MediaType.APPLICATION_JSON_TYPE), String::class.java) + assertThat(resp.code()).isEqualTo(400) + } + @Test fun `blob is updated on custom API PUT`() { validateUpdate { From bb703c15b2056d09bd375221d1c2d4d8620ac4f5 Mon Sep 17 00:00:00 2001 From: Tristan Burch Date: Sat, 6 Apr 2024 10:37:01 -0600 Subject: [PATCH 4/5] switch to new GA --- src/main/resources/views/editor.hbs | 44 +---------------------------- src/main/resources/views/ga.hbs | 14 ++++----- 2 files changed, 8 insertions(+), 50 deletions(-) diff --git a/src/main/resources/views/editor.hbs b/src/main/resources/views/editor.hbs index dc0ea84..07a44a7 100644 --- a/src/main/resources/views/editor.hbs +++ b/src/main/resources/views/editor.hbs @@ -289,7 +289,6 @@ \ No newline at end of file From 17e49748e15ff420a77e234c71e64724919e98c5 Mon Sep 17 00:00:00 2001 From: tburch Date: Mon, 17 Feb 2025 10:47:33 -0700 Subject: [PATCH 5/5] Fixes #106 - validate that PUT requests contain valid JSON --- .../kotlin/jsonblob/api/http/ApiController.kt | 24 +++++++++++-------- src/test/kotlin/jsonblob/api/http/ApiTest.kt | 18 +++++++------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/main/kotlin/jsonblob/api/http/ApiController.kt b/src/main/kotlin/jsonblob/api/http/ApiController.kt index 78ad55a..d0586aa 100644 --- a/src/main/kotlin/jsonblob/api/http/ApiController.kt +++ b/src/main/kotlin/jsonblob/api/http/ApiController.kt @@ -169,17 +169,21 @@ class ApiController( } private fun update(blobId: String, json: String): JsonBlob? { - val resolver = idResolvers.firstOrNull { it.handles(blobId) } - return if (resolver != null) { - val created = resolver.resolveTimestamp(blobId) - val jsonBlob = JsonBlob( - id = blobId, - json = json, - created = created - ) - jsonBlobStore.write(jsonBlob) + if (JsonCleaner.validJson(json)) { + val resolver = idResolvers.firstOrNull { it.handles(blobId) } + return if (resolver != null) { + val created = resolver.resolveTimestamp(blobId) + val jsonBlob = JsonBlob( + id = blobId, + json = json, + created = created + ) + jsonBlobStore.write(jsonBlob) + } else { + null + } } else { - null + throw HttpStatusException(HttpStatus.BAD_REQUEST, "Invalid JSON") } } diff --git a/src/test/kotlin/jsonblob/api/http/ApiTest.kt b/src/test/kotlin/jsonblob/api/http/ApiTest.kt index 31e20c3..e5a0739 100644 --- a/src/test/kotlin/jsonblob/api/http/ApiTest.kt +++ b/src/test/kotlin/jsonblob/api/http/ApiTest.kt @@ -8,23 +8,19 @@ import io.micronaut.http.HttpResponse import io.micronaut.http.MediaType import io.micronaut.http.client.HttpClient import io.micronaut.http.client.annotation.Client +import io.micronaut.http.client.exceptions.HttpClientResponseException import io.micronaut.test.extensions.junit5.annotation.MicronautTest import io.micronaut.test.support.TestPropertyProvider -import jsonblob.config.S3ClientBuilderListener import jsonblob.core.compression.compressor.GZIPBlobCompressor import jsonblob.core.id.Type1UUIDJsonBlobHandler import jsonblob.core.store.JsonBlobStore import mu.KotlinLogging import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.AfterAll -import org.junit.jupiter.api.BeforeAll +import org.assertj.core.api.Assertions.assertThatThrownBy import org.junit.jupiter.api.Test import org.junit.jupiter.api.TestInstance import org.skyscreamer.jsonassert.JSONAssert.assertEquals -import org.testcontainers.containers.localstack.LocalStackContainer import org.testcontainers.shaded.com.google.common.io.Files -import org.testcontainers.utility.DockerImageName -import software.amazon.awssdk.services.s3.S3Client import java.util.UUID import javax.inject.Inject @@ -140,10 +136,12 @@ class ApiTest: TestPropertyProvider { @Test fun `blob is not created on bad API PUT`() { - val resp = client - .toBlocking() - .exchange(PUT("/api/jsonBlob/${UUID.randomUUID()}", json).contentType(MediaType.APPLICATION_JSON_TYPE), String::class.java) - assertThat(resp.code()).isEqualTo(400) + assertThatThrownBy { + client + .toBlocking() + .exchange(PUT("/api/jsonBlob/${UUID.randomUUID()}", json).contentType(MediaType.APPLICATION_JSON_TYPE), String::class.java) + + }.isInstanceOf(HttpClientResponseException::class.java) } @Test