From 2a0b4d98475755d55ab5037183ddd963813fc655 Mon Sep 17 00:00:00 2001 From: Syer10 Date: Fri, 29 Sep 2023 20:19:06 -0400 Subject: [PATCH 1/3] Fix File Upload --- .../server/JavalinGraphQLRequestParser.kt | 11 +--- .../tachidesk/graphql/RequestParserTest.kt | 60 +++++++++++++++++++ 2 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 server/src/test/kotlin/suwayomi/tachidesk/graphql/RequestParserTest.kt diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/JavalinGraphQLRequestParser.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/JavalinGraphQLRequestParser.kt index a6114abe4..e7c00d7b4 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/JavalinGraphQLRequestParser.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/JavalinGraphQLRequestParser.kt @@ -35,18 +35,12 @@ class JavalinGraphQLRequestParser : GraphQLRequestParser { ) }.orEmpty() - val filesMap = map.keys - .sortedBy { it.toIntOrNull() } - .map { context.uploadedFile(it) } - - val mapItems = map.flatMap { (index, variables) -> - val indexInt = index.toIntOrNull() ?: return@flatMap emptyList() - val file = filesMap.getOrNull(indexInt) + val mapItems = map.flatMap { (key, variables) -> + val file = context.uploadedFile(key) variables.map { fullVariable -> val variable = fullVariable.removePrefix("variables.").substringBefore('.') val listIndex = fullVariable.substringAfterLast('.').toIntOrNull() MapItem( - indexInt, variable, listIndex, file @@ -74,7 +68,6 @@ class JavalinGraphQLRequestParser : GraphQLRequestParser { } data class MapItem( - val index: Int, val variable: String, val listIndex: Int?, val file: UploadedFile? diff --git a/server/src/test/kotlin/suwayomi/tachidesk/graphql/RequestParserTest.kt b/server/src/test/kotlin/suwayomi/tachidesk/graphql/RequestParserTest.kt new file mode 100644 index 000000000..2924f6b02 --- /dev/null +++ b/server/src/test/kotlin/suwayomi/tachidesk/graphql/RequestParserTest.kt @@ -0,0 +1,60 @@ +package suwayomi.tachidesk.graphql + +import com.expediagroup.graphql.server.types.GraphQLRequest +import io.javalin.http.Context +import io.javalin.http.UploadedFile +import io.javalin.plugin.json.JSON_MAPPER_KEY +import io.javalin.plugin.json.JavalinJackson +import io.javalin.plugin.json.JsonMapper +import io.mockk.every +import io.mockk.mockk +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Test +import suwayomi.tachidesk.graphql.server.JavalinGraphQLRequestParser +import java.io.ByteArrayInputStream +import kotlin.test.assertIs +import kotlin.test.assertNotNull + +class RequestParserTest { + private val ctx = mockk(relaxed = true) + private val requestParser = JavalinGraphQLRequestParser() + + @Test + fun testZero() = runTest { + every { ctx.appAttribute(JSON_MAPPER_KEY) } returns (JavalinJackson(JavalinJackson.defaultMapper())) + every { ctx.formParam("operation") } returns """{ "query": "mutation (${'$'}file: Upload!) { singleUpload(file: ${'$'}file) { id } }", "variables": { "file": null } }""" + every { ctx.formParam("map") } returns """{ "0": ["variables.file"] }""" + every { ctx.uploadedFile("0") } returns UploadedFile(ByteArrayInputStream(byteArrayOf()), "", "", "", 0) + val test = requestParser.parseRequest(ctx) + assertIs(test) + assertNotNull(test.variables?.get("file")) + println("File: " + test.variables?.get("file")) + } + + @Test + fun testTest() = runTest { + every { ctx.appAttribute(JSON_MAPPER_KEY) } returns (JavalinJackson(JavalinJackson.defaultMapper())) + every { ctx.formParam("operation") } returns """{ "query": "mutation (${'$'}file: Upload!) { singleUpload(file: ${'$'}file) { id } }", "variables": { "file": null } }""" + every { ctx.formParam("map") } returns """{ "test": ["variables.file"] }""" + every { ctx.uploadedFile("test") } returns UploadedFile(ByteArrayInputStream(byteArrayOf()), "", "", "", 0) + val test = requestParser.parseRequest(ctx) + assertIs(test) + assertNotNull(test.variables?.get("file")) + println("File: " + test.variables?.get("file")) + } + + @Test + fun testList() = runTest { + every { ctx.appAttribute(JSON_MAPPER_KEY) } returns (JavalinJackson(JavalinJackson.defaultMapper())) + every { ctx.formParam("operation") } returns """{ "query": "mutation (${'$'}files: [Upload!]!) { singleUpload(files: ${'$'}files) { id } }", "variables": { "files": [null, null] } }""" + every { ctx.formParam("map") } returns """{ "test": ["variables.files.0"], "test2": ["variables.files.1"] }""" + every { ctx.uploadedFile("test") } returns UploadedFile(ByteArrayInputStream(byteArrayOf()), "", "", "", 0) + every { ctx.uploadedFile("test2") } returns UploadedFile(ByteArrayInputStream(byteArrayOf()), "", "", "", 0) + val test = requestParser.parseRequest(ctx) + assertIs(test) + val files = test.variables?.get("files") + assertIs>(files) + assert(files.all { it is UploadedFile }) + println("Files: $files") + } +} From 9ab1d8dc19e1af2f3225d461e77899558ec3124f Mon Sep 17 00:00:00 2001 From: Mitchell Syer Date: Sat, 30 Sep 2023 12:36:02 -0400 Subject: [PATCH 2/3] Use operations instead of operation --- .../tachidesk/graphql/server/JavalinGraphQLRequestParser.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/JavalinGraphQLRequestParser.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/JavalinGraphQLRequestParser.kt index e7c00d7b4..d55d047ef 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/JavalinGraphQLRequestParser.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/JavalinGraphQLRequestParser.kt @@ -21,7 +21,7 @@ class JavalinGraphQLRequestParser : GraphQLRequestParser { @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE", "UNCHECKED_CAST") override suspend fun parseRequest(context: Context): GraphQLServerRequest? { return try { - val formParam = context.formParam("operation") + val formParam = context.formParam("operations") ?: return context.bodyAsClass(GraphQLServerRequest::class.java) val request = context.jsonMapper().fromJsonString( From cbae0306f0264c3f16beb1f6d491358d4985a5a1 Mon Sep 17 00:00:00 2001 From: Mitchell Syer Date: Sat, 30 Sep 2023 12:37:21 -0400 Subject: [PATCH 3/3] Fix tests --- .../kotlin/suwayomi/tachidesk/graphql/RequestParserTest.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/test/kotlin/suwayomi/tachidesk/graphql/RequestParserTest.kt b/server/src/test/kotlin/suwayomi/tachidesk/graphql/RequestParserTest.kt index 2924f6b02..ece905fc1 100644 --- a/server/src/test/kotlin/suwayomi/tachidesk/graphql/RequestParserTest.kt +++ b/server/src/test/kotlin/suwayomi/tachidesk/graphql/RequestParserTest.kt @@ -22,7 +22,7 @@ class RequestParserTest { @Test fun testZero() = runTest { every { ctx.appAttribute(JSON_MAPPER_KEY) } returns (JavalinJackson(JavalinJackson.defaultMapper())) - every { ctx.formParam("operation") } returns """{ "query": "mutation (${'$'}file: Upload!) { singleUpload(file: ${'$'}file) { id } }", "variables": { "file": null } }""" + every { ctx.formParam("operations") } returns """{ "query": "mutation (${'$'}file: Upload!) { singleUpload(file: ${'$'}file) { id } }", "variables": { "file": null } }""" every { ctx.formParam("map") } returns """{ "0": ["variables.file"] }""" every { ctx.uploadedFile("0") } returns UploadedFile(ByteArrayInputStream(byteArrayOf()), "", "", "", 0) val test = requestParser.parseRequest(ctx) @@ -34,7 +34,7 @@ class RequestParserTest { @Test fun testTest() = runTest { every { ctx.appAttribute(JSON_MAPPER_KEY) } returns (JavalinJackson(JavalinJackson.defaultMapper())) - every { ctx.formParam("operation") } returns """{ "query": "mutation (${'$'}file: Upload!) { singleUpload(file: ${'$'}file) { id } }", "variables": { "file": null } }""" + every { ctx.formParam("operations") } returns """{ "query": "mutation (${'$'}file: Upload!) { singleUpload(file: ${'$'}file) { id } }", "variables": { "file": null } }""" every { ctx.formParam("map") } returns """{ "test": ["variables.file"] }""" every { ctx.uploadedFile("test") } returns UploadedFile(ByteArrayInputStream(byteArrayOf()), "", "", "", 0) val test = requestParser.parseRequest(ctx) @@ -46,7 +46,7 @@ class RequestParserTest { @Test fun testList() = runTest { every { ctx.appAttribute(JSON_MAPPER_KEY) } returns (JavalinJackson(JavalinJackson.defaultMapper())) - every { ctx.formParam("operation") } returns """{ "query": "mutation (${'$'}files: [Upload!]!) { singleUpload(files: ${'$'}files) { id } }", "variables": { "files": [null, null] } }""" + every { ctx.formParam("operations") } returns """{ "query": "mutation (${'$'}files: [Upload!]!) { singleUpload(files: ${'$'}files) { id } }", "variables": { "files": [null, null] } }""" every { ctx.formParam("map") } returns """{ "test": ["variables.files.0"], "test2": ["variables.files.1"] }""" every { ctx.uploadedFile("test") } returns UploadedFile(ByteArrayInputStream(byteArrayOf()), "", "", "", 0) every { ctx.uploadedFile("test2") } returns UploadedFile(ByteArrayInputStream(byteArrayOf()), "", "", "", 0)