Skip to content

Commit d8a001f

Browse files
authored
Merge pull request #107 from tburch/validate-put-request-json
Validate put request json
2 parents cf0f589 + 17e4974 commit d8a001f

File tree

7 files changed

+47
-70
lines changed

7 files changed

+47
-70
lines changed

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ plugins {
66
id("io.micronaut.application") version "2.0.2"
77
}
88

9-
version = "1.0.1"
9+
version = "1.0.2"
1010
group = "com.jsonblob"
1111

1212
val kotlinVersion= project.properties["kotlinVersion"]

src/main/kotlin/jsonblob/api/http/ApiController.kt

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ class ApiController(
157157
return false
158158
}
159159

160-
private fun delete(blobId: String) = jsonBlobStore.remove(blobId)
160+
private fun delete(blobId: String) = jsonBlobStore.exists(blobId) && jsonBlobStore.remove(blobId)
161161

162162
private fun updateFirstBlobFromPath(path: String, json: String): JsonBlob? {
163163
val ids = blobIdsFromPath(path)
@@ -169,17 +169,21 @@ class ApiController(
169169
}
170170

171171
private fun update(blobId: String, json: String): JsonBlob? {
172-
val resolver = idResolvers.firstOrNull { it.handles(blobId) }
173-
return if (resolver != null) {
174-
val created = resolver.resolveTimestamp(blobId)
175-
val jsonBlob = JsonBlob(
176-
id = blobId,
177-
json = json,
178-
created = created
179-
)
180-
jsonBlobStore.write(jsonBlob)
172+
if (JsonCleaner.validJson(json)) {
173+
val resolver = idResolvers.firstOrNull { it.handles(blobId) }
174+
return if (resolver != null) {
175+
val created = resolver.resolveTimestamp(blobId)
176+
val jsonBlob = JsonBlob(
177+
id = blobId,
178+
json = json,
179+
created = created
180+
)
181+
jsonBlobStore.write(jsonBlob)
182+
} else {
183+
null
184+
}
181185
} else {
182-
null
186+
throw HttpStatusException(HttpStatus.BAD_REQUEST, "Invalid JSON")
183187
}
184188
}
185189

src/main/kotlin/jsonblob/core/store/JsonBlobStore.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ abstract class JsonBlobStore(
3232
created = created
3333
)
3434
}.onFailure {
35-
log.warn { "Couldn't read JsonBlob with id=$id " }
35+
log.debug { "Couldn't read JsonBlob with id=$id " }
3636
}.getOrNull()
3737
}
3838

src/main/kotlin/jsonblob/core/store/file/FileSystemJsonBlobStore.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ open class FileSystemJsonBlobStore(
5858
lock.unlock()
5959
}
6060
}.onFailure {
61-
log.warn { "Couldn't retrieve JsonBlob with id=$id " }
61+
log.debug { "Couldn't retrieve JsonBlob with id=$id " }
6262
}.getOrNull()
6363
}
6464

src/main/resources/views/editor.hbs

Lines changed: 1 addition & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,6 @@
289289
<script type="text/javascript">
290290
{{#if blobId}}
291291
var blobId = "{{blobId}}";
292-
ga('send', 'event', "Blobs", "load", blobId);
293292
{{else}}
294293
var blobId = null;
295294
{{/if}}
@@ -322,11 +321,6 @@
322321
app.codeEditor.resize();
323322
}
324323
$('#tour').click(function() {
325-
if (blobId) {
326-
ga('send', 'event', "Tour", "start", blobId);
327-
} else {
328-
ga('send', 'event', "Tour", "start");
329-
}
330324
$('#tourContent').joyride({
331325
autoStart: true,
332326
expose: true,
@@ -335,21 +329,7 @@
335329
tipAnimationFadeSpeed: 300,
336330
cookieMonster: true,
337331
cookieName: 'jsonblobTour',
338-
cookieDomain: true,
339-
postRideCallback: function () {
340-
if (blobId) {
341-
ga('send', 'event', "Tour", "complete", blobId);
342-
} else {
343-
ga('send', 'event', "Tour", "complete");
344-
}
345-
},
346-
'postStepCallback': function (index, tip) {
347-
if (blobId) {
348-
ga('send', 'event', "Tour", "step", blobId, index);
349-
} else {
350-
ga('send', 'event', "Tour", "step", null, index);
351-
}
352-
}
332+
cookieDomain: true
353333
});
354334
});
355335
$(document).ready(function() {
@@ -365,11 +345,6 @@
365345
}
366346
});
367347
$("#createGist").click(function() {
368-
if (blobId) {
369-
ga('send', 'event', "Blobs", "gist", blobId);
370-
} else {
371-
ga('send', 'event', "Blobs", "gist");
372-
}
373348
var gist = {
374349
"description": "JSON Blob from " + document.URL,
375350
"public": false,
@@ -394,11 +369,6 @@
394369
});
395370
});
396371
$("#clear").click(function() {
397-
if (blobId) {
398-
ga('send', 'event', "Blobs", "clear", blobId);
399-
} else {
400-
ga('send', 'event', "Blobs", "clear");
401-
}
402372
app.codeEditor.set({});
403373
app.treeEditor.set({});
404374
blobId = null;
@@ -419,11 +389,6 @@
419389
alert("Please enter a URL for the request to be sent to!");
420390
return false;
421391
}
422-
if (blobId) {
423-
ga('send', 'event', "Blobs", "makeRequest", blobId);
424-
} else {
425-
ga('send', 'event', "Blobs", "makeRequest");
426-
}
427392
var method = $(this).text();
428393
var headers = {};
429394
$(".requestHeader").each(function() {
@@ -455,7 +420,6 @@
455420
}
456421
$('#makeRequestModal').modal('hide');
457422
$('#makeRequestSuccess').modal('show');
458-
ga('send', 'event', "Blobs", "makeRequestSuccess");
459423
},
460424
error: function(jqXHR, textStatus, errorThrown) {
461425
if (errorThrown) {
@@ -470,7 +434,6 @@
470434
$(".requestedUrl").text($("#requestUrl").val());
471435
$("#makeRequestModal").modal('hide');
472436
$("#makeRequestFailure").modal('show');
473-
ga('send', 'event', "Blobs", "makeRequestFailure");
474437
},
475438
cache: false
476439
};
@@ -490,11 +453,6 @@
490453
$("#save").click(function() {
491454
var jsonString = app.codeEditor == app.lastChanged ? app.codeEditor.getText() : app.treeEditor.getText();
492455
var valid = !isValidJson(jsonString);
493-
if (blobId) {
494-
ga('send', 'event', "Blobs", "save", blobId, valid ? 1 : 0);
495-
} else {
496-
ga('send', 'event', "Blobs", "save", null, valid ? 1 : 0);
497-
}
498456
if (valid) {
499457
$('#invalidJson').modal('show');
500458
return;

src/main/resources/views/ga.hbs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1+
<!-- Google tag (gtag.js) -->
2+
<script async src="https://www.googletagmanager.com/gtag/js?id={{gaWebPropertyID}}"></script>
13
<script>
2-
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
3-
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
4-
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
5-
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
6-
ga('create', '{{gaWebPropertyID}}', 'auto');
7-
ga('require', 'displayfeatures');
8-
ga('send', 'pageview');
4+
window.dataLayer = window.dataLayer || [];
5+
function gtag(){dataLayer.push(arguments);}
6+
gtag('js', new Date());
7+
8+
gtag('config', '{{gaWebPropertyID}}');
99
</script>

src/test/kotlin/jsonblob/api/http/ApiTest.kt

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,20 @@ import io.micronaut.http.HttpResponse
88
import io.micronaut.http.MediaType
99
import io.micronaut.http.client.HttpClient
1010
import io.micronaut.http.client.annotation.Client
11+
import io.micronaut.http.client.exceptions.HttpClientResponseException
1112
import io.micronaut.test.extensions.junit5.annotation.MicronautTest
1213
import io.micronaut.test.support.TestPropertyProvider
13-
import jsonblob.config.S3ClientBuilderListener
1414
import jsonblob.core.compression.compressor.GZIPBlobCompressor
1515
import jsonblob.core.id.Type1UUIDJsonBlobHandler
1616
import jsonblob.core.store.JsonBlobStore
1717
import mu.KotlinLogging
1818
import org.assertj.core.api.Assertions.assertThat
19-
import org.junit.jupiter.api.AfterAll
20-
import org.junit.jupiter.api.BeforeAll
19+
import org.assertj.core.api.Assertions.assertThatThrownBy
2120
import org.junit.jupiter.api.Test
2221
import org.junit.jupiter.api.TestInstance
2322
import org.skyscreamer.jsonassert.JSONAssert.assertEquals
24-
import org.testcontainers.containers.localstack.LocalStackContainer
2523
import org.testcontainers.shaded.com.google.common.io.Files
26-
import org.testcontainers.utility.DockerImageName
27-
import software.amazon.awssdk.services.s3.S3Client
24+
import java.util.UUID
2825
import javax.inject.Inject
2926

3027

@@ -129,6 +126,24 @@ class ApiTest: TestPropertyProvider {
129126
}
130127
}
131128

129+
@Test
130+
fun `blob is created on API PUT`() {
131+
val resp = client
132+
.toBlocking()
133+
.exchange(PUT("/api/jsonBlob/${type1UUIDJsonBlobHandler.generate()}", json).contentType(MediaType.APPLICATION_JSON_TYPE), String::class.java)
134+
assertThat(resp.code()).isEqualTo(200)
135+
}
136+
137+
@Test
138+
fun `blob is not created on bad API PUT`() {
139+
assertThatThrownBy {
140+
client
141+
.toBlocking()
142+
.exchange(PUT("/api/jsonBlob/${UUID.randomUUID()}", json).contentType(MediaType.APPLICATION_JSON_TYPE), String::class.java)
143+
144+
}.isInstanceOf(HttpClientResponseException::class.java)
145+
}
146+
132147
@Test
133148
fun `blob is updated on custom API PUT`() {
134149
validateUpdate {

0 commit comments

Comments
 (0)