From 3513d4c316d9b62d75cb4c921adb5d76ffe83a3b Mon Sep 17 00:00:00 2001 From: Kevin Kruijthof Date: Thu, 10 Jul 2025 11:45:42 +0200 Subject: [PATCH 1/6] feat(backend): Add file router and update image router This commit introduces a new file router for handling file uploads and retrieval, and updates the image router to utilize the new file storage location. The AuthProvider is also updated to use the `java.util` package. --- compose.yaml | 1 + .../com/ex_dock/ex_dock/MainVerticle.kt | 1 - .../backend/v1/router/BackendV1Router.kt | 2 + .../backend/v1/router/auth/AuthProvider.kt | 2 +- .../backend/v1/router/file/fileRouter.kt | 87 +++++++++++++++++++ .../backend/v1/router/image/imageRouter.kt | 45 +++++++++- 6 files changed, 132 insertions(+), 6 deletions(-) create mode 100644 src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/file/fileRouter.kt diff --git a/compose.yaml b/compose.yaml index 11085e61..8ee198d8 100644 --- a/compose.yaml +++ b/compose.yaml @@ -15,6 +15,7 @@ services: - POSTGRES_DB=ex-dock volumes: - ./database/ex-dock.sql:/docker-entrypoint-initdb.d/datadump.sql + - ./application-files:/app/application-files ports: - "8890:5432" networks: diff --git a/src/main/kotlin/com/ex_dock/ex_dock/MainVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/MainVerticle.kt index d79496c6..03321d58 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/MainVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/MainVerticle.kt @@ -50,7 +50,6 @@ class MainVerticle : AbstractVerticle() { startPromise.fail(err) } - val eventBus = vertx.eventBus() val mainRouter : Router = Router.router(vertx) val store = SessionStore.create(vertx) val sessionHandler = SessionHandler.create(store) diff --git a/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/BackendV1Router.kt b/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/BackendV1Router.kt index dbf41467..022a8635 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/BackendV1Router.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/BackendV1Router.kt @@ -2,6 +2,7 @@ package com.ex_dock.ex_dock.backend.v1.router import com.ex_dock.ex_dock.backend.apiMountingPath import com.ex_dock.ex_dock.backend.v1.router.auth.AuthProvider +import com.ex_dock.ex_dock.backend.v1.router.file.initFileRouter import com.ex_dock.ex_dock.database.backend_block.FullBlockInfo import com.ex_dock.ex_dock.frontend.auth.ExDockAuthHandler import com.ex_dock.ex_dock.backend.v1.router.image.initImage @@ -114,6 +115,7 @@ fun Router.enableBackendV1Router(vertx: Vertx, absoluteMounting: Boolean = false // TODO: routing backendV1Router.initImage(vertx) + backendV1Router.initFileRouter(vertx) backendV1Router.enableSystemRouter(vertx) this.route( diff --git a/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/auth/AuthProvider.kt b/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/auth/AuthProvider.kt index 4830ec79..1bb83f67 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/auth/AuthProvider.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/auth/AuthProvider.kt @@ -2,7 +2,7 @@ package com.ex_dock.ex_dock.backend.v1.router.auth import java.security.KeyPair import java.security.KeyPairGenerator -import java.util.Base64 +import java.util.* class AuthProvider { private val generator: KeyPairGenerator = KeyPairGenerator.getInstance("RSA") diff --git a/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/file/fileRouter.kt b/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/file/fileRouter.kt new file mode 100644 index 00000000..910d1614 --- /dev/null +++ b/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/file/fileRouter.kt @@ -0,0 +1,87 @@ +package com.ex_dock.ex_dock.backend.v1.router.file + +import io.vertx.core.Vertx +import io.vertx.core.buffer.Buffer +import io.vertx.core.json.JsonObject +import io.vertx.ext.web.Router +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.Json +import java.nio.file.Paths + +fun Router.initFileRouter(vertx: Vertx) { + val fileRouter = Router.router(vertx) + + fileRouter["/getAll"].handler { ctx -> + val folders = emptyList().toMutableList() + val files = emptyList().toMutableList() + val path = "application-files" + val fullPath = Paths.get(path) + + fullPath.toFile().listFiles()?.forEach { file -> + if (file.isDirectory) { + folders.add(file.name) + } else { + files.add(file.name) + } + } + + val fullList = folders + files + ctx.response().putHeader("Content-Type", "application/json") + .end(JsonObject().put("files", fullList).encode()) + } + + fileRouter["/getAll/:path"].handler { ctx -> + val folders = emptyList().toMutableList() + val files = emptyList().toMutableList() + var path = ctx.pathParam("path") + path = path.replace("%2F", "/") + path = "application-files/$path" + val fullPath = Paths.get(path) + + if (!fullPath.toFile().exists()) { + ctx.fail(400, Error("Path does not exist")) + } + + if (fullPath.toFile().isDirectory) { + fullPath.toFile().listFiles()?.forEach { file -> + if (file.isDirectory) { + val engineFile = EngineFile(file.name, "folder", file.length().toInt()) + folders.add(Json.encodeToString(EngineFile.serializer(), engineFile)) + } else { + val engineFile = EngineFile(file.name, file.extension, file.length().toInt()) + files.add(Json.encodeToString(EngineFile.serializer(), engineFile)) + } + } + + val fullList = folders + files + ctx.response().putHeader("Content-Type", "application/json") + .end(JsonObject().put("files", fullList).encode()) + } else { + val contentType: String = when (fullPath.toFile().extension) { + "png" -> "image/png" + "jpg" -> "image/jpeg" + "jpeg" -> "image/jpeg" + "gif" -> "image/gif" + "avif" -> "image/avif" + "md" -> "text/markdown" + "mp4" -> "video/mp4" + "pdf" -> "application/pdf" + "txt" -> "text/plain" + "webp" -> "image/webp" + else -> "application/octet-stream" + } + + ctx.response().putHeader("Content-Type", contentType) + .end(Buffer.buffer(fullPath.toFile().readBytes())) + } + } + + this.route("/file*").subRouter(fileRouter) +} + +@Serializable +data class EngineFile( + val fileName: String, + val extension: String, + val fileSize: Int +) diff --git a/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/image/imageRouter.kt b/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/image/imageRouter.kt index a14dd185..408ee560 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/image/imageRouter.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/image/imageRouter.kt @@ -1,25 +1,62 @@ package com.ex_dock.ex_dock.backend.v1.router.image +import com.ex_dock.ex_dock.MainVerticle import io.vertx.core.Vertx +import io.vertx.core.buffer.Buffer import io.vertx.ext.web.Router import io.vertx.ext.web.handler.BodyHandler import io.vertx.ext.web.handler.StaticHandler +import java.io.IOException +import java.nio.file.Files +import java.nio.file.Paths +import kotlin.io.path.extension fun Router.initImage(vertx: Vertx) { val imageRouter = Router.router(vertx) val eventBus = vertx.eventBus() imageRouter.post().handler(BodyHandler.create() - .setUploadsDirectory("src/main/resources/images") + .setUploadsDirectory("application-files/images") .setMergeFormAttributes(true)) - imageRouter.post("/").handler(StaticHandler.create("src/main/resources/images").setCachingEnabled(false)) + imageRouter.post("/").handler(StaticHandler.create("application-files/images").setCachingEnabled(false)) - imageRouter.post("/").handler { ctx -> - val path = ctx.request().getFormAttribute("path") + imageRouter.post("/:path").handler { ctx -> + var path = ctx.pathParam("path") + path = path.replace("%2F", "/") eventBus.send("process.service.convertImage", path) ctx.end("request to imageRouter successful") } + imageRouter.get("/get/:path").handler { ctx -> + var path = ctx.pathParam("path") + path = path.replace("%2F", "/") + path = "application-files/$path" + val imagePath = Paths.get(path) + + // Check if the requested image exists + if (!Files.exists(imagePath)) { + MainVerticle.logger.error { "Image not found: $path" } + ctx.response().setStatusCode(404).end("Image not found") + } + + try { + // Read the image file into a byte array + val imageData: ByteArray = Files.readAllBytes(imagePath) + + // Get the image extension type + var extension = imagePath.extension + if (extension == "jpg") extension = "jpeg" + val contentType = "image/$extension" + + ctx.response().putHeader("Content-Type", contentType) + ctx.response().end(Buffer.buffer(imageData)) + } catch (e: IOException) { + MainVerticle.logger.error { "Error reading image file: $path" } + ctx.response().setStatusCode(500).end("Error reading image file") + } + + } + this.route("/image*").subRouter(imageRouter) } From 470b3895358aab685cb1864ac55d8dfd2990f44b Mon Sep 17 00:00:00 2001 From: Kevin Kruijthof Date: Thu, 10 Jul 2025 11:45:56 +0200 Subject: [PATCH 2/6] Please provide the `git diff --staged` output. I need that information to craft the commit message. --- application-files/products/1/test.avif | 0 application-files/products/1/test.jpg | Bin 0 -> 39426 bytes application-files/products/1/test.png | Bin 0 -> 43410 bytes application-files/products/1/test.webp | Bin 0 -> 18514 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 application-files/products/1/test.avif create mode 100644 application-files/products/1/test.jpg create mode 100644 application-files/products/1/test.png create mode 100644 application-files/products/1/test.webp diff --git a/application-files/products/1/test.avif b/application-files/products/1/test.avif new file mode 100644 index 00000000..e69de29b diff --git a/application-files/products/1/test.jpg b/application-files/products/1/test.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ae21009243c4f7df4e0245af0b14f2c8e7cdb16e GIT binary patch literal 39426 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Ð%7L(GLlkBERcYX71wgCA3xQ8m4b3!# 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 literal 0 HcmV?d00001 diff --git a/application-files/products/1/test.png b/application-files/products/1/test.png new file mode 100644 index 0000000000000000000000000000000000000000..93c85a91026134d15977b0b1d53a2806d3dca0b0 GIT binary patch literal 43410 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�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 RM(F3NaUu$3870>s006+?x4!@Y literal 0 HcmV?d00001 From dae2a02850cc2a8ee5976a45e71be088186f9d4f Mon Sep 17 00:00:00 2001 From: Kevin Kruijthof Date: Fri, 11 Jul 2025 10:53:10 +0200 Subject: [PATCH 3/6] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor(verticle):=20?= =?UTF-8?q?Remove=20unnecessary=20AbstractVerticle=20inheritance?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ex_dock/ex_dock/ExtensionsLauncher.kt | 2 - .../com/ex_dock/ex_dock/MainVerticle.kt | 7 +- .../v1/router/system/SystemVerticle.kt | 1 - .../ex_dock/ex_dock/database/JDBCStarter.kt | 2 - .../database/account/AccountJdbcVerticle.kt | 1 - .../database/auth/AuthenticationVerticle.kt | 4 - .../backend_block/BackendBlockJdbcVerticle.kt | 2 - .../database/category/CategoryJdbcVerticle.kt | 1 - .../database/image/ImageJdbcVerticle.kt | 1 - .../product/ProductCompleteEavJdbcVerticle.kt | 97 ------------------- .../ProductCustomAttributesJdbcVerticle.kt | 1 - .../product/ProductGlobalEavJdbcVerticle.kt | 1 - .../database/product/ProductJdbcVerticle.kt | 2 - .../product/ProductMultiSelectJdbcVerticle.kt | 1 - .../ProductStoreViewEavJdbcVerticle.kt | 1 - .../product/ProductWebsiteEavJdbcVerticle.kt | 1 - .../database/scope/ScopeJdbcVerticle.kt | 1 - .../database/server/ServerJDBCVerticle.kt | 1 - .../database/service/ServiceVerticle.kt | 1 - .../database/template/TemplateJdbcVerticle.kt | 1 - .../text_pages/TextPagesJdbcVerticle.kt | 1 - .../ex_dock/database/url/UrlJdbcVerticle.kt | 3 - .../ex_dock/frontend/FrontendVerticle.kt | 1 - .../account/AccountFrontendVerticle.kt | 2 - .../ex_dock/frontend/cache/CacheVerticle.kt | 1 - .../frontend/home/HomeFrontendVerticle.kt | 1 - .../template_engine/TemplateEngineVerticle.kt | 1 - 27 files changed, 6 insertions(+), 133 deletions(-) diff --git a/src/main/kotlin/com/ex_dock/ex_dock/ExtensionsLauncher.kt b/src/main/kotlin/com/ex_dock/ex_dock/ExtensionsLauncher.kt index 573cf57b..dfc8b228 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/ExtensionsLauncher.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/ExtensionsLauncher.kt @@ -5,9 +5,7 @@ import com.ex_dock.ex_dock.frontend.FrontendVerticle import com.ex_dock.ex_dock.helper.deployVerticleHelper import com.ex_dock.ex_dock.helper.registerVerticleIds import io.github.oshai.kotlinlogging.KotlinLogging -import io.vertx.core.AbstractVerticle import io.vertx.core.Future -import io.vertx.core.Promise import io.vertx.core.VerticleBase import io.vertx.ext.web.client.WebClient import java.util.* diff --git a/src/main/kotlin/com/ex_dock/ex_dock/MainVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/MainVerticle.kt index 8f589a4f..b98f862f 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/MainVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/MainVerticle.kt @@ -11,7 +11,6 @@ import com.ex_dock.ex_dock.frontend.text_pages.router.initTextPages import com.ex_dock.ex_dock.helper.registerGenericCodec import com.ex_dock.ex_dock.helper.sendError import io.github.oshai.kotlinlogging.KotlinLogging -import io.vertx.core.AbstractVerticle import io.vertx.core.Future import io.vertx.core.Promise import io.vertx.core.VerticleBase @@ -54,6 +53,12 @@ class MainVerticle : VerticleBase() { val mainRouter : Router = Router.router(vertx) val store = SessionStore.create(vertx) val sessionHandler = SessionHandler.create(store) + val eventBus: EventBus = vertx.eventBus() + + if (!areCodecsRegistered) { + eventBus.registerGenericCodec(ServerStartException::class) + areCodecsRegistered = true + } eventBus.registerGenericCodec(List::class) eventBus.consumer>("process.main.registerVerticleId").handler { message -> diff --git a/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/system/SystemVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/system/SystemVerticle.kt index 0c1fb0d3..85c4400b 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/system/SystemVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/system/SystemVerticle.kt @@ -2,7 +2,6 @@ package com.ex_dock.ex_dock.backend.v1.router.system import com.ex_dock.ex_dock.helper.load import io.github.oshai.kotlinlogging.KotlinLogging -import io.vertx.core.AbstractVerticle import io.vertx.core.Future import io.vertx.core.VerticleBase import io.vertx.core.eventbus.EventBus diff --git a/src/main/kotlin/com/ex_dock/ex_dock/database/JDBCStarter.kt b/src/main/kotlin/com/ex_dock/ex_dock/database/JDBCStarter.kt index 42ea50de..2555d428 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/database/JDBCStarter.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/database/JDBCStarter.kt @@ -32,9 +32,7 @@ import com.ex_dock.ex_dock.database.text_pages.TextPagesSeo import com.ex_dock.ex_dock.database.url.* import com.ex_dock.ex_dock.frontend.cache.CacheVerticle import com.ex_dock.ex_dock.helper.* -import io.vertx.core.AbstractVerticle import io.vertx.core.Future -import io.vertx.core.Promise import io.vertx.core.VerticleBase import io.vertx.core.eventbus.DeliveryOptions import io.vertx.core.eventbus.EventBus diff --git a/src/main/kotlin/com/ex_dock/ex_dock/database/account/AccountJdbcVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/database/account/AccountJdbcVerticle.kt index a1d56d28..21114105 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/database/account/AccountJdbcVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/database/account/AccountJdbcVerticle.kt @@ -2,7 +2,6 @@ package com.ex_dock.ex_dock.database.account import com.ex_dock.ex_dock.database.connection.getConnection import com.ex_dock.ex_dock.frontend.cache.setCacheFlag -import io.vertx.core.AbstractVerticle import io.vertx.core.Future import io.vertx.core.VerticleBase import io.vertx.core.eventbus.DeliveryOptions diff --git a/src/main/kotlin/com/ex_dock/ex_dock/database/auth/AuthenticationVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/database/auth/AuthenticationVerticle.kt index 300d56bd..797c2e48 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/database/auth/AuthenticationVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/database/auth/AuthenticationVerticle.kt @@ -1,10 +1,8 @@ package com.ex_dock.ex_dock.database.auth -import com.ex_dock.ex_dock.database.account.BackendPermissions import com.ex_dock.ex_dock.database.account.FullUser import com.ex_dock.ex_dock.database.account.convertUser import com.ex_dock.ex_dock.frontend.auth.ExDockAuthHandler -import io.vertx.core.AbstractVerticle import io.vertx.core.Future import io.vertx.core.VerticleBase import io.vertx.core.eventbus.EventBus @@ -15,8 +13,6 @@ import io.vertx.ext.auth.authentication.TokenCredentials import io.vertx.ext.auth.authentication.UsernamePasswordCredentials import io.vertx.ext.auth.jwt.JWTAuth import io.vertx.ext.auth.jwt.JWTAuthOptions -import java.security.KeyPair -import java.security.KeyPairGenerator import java.util.* class AuthenticationVerticle: VerticleBase() { diff --git a/src/main/kotlin/com/ex_dock/ex_dock/database/backend_block/BackendBlockJdbcVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/database/backend_block/BackendBlockJdbcVerticle.kt index a826be5c..f0ca2bcf 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/database/backend_block/BackendBlockJdbcVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/database/backend_block/BackendBlockJdbcVerticle.kt @@ -1,8 +1,6 @@ package com.ex_dock.ex_dock.database.backend_block import com.ex_dock.ex_dock.database.connection.getConnection -import io.vertx.core.AbstractVerticle -import io.vertx.core.CompositeFuture import io.vertx.core.Future import io.vertx.core.Promise import io.vertx.core.VerticleBase diff --git a/src/main/kotlin/com/ex_dock/ex_dock/database/category/CategoryJdbcVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/database/category/CategoryJdbcVerticle.kt index a73c1eaa..f6b0d774 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/database/category/CategoryJdbcVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/database/category/CategoryJdbcVerticle.kt @@ -3,7 +3,6 @@ package com.ex_dock.ex_dock.database.category import com.ex_dock.ex_dock.database.connection.getConnection import com.ex_dock.ex_dock.database.product.Products import com.ex_dock.ex_dock.frontend.cache.setCacheFlag -import io.vertx.core.AbstractVerticle import io.vertx.core.Future import io.vertx.core.VerticleBase import io.vertx.core.eventbus.DeliveryOptions diff --git a/src/main/kotlin/com/ex_dock/ex_dock/database/image/ImageJdbcVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/database/image/ImageJdbcVerticle.kt index 753b4072..5399c80b 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/database/image/ImageJdbcVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/database/image/ImageJdbcVerticle.kt @@ -1,7 +1,6 @@ package com.ex_dock.ex_dock.database.image import com.ex_dock.ex_dock.database.connection.getConnection -import io.vertx.core.AbstractVerticle import io.vertx.core.Future import io.vertx.core.VerticleBase import io.vertx.core.eventbus.DeliveryOptions diff --git a/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductCompleteEavJdbcVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductCompleteEavJdbcVerticle.kt index 1cc3a059..be028f45 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductCompleteEavJdbcVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductCompleteEavJdbcVerticle.kt @@ -1,7 +1,6 @@ package com.ex_dock.ex_dock.database.product import com.ex_dock.ex_dock.database.connection.getConnection -import io.vertx.core.AbstractVerticle import io.vertx.core.Future import io.vertx.core.VerticleBase import io.vertx.core.eventbus.EventBus @@ -24,7 +23,6 @@ class ProductCompleteEavJdbcVerticle : VerticleBase() { eventBus = vertx.eventBus() getAllCompleteProductEavData() - getAllCompleteProductEavDataByProductIdOld() getAllCompleteProductEavDataByProductId() return Future.succeededFuture() @@ -123,101 +121,6 @@ class ProductCompleteEavJdbcVerticle : VerticleBase() { } } - @Deprecated("Use the newer function below") - private fun getAllCompleteProductEavDataByProductIdOld() { - val consumer = eventBus.consumer("process.completeEav.getByIdOld") - consumer.handler { message -> - val query = "SELECT " + - "products.product_id AS product_id, " + - "products.name AS product_name, " + - "products.short_name AS product_short_name, " + - "products.description AS product_description, " + - "products.short_description AS product_short_description, " + - "e.attribute_key AS attribute_key, " + - "egb.value AS global_bool, " + - "egf.value AS global_float, " + - "egs.value AS global_string, " + - "egi.value AS global_int, " + - "egm.value AS global_money, " + - "egms.value AS global_multi_select, " + - "esvb.value AS store_view_bool, " + - "esvf.value AS store_view_float, " + - "esvs.value AS store_view_string, " + - "esvi.value AS store_view_int, " + - "esvm.value AS store_view_money, " + - "esvms.value AS store_view_multi_select, " + - "ewb.value AS website_bool, " + - "ewf.value AS website_float, " + - "ews.value AS website_string, " + - "ewi.value AS website_int, " + - "ewm.value AS website_money, " + - "ewms.value AS website_multi_select," + - "msab.value AS multi_select_bool, " + - "msaf.value AS multi_select_float, " + - "msas.value AS multi_select_string, " + - "msai.value AS multi_select_int, " + - "msam.value AS multi_select_money, " + - "w.website_id AS website_id, " + - "sv.store_view_id AS store_view_id " + - "FROM products " + - "LEFT JOIN public.eav e on products.product_id = e.product_id " + - "LEFT JOIN public.custom_product_attributes cpa on cpa.attribute_key = e.attribute_key " + - "LEFT JOIN public.eav_global_bool egb on products.product_id = egb.product_id " + - "LEFT JOIN public.eav_global_float egf on products.product_id = egf.product_id " + - "LEFT JOIN public.eav_global_int egi on products.product_id = egi.product_id " + - "LEFT JOIN public.eav_global_money egm on products.product_id = egm.product_id " + - "LEFT JOIN public.eav_global_multi_select egms on products.product_id = egms.product_id " + - "LEFT JOIN public.eav_global_string egs on products.product_id = egs.product_id " + - "LEFT JOIN public.eav_website_bool ewb on products.product_id = ewb.product_id " + - "LEFT JOIN public.eav_website_float ewf on products.product_id = ewf.product_id " + - "LEFT JOIN public.eav_website_int ewi on products.product_id = ewi.product_id " + - "LEFT JOIN public.eav_website_money ewm on products.product_id = ewm.product_id " + - "LEFT JOIN public.eav_website_multi_select ewms on products.product_id = ewms.product_id " + - "LEFT JOIN public.eav_website_string ews on products.product_id = ews.product_id " + - "LEFT JOIN public.eav_store_view_bool esvb on products.product_id = esvb.product_id " + - "LEFT JOIN public.eav_store_view_float esvf on products.product_id = esvf.product_id " + - "LEFT JOIN public.eav_store_view_int esvi on products.product_id = esvi.product_id " + - "LEFT JOIN public.eav_store_view_money esvm on products.product_id = esvm.product_id " + - "LEFT JOIN public.eav_store_view_multi_select esvms on products.product_id = esvms.product_id " + - "LEFT JOIN public.eav_store_view_string esvs on products.product_id = esvs.product_id " + - "LEFT JOIN public.multi_select_attributes_bool msab on cpa.attribute_key = msab.attribute_key " + - "LEFT JOIN public.multi_select_attributes_float msaf on cpa.attribute_key = msaf.attribute_key " + - "LEFT JOIN public.multi_select_attributes_int msai on cpa.attribute_key = msai.attribute_key " + - "LEFT JOIN public.multi_select_attributes_string msas on cpa.attribute_key = msas.attribute_key " + - "LEFT JOIN public.multi_select_attributes_money msam on cpa.attribute_key = msam.attribute_key " + - "LEFT JOIN public.store_view sv on esvb.store_view_id = sv.store_view_id " + - "LEFT JOIN public.websites w on ewb.website_id = w.website_id " + - "WHERE products.product_id =?" - var json: JsonObject - - val rowsFuture = client.preparedQuery(query).execute(Tuple.of(message.body())) - - rowsFuture.onFailure { res -> - println("Failed to execute query: $res") - message.reply(failedMessage) - } - - rowsFuture.onComplete { res -> - val rows = res.result() - if (rows.size() > 0) { - json = io.vertx.kotlin.core.json.json { - obj( - "completeEav" to rows.map { row -> - obj( - row.makeCompleteEavDataJsonFields() - ) - } - ) - } - - message.reply(json) - } else { - message.reply("No complete product EAV data found!") - } - } - } - } - private fun getAllCompleteProductEavDataByProductId() { val consumer = eventBus.consumer("process.completeEav.getById") consumer.handler { message -> diff --git a/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductCustomAttributesJdbcVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductCustomAttributesJdbcVerticle.kt index 0fa45b27..4d6a3e4b 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductCustomAttributesJdbcVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductCustomAttributesJdbcVerticle.kt @@ -2,7 +2,6 @@ package com.ex_dock.ex_dock.database.product import com.ex_dock.ex_dock.database.connection.getConnection import com.ex_dock.ex_dock.frontend.cache.setCacheFlag -import io.vertx.core.AbstractVerticle import io.vertx.core.Future import io.vertx.core.VerticleBase import io.vertx.core.eventbus.DeliveryOptions diff --git a/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductGlobalEavJdbcVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductGlobalEavJdbcVerticle.kt index 411851ec..cd582114 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductGlobalEavJdbcVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductGlobalEavJdbcVerticle.kt @@ -2,7 +2,6 @@ package com.ex_dock.ex_dock.database.product import com.ex_dock.ex_dock.database.connection.getConnection import com.ex_dock.ex_dock.frontend.cache.setCacheFlag -import io.vertx.core.AbstractVerticle import io.vertx.core.Future import io.vertx.core.VerticleBase import io.vertx.core.eventbus.DeliveryOptions diff --git a/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductJdbcVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductJdbcVerticle.kt index 10556351..ef362cf4 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductJdbcVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductJdbcVerticle.kt @@ -1,12 +1,10 @@ package com.ex_dock.ex_dock.database.product -import com.ex_dock.ex_dock.database.category.PageIndex import com.ex_dock.ex_dock.database.category.convertToString import com.ex_dock.ex_dock.database.category.toPageIndex import com.ex_dock.ex_dock.database.connection.getConnection import com.ex_dock.ex_dock.database.image.Image import com.ex_dock.ex_dock.frontend.cache.setCacheFlag -import io.vertx.core.AbstractVerticle import io.vertx.core.Future import io.vertx.core.VerticleBase import io.vertx.core.eventbus.DeliveryOptions diff --git a/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductMultiSelectJdbcVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductMultiSelectJdbcVerticle.kt index 7efbbe2f..9aae4679 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductMultiSelectJdbcVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductMultiSelectJdbcVerticle.kt @@ -2,7 +2,6 @@ package com.ex_dock.ex_dock.database.product import com.ex_dock.ex_dock.database.connection.getConnection import com.ex_dock.ex_dock.frontend.cache.setCacheFlag -import io.vertx.core.AbstractVerticle import io.vertx.core.Future import io.vertx.core.VerticleBase import io.vertx.core.eventbus.DeliveryOptions diff --git a/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductStoreViewEavJdbcVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductStoreViewEavJdbcVerticle.kt index d5b8c4eb..eb66aaea 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductStoreViewEavJdbcVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductStoreViewEavJdbcVerticle.kt @@ -2,7 +2,6 @@ package com.ex_dock.ex_dock.database.product import com.ex_dock.ex_dock.database.connection.getConnection import com.ex_dock.ex_dock.frontend.cache.setCacheFlag -import io.vertx.core.AbstractVerticle import io.vertx.core.Future import io.vertx.core.VerticleBase import io.vertx.core.eventbus.DeliveryOptions diff --git a/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductWebsiteEavJdbcVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductWebsiteEavJdbcVerticle.kt index 73d94128..db384009 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductWebsiteEavJdbcVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/database/product/ProductWebsiteEavJdbcVerticle.kt @@ -2,7 +2,6 @@ package com.ex_dock.ex_dock.database.product import com.ex_dock.ex_dock.database.connection.getConnection import com.ex_dock.ex_dock.frontend.cache.setCacheFlag -import io.vertx.core.AbstractVerticle import io.vertx.core.Future import io.vertx.core.VerticleBase import io.vertx.core.eventbus.DeliveryOptions diff --git a/src/main/kotlin/com/ex_dock/ex_dock/database/scope/ScopeJdbcVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/database/scope/ScopeJdbcVerticle.kt index 060f8ca0..ae7fda46 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/database/scope/ScopeJdbcVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/database/scope/ScopeJdbcVerticle.kt @@ -2,7 +2,6 @@ package com.ex_dock.ex_dock.database.scope import com.ex_dock.ex_dock.database.connection.getConnection import com.ex_dock.ex_dock.frontend.cache.setCacheFlag -import io.vertx.core.AbstractVerticle import io.vertx.core.Future import io.vertx.core.VerticleBase import io.vertx.core.eventbus.DeliveryOptions diff --git a/src/main/kotlin/com/ex_dock/ex_dock/database/server/ServerJDBCVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/database/server/ServerJDBCVerticle.kt index 0d7f36f3..05affa41 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/database/server/ServerJDBCVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/database/server/ServerJDBCVerticle.kt @@ -2,7 +2,6 @@ package com.ex_dock.ex_dock.database.server import com.ex_dock.ex_dock.database.connection.getConnection import com.ex_dock.ex_dock.frontend.cache.setCacheFlag -import io.vertx.core.AbstractVerticle import io.vertx.core.Future import io.vertx.core.VerticleBase import io.vertx.core.eventbus.DeliveryOptions diff --git a/src/main/kotlin/com/ex_dock/ex_dock/database/service/ServiceVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/database/service/ServiceVerticle.kt index f1a28203..128e2ba1 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/database/service/ServiceVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/database/service/ServiceVerticle.kt @@ -4,7 +4,6 @@ import com.ex_dock.ex_dock.database.account.Permission import com.ex_dock.ex_dock.database.account.hash import com.ex_dock.ex_dock.database.connection.getConnection import com.ex_dock.ex_dock.helper.convertImage -import io.vertx.core.AbstractVerticle import io.vertx.core.Future import io.vertx.core.VerticleBase import io.vertx.core.eventbus.EventBus diff --git a/src/main/kotlin/com/ex_dock/ex_dock/database/template/TemplateJdbcVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/database/template/TemplateJdbcVerticle.kt index 9de85274..a3fe8259 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/database/template/TemplateJdbcVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/database/template/TemplateJdbcVerticle.kt @@ -1,7 +1,6 @@ package com.ex_dock.ex_dock.database.template import com.ex_dock.ex_dock.database.connection.getConnection -import io.vertx.core.AbstractVerticle import io.vertx.core.Future import io.vertx.core.VerticleBase import io.vertx.core.eventbus.DeliveryOptions diff --git a/src/main/kotlin/com/ex_dock/ex_dock/database/text_pages/TextPagesJdbcVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/database/text_pages/TextPagesJdbcVerticle.kt index 37300a3b..d7cdb4ea 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/database/text_pages/TextPagesJdbcVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/database/text_pages/TextPagesJdbcVerticle.kt @@ -5,7 +5,6 @@ import com.ex_dock.ex_dock.database.category.convertToString import com.ex_dock.ex_dock.database.category.toPageIndex import com.ex_dock.ex_dock.database.connection.getConnection import com.ex_dock.ex_dock.frontend.cache.setCacheFlag -import io.vertx.core.AbstractVerticle import io.vertx.core.Future import io.vertx.core.VerticleBase import io.vertx.core.eventbus.DeliveryOptions diff --git a/src/main/kotlin/com/ex_dock/ex_dock/database/url/UrlJdbcVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/database/url/UrlJdbcVerticle.kt index 65f24721..4f424dc4 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/database/url/UrlJdbcVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/database/url/UrlJdbcVerticle.kt @@ -1,14 +1,11 @@ package com.ex_dock.ex_dock.database.url import com.ex_dock.ex_dock.database.category.Categories -import com.ex_dock.ex_dock.database.category.toPageIndex import com.ex_dock.ex_dock.database.connection.getConnection import com.ex_dock.ex_dock.database.product.Products import com.ex_dock.ex_dock.database.text_pages.TextPages import com.ex_dock.ex_dock.frontend.cache.setCacheFlag -import io.vertx.core.AbstractVerticle import io.vertx.core.Future -import io.vertx.core.Verticle import io.vertx.core.VerticleBase import io.vertx.core.eventbus.DeliveryOptions import io.vertx.core.eventbus.EventBus diff --git a/src/main/kotlin/com/ex_dock/ex_dock/frontend/FrontendVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/frontend/FrontendVerticle.kt index 9b6fc4e7..a6b0f670 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/frontend/FrontendVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/frontend/FrontendVerticle.kt @@ -8,7 +8,6 @@ import com.ex_dock.ex_dock.frontend.product.ProductFrontendVerticle import com.ex_dock.ex_dock.frontend.template_engine.TemplateEngineVerticle import com.ex_dock.ex_dock.frontend.text_pages.TextPagesFrontendVerticle import com.ex_dock.ex_dock.helper.deployVerticleHelper -import io.vertx.core.AbstractVerticle import io.vertx.core.Future import io.vertx.core.VerticleBase diff --git a/src/main/kotlin/com/ex_dock/ex_dock/frontend/account/AccountFrontendVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/frontend/account/AccountFrontendVerticle.kt index 5966be80..bcb3653e 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/frontend/account/AccountFrontendVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/frontend/account/AccountFrontendVerticle.kt @@ -1,8 +1,6 @@ package com.ex_dock.ex_dock.frontend.account -import io.vertx.core.AbstractVerticle import io.vertx.core.Future -import io.vertx.core.Promise import io.vertx.core.VerticleBase import io.vertx.core.eventbus.EventBus diff --git a/src/main/kotlin/com/ex_dock/ex_dock/frontend/cache/CacheVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/frontend/cache/CacheVerticle.kt index 2b549bcd..0f647b47 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/frontend/cache/CacheVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/frontend/cache/CacheVerticle.kt @@ -3,7 +3,6 @@ package com.ex_dock.ex_dock.frontend.cache import com.ex_dock.ex_dock.database.service.InvalidCacheKeyException import com.github.benmanes.caffeine.cache.Caffeine import com.github.benmanes.caffeine.cache.LoadingCache -import io.vertx.core.AbstractVerticle import io.vertx.core.Future import io.vertx.core.VerticleBase import io.vertx.core.eventbus.DeliveryOptions diff --git a/src/main/kotlin/com/ex_dock/ex_dock/frontend/home/HomeFrontendVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/frontend/home/HomeFrontendVerticle.kt index 16439e40..5cc9a092 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/frontend/home/HomeFrontendVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/frontend/home/HomeFrontendVerticle.kt @@ -1,6 +1,5 @@ package com.ex_dock.ex_dock.frontend.home -import io.vertx.core.AbstractVerticle import io.vertx.core.Future import io.vertx.core.VerticleBase import io.vertx.core.eventbus.EventBus diff --git a/src/main/kotlin/com/ex_dock/ex_dock/frontend/template_engine/TemplateEngineVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/frontend/template_engine/TemplateEngineVerticle.kt index dbf5a64f..ea9b643b 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/frontend/template_engine/TemplateEngineVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/frontend/template_engine/TemplateEngineVerticle.kt @@ -8,7 +8,6 @@ import com.github.benmanes.caffeine.cache.LoadingCache import io.pebbletemplates.pebble.PebbleEngine import io.pebbletemplates.pebble.loader.StringLoader import io.pebbletemplates.pebble.template.PebbleTemplate -import io.vertx.core.AbstractVerticle import io.vertx.core.Future import io.vertx.core.VerticleBase import io.vertx.core.eventbus.EventBus From ddca003d8cf4e8db7d6bee9fbacad783c067bc67 Mon Sep 17 00:00:00 2001 From: Kevin Kruijthof Date: Fri, 11 Jul 2025 10:53:24 +0200 Subject: [PATCH 4/6] =?UTF-8?q?```=20=F0=9F=90=9B=20fix(pom.xml):=20Update?= =?UTF-8?q?=20Vertx=20launcher=20class=20and=20add=20vertx-launcher-applic?= =?UTF-8?q?ation=20dependency?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ``` --- pom.xml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 399ded35..c386fda0 100644 --- a/pom.xml +++ b/pom.xml @@ -22,7 +22,7 @@ 5.9.1 com.ex_dock.ex_dock.MainVerticle - io.vertx.core.Launcher + io.vertx.launcher.application.VertxApplication @@ -44,6 +44,11 @@ kotlin-stdlib ${kotlin.version} + + io.vertx + vertx-launcher-application + ${vertx.version} + org.jetbrains.kotlin kotlin-reflect @@ -282,7 +287,7 @@ exec-maven-plugin ${exec-maven-plugin.version} - io.vertx.core.Launcher + ${launcher.class} run ${main.verticle} From 538f091aa7922112359ac411459ba05d63f7446e Mon Sep 17 00:00:00 2001 From: Kevin Kruijthof Date: Fri, 11 Jul 2025 10:53:45 +0200 Subject: [PATCH 5/6] feat(backend): Add endpoint to retrieve block data including files. --- .../backend/v1/router/file/fileRouter.kt | 74 +++++++++++++++---- 1 file changed, 61 insertions(+), 13 deletions(-) diff --git a/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/file/fileRouter.kt b/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/file/fileRouter.kt index 910d1614..72af34b7 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/file/fileRouter.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/file/fileRouter.kt @@ -1,7 +1,10 @@ package com.ex_dock.ex_dock.backend.v1.router.file +import com.ex_dock.ex_dock.database.backend_block.FullBlockInfo +import com.google.gson.Gson import io.vertx.core.Vertx import io.vertx.core.buffer.Buffer +import io.vertx.core.eventbus.DeliveryOptions import io.vertx.core.json.JsonObject import io.vertx.ext.web.Router import kotlinx.serialization.Serializable @@ -12,20 +15,8 @@ fun Router.initFileRouter(vertx: Vertx) { val fileRouter = Router.router(vertx) fileRouter["/getAll"].handler { ctx -> - val folders = emptyList().toMutableList() - val files = emptyList().toMutableList() - val path = "application-files" - val fullPath = Paths.get(path) - - fullPath.toFile().listFiles()?.forEach { file -> - if (file.isDirectory) { - folders.add(file.name) - } else { - files.add(file.name) - } - } + val fullList = getRootFiles() - val fullList = folders + files ctx.response().putHeader("Content-Type", "application/json") .end(JsonObject().put("files", fullList).encode()) } @@ -76,9 +67,66 @@ fun Router.initFileRouter(vertx: Vertx) { } } + fileRouter["/getBlockData/:blockName"].handler { ctx -> + val blockName = ctx.pathParam("blockName") + + vertx.eventBus().request>( + "process.backend_block.getAllFullInfoByBlockNames", + blockName, DeliveryOptions().setCodecName("ListCodec") + ).onFailure { + ctx.fail(500, it) + }.onSuccess { result -> + val blocks = result.body() + val jsonResponse = JsonObject() + blocks.forEach { block -> + val blockInformationJson = JsonObject() + val blockAttributesList = mutableListOf() + val fullList = getRootFiles() + + block.blockAttributes.forEach { blockAttribute -> + if (blockAttribute.attributeName == "files") { + val attributeJson = JsonObject() + attributeJson.put("attribute_id", blockAttribute.attributeId) + attributeJson.put("attribute_name", blockAttribute.attributeName) + attributeJson.put("attribute_type", blockAttribute.attributeType) + attributeJson.put( + "current_attribute_value", + Gson().toJson(fullList) + ) + blockAttributesList.add(attributeJson) + } + } + + blockInformationJson.put("block_type", block.backendBlock.blockType) + blockInformationJson.put("attributes", blockAttributesList) + jsonResponse.put(block.backendBlock.blockName, blockInformationJson) + } + + ctx.end(jsonResponse.toString()) + } + } + this.route("/file*").subRouter(fileRouter) } +fun getRootFiles(): List { + val folders = emptyList().toMutableList() + val files = emptyList().toMutableList() + val path = "application-files" + val fullPath = Paths.get(path) + + fullPath.toFile().listFiles()?.forEach { file -> + if (file.isDirectory) { + folders.add(file.name) + } else { + files.add(file.name) + } + } + + val fullList = folders + files + return fullList +} + @Serializable data class EngineFile( val fileName: String, From 11b743c12cfd657fdca86fe4e0e9a4a66f70553c Mon Sep 17 00:00:00 2001 From: Kevin Kruijthof Date: Mon, 28 Jul 2025 16:57:12 +0200 Subject: [PATCH 6/6] =?UTF-8?q?```=20=E2=9C=A8=20feat(backend):=20Improve?= =?UTF-8?q?=20file=20handling=20and=20add=20CORS=20support?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit enhances file handling in the backend, improving the way files are served and adding CORS support for improved security and browser compatibility. It also refactors the file router and updates image conversion. ``` --- pom.xml | 5 ++ .../com/ex_dock/ex_dock/MainVerticle.kt | 3 +- .../ex_dock/ex_dock/backend/BackendRouter.kt | 3 +- .../backend/v1/router/BackendV1Router.kt | 3 +- .../backend/v1/router/file/fileRouter.kt | 65 +++++++++++-------- .../ex_dock/ex_dock/helper/ImageConverter.kt | 2 +- 6 files changed, 49 insertions(+), 32 deletions(-) diff --git a/pom.xml b/pom.xml index 43e686dc..21886e16 100644 --- a/pom.xml +++ b/pom.xml @@ -207,6 +207,11 @@ oshi-core 6.8.2 + + com.fasterxml.jackson.core + jackson-databind + 2.18.0 + diff --git a/src/main/kotlin/com/ex_dock/ex_dock/MainVerticle.kt b/src/main/kotlin/com/ex_dock/ex_dock/MainVerticle.kt index b98f862f..b3946348 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/MainVerticle.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/MainVerticle.kt @@ -18,6 +18,7 @@ import io.vertx.core.eventbus.EventBus import io.vertx.core.http.CookieSameSite import io.vertx.core.http.HttpServerOptions import io.vertx.ext.web.Router +import io.vertx.ext.web.handler.CorsHandler import io.vertx.ext.web.handler.SessionHandler import io.vertx.ext.web.sstore.SessionStore import java.util.Properties @@ -57,7 +58,6 @@ class MainVerticle : VerticleBase() { if (!areCodecsRegistered) { eventBus.registerGenericCodec(ServerStartException::class) - areCodecsRegistered = true } eventBus.registerGenericCodec(List::class) @@ -88,6 +88,7 @@ class MainVerticle : VerticleBase() { sessionHandler.setCookieSameSite(CookieSameSite.STRICT) mainRouter.route().handler(sessionHandler) + mainRouter.route().handler(CorsHandler.create()) mainRouter.enableBackendRouter(vertx, logger) diff --git a/src/main/kotlin/com/ex_dock/ex_dock/backend/BackendRouter.kt b/src/main/kotlin/com/ex_dock/ex_dock/backend/BackendRouter.kt index 979d7ae8..e657959f 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/backend/BackendRouter.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/backend/BackendRouter.kt @@ -4,6 +4,7 @@ import com.ex_dock.ex_dock.backend.v1.router.auth.AuthProvider import com.ex_dock.ex_dock.backend.v1.router.auth.enableAuthRouter import com.ex_dock.ex_dock.backend.v1.router.docker.initDocker import com.ex_dock.ex_dock.backend.v1.router.enableBackendV1Router +import com.ex_dock.ex_dock.backend.v1.router.file.initFileRouter import com.ex_dock.ex_dock.backend.v1.router.websocket.initWebsocket import com.ex_dock.ex_dock.helper.registerGenericCodec import io.github.oshai.kotlinlogging.KLogger @@ -45,8 +46,6 @@ fun Router.enableBackendRouter(vertx: Vertx, logger: KLogger) { pairDeliveryOptions ) - backendRouter.route().handler(CorsHandler.create()) - backendRouter.enableAuthRouter(vertx) // Only use these routers for websockets, because they use other authorization methods diff --git a/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/BackendV1Router.kt b/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/BackendV1Router.kt index 022a8635..12ce9ff7 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/BackendV1Router.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/BackendV1Router.kt @@ -77,6 +77,7 @@ fun Router.enableBackendV1Router(vertx: Vertx, absoluteMounting: Boolean = false "images", jsonElement.findValueByFieldName("images").convertJsonElement() ) + blockInformationJson.put("attributes", blockAttributesList) } else { blockInformationJson.put("attributes", blockAttributesList) } @@ -115,8 +116,8 @@ fun Router.enableBackendV1Router(vertx: Vertx, absoluteMounting: Boolean = false // TODO: routing backendV1Router.initImage(vertx) - backendV1Router.initFileRouter(vertx) backendV1Router.enableSystemRouter(vertx) + backendV1Router.initFileRouter(vertx) this.route( if (absoluteMounting) "$apiMountingPath/v1*" else "/v1*" diff --git a/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/file/fileRouter.kt b/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/file/fileRouter.kt index 72af34b7..71267285 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/file/fileRouter.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/backend/v1/router/file/fileRouter.kt @@ -1,16 +1,18 @@ package com.ex_dock.ex_dock.backend.v1.router.file import com.ex_dock.ex_dock.database.backend_block.FullBlockInfo -import com.google.gson.Gson import io.vertx.core.Vertx import io.vertx.core.buffer.Buffer import io.vertx.core.eventbus.DeliveryOptions import io.vertx.core.json.JsonObject import io.vertx.ext.web.Router import kotlinx.serialization.Serializable -import kotlinx.serialization.json.Json import java.nio.file.Paths +import kotlin.io.encoding.Base64 +import kotlin.io.encoding.ExperimentalEncodingApi +import kotlin.io.path.isDirectory +@OptIn(ExperimentalEncodingApi::class) fun Router.initFileRouter(vertx: Vertx) { val fileRouter = Router.router(vertx) @@ -22,8 +24,8 @@ fun Router.initFileRouter(vertx: Vertx) { } fileRouter["/getAll/:path"].handler { ctx -> - val folders = emptyList().toMutableList() - val files = emptyList().toMutableList() + val folders = emptyList().toMutableList() + val files = emptyList().toMutableList() var path = ctx.pathParam("path") path = path.replace("%2F", "/") path = "application-files/$path" @@ -37,10 +39,10 @@ fun Router.initFileRouter(vertx: Vertx) { fullPath.toFile().listFiles()?.forEach { file -> if (file.isDirectory) { val engineFile = EngineFile(file.name, "folder", file.length().toInt()) - folders.add(Json.encodeToString(EngineFile.serializer(), engineFile)) + folders.add(engineFile) } else { val engineFile = EngineFile(file.name, file.extension, file.length().toInt()) - files.add(Json.encodeToString(EngineFile.serializer(), engineFile)) + files.add(engineFile) } } @@ -49,21 +51,28 @@ fun Router.initFileRouter(vertx: Vertx) { .end(JsonObject().put("files", fullList).encode()) } else { val contentType: String = when (fullPath.toFile().extension) { - "png" -> "image/png" - "jpg" -> "image/jpeg" - "jpeg" -> "image/jpeg" - "gif" -> "image/gif" - "avif" -> "image/avif" - "md" -> "text/markdown" - "mp4" -> "video/mp4" - "pdf" -> "application/pdf" - "txt" -> "text/plain" - "webp" -> "image/webp" - else -> "application/octet-stream" + "png" -> "image" + "jpg" -> "image" + "jpeg" -> "image" + "gif" -> "image" + "avif" -> "image" + "md" -> "markdown" + "mp4" -> "mp4" + "pdf" -> "pdf" + "txt" -> "plain" + "webp" -> "image" + else -> "unknown" } - ctx.response().putHeader("Content-Type", contentType) - .end(Buffer.buffer(fullPath.toFile().readBytes())) + ctx.response().putHeader("Content-Type", "application/octet-stream") + .end( + JsonObject() + .put("contentType", contentType) + .put("fileName", fullPath.toFile().name) + .put("fileSize", fullPath.toFile().length()) + .put("fileExtension", fullPath.toFile().extension) + .put("data", Base64.Default.encode(fullPath.toFile().readBytes())).encode() + ) } } @@ -84,14 +93,14 @@ fun Router.initFileRouter(vertx: Vertx) { val fullList = getRootFiles() block.blockAttributes.forEach { blockAttribute -> - if (blockAttribute.attributeName == "files") { + if (blockAttribute.attributeName == "Files") { val attributeJson = JsonObject() attributeJson.put("attribute_id", blockAttribute.attributeId) attributeJson.put("attribute_name", blockAttribute.attributeName) attributeJson.put("attribute_type", blockAttribute.attributeType) attributeJson.put( "current_attribute_value", - Gson().toJson(fullList) + fullList ) blockAttributesList.add(attributeJson) } @@ -102,24 +111,26 @@ fun Router.initFileRouter(vertx: Vertx) { jsonResponse.put(block.backendBlock.blockName, blockInformationJson) } - ctx.end(jsonResponse.toString()) + ctx.end(jsonResponse.encode()) } } this.route("/file*").subRouter(fileRouter) } -fun getRootFiles(): List { - val folders = emptyList().toMutableList() - val files = emptyList().toMutableList() +fun getRootFiles(): List { + val folders = emptyList().toMutableList() + val files = emptyList().toMutableList() val path = "application-files" val fullPath = Paths.get(path) fullPath.toFile().listFiles()?.forEach { file -> if (file.isDirectory) { - folders.add(file.name) + val engineFile = EngineFile(file.name, "folder", file.length().toInt()) + folders.add(engineFile) } else { - files.add(file.name) + val engineFile = EngineFile(file.name, file.extension, file.length().toInt()) + files.add(engineFile) } } diff --git a/src/main/kotlin/com/ex_dock/ex_dock/helper/ImageConverter.kt b/src/main/kotlin/com/ex_dock/ex_dock/helper/ImageConverter.kt index 1e42058a..55f9f7eb 100644 --- a/src/main/kotlin/com/ex_dock/ex_dock/helper/ImageConverter.kt +++ b/src/main/kotlin/com/ex_dock/ex_dock/helper/ImageConverter.kt @@ -15,7 +15,7 @@ import javax.imageio.stream.ImageOutputStream fun convertImage(path: String) { // Set all the path locations val validExtensions = listOf("png", "jpg", "webp") - val imagePath = System.getProperty("user.dir") + "\\src\\main\\resources\\images\\" + val imagePath = System.getProperty("user.dir") + "\\application-files\\" val pathSplit = path.split(".") val directorySplit = pathSplit[0].split("\\") val fileName = directorySplit.last()