Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
7ab48fd
feat(frontend): Enable frontend router and update config
Moltensnor Oct 9, 2025
1d2d92f
feat(url): add URL routing
Moltensnor Oct 10, 2025
b14be91
fix(template): Enhance template engine caching
Moltensnor Nov 14, 2025
4c01441
fix(auth): Fix package declaration
Moltensnor Nov 14, 2025
53a55cd
refactor(backend): Refactor BackendRouter
Moltensnor Nov 14, 2025
25b08bb
fix(router): Correct package and import statements
Moltensnor Nov 14, 2025
bbcd203
fix(data): Correct data accessor imports
Moltensnor Nov 14, 2025
40f0607
fix(frontend): Improve page rendering
Moltensnor Nov 14, 2025
4a491fc
fix(jdbcHelper): Fix error handling in JDBC queries
Moltensnor Nov 14, 2025
76066a4
fix(core): Fix JDBCStarter imports
Moltensnor Nov 14, 2025
5a0bb78
fix(json): Fix JsonElement extension functions
Moltensnor Nov 14, 2025
76bde22
feat(database): add ListVerticle for data delegation
Moltensnor Nov 14, 2025
3cabdcd
fix(core): Refactor MainVerticle dependencies
Moltensnor Nov 14, 2025
13bf0ed
feat(websocket): Add websocket page router
Moltensnor Nov 14, 2025
2eb74f0
refactor(template): Refactor template cache
Moltensnor Nov 14, 2025
163fcc2
fix(url): Refactor URL creation and update
Moltensnor Nov 14, 2025
dda3121
feat(websocket): add WebsocketHelper for auth
Moltensnor Nov 14, 2025
d80f48c
feat(websocket): add websocket router
Moltensnor Nov 14, 2025
b079bc4
feat(websocket): add WebsocketVerticle
Moltensnor Nov 14, 2025
45e4cef
Merge branch 'main' into frontend-pages
Moltensnor Nov 14, 2025
a8dcbb0
Merge remote-tracking branch 'exDock/main' into frontend-pages
rensPols May 8, 2026
fdb38f7
chore: add additional remote repositories to `.idea/jarRepositories.xml`
rensPols May 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .idea/jarRepositories.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion config/default.properties
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
# Frontend
FRONTEND_PORT=80
FRONTEND_PORT=8888
BASE_URL=http://127.0.0.1
HOST=127.0.0.1

# Backend
BACKEND_PORT=9000

# Websocket
WEBSOCKET_PORT=9001

# Database
JDBC_URL=127.0.0.1
DATABASE_URL="test_url"
Expand Down
42 changes: 35 additions & 7 deletions src/main/kotlin/com/ex_dock/ex_dock/MainVerticle.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package com.ex_dock.ex_dock

import com.ex_dock.ex_dock.backend.enableBackendRouter
import com.ex_dock.ex_dock.backend.v1.router.auth.AuthProvider
import com.ex_dock.ex_dock.frontend.account.router.initAccount
import com.ex_dock.ex_dock.frontend.category.router.initCategory
import com.ex_dock.ex_dock.frontend.checkout.router.initCheckout
import com.ex_dock.ex_dock.frontend.home.router.initHome
import com.ex_dock.ex_dock.frontend.product.router.initProduct
import com.ex_dock.ex_dock.frontend.router.enableFrontendRouter
import com.ex_dock.ex_dock.frontend.text_pages.router.initTextPages
import com.ex_dock.ex_dock.helper.load
import com.ex_dock.ex_dock.helper.codecs.registerGenericCodec
import com.ex_dock.ex_dock.helper.sendError
import com.ex_dock.ex_dock.websocket.router.enableWebsocketRouter
import io.github.oshai.kotlinlogging.KotlinLogging
import io.vertx.core.Future
import io.vertx.core.VerticleBase
Expand Down Expand Up @@ -50,12 +53,13 @@ class MainVerticle : VerticleBase() {

val eventBus = vertx.eventBus()
val mainRouter : Router = Router.router(vertx)
val frontendRouter : Router = Router.router(vertx)
val websocketRouter : Router = Router.router(vertx)
val store = SessionStore.create(vertx)
val sessionHandler = SessionHandler.create(store)
val staticHandler = StaticHandler.create("webroot")
.setCachingEnabled(false)
val authProvider = AuthProvider()

eventBus.registerGenericCodec(List::class)
// eventBus.registerGenericCodec(List::class)
eventBus.consumer<List<String>>("process.main.registerVerticleId").handler { message ->
val verticleIds: List<String> = message.body()
verticleIds.forEach { value ->
Expand Down Expand Up @@ -94,7 +98,7 @@ class MainVerticle : VerticleBase() {
ctx -> ctx.response().sendFile("swagger.json")
}

mainRouter.enableBackendRouter(vertx, logger)
mainRouter.enableBackendRouter(vertx, logger, authProvider)

mainRouter.initHome(eventBus)
mainRouter.initProduct(vertx)
Expand All @@ -103,17 +107,41 @@ class MainVerticle : VerticleBase() {
mainRouter.initCheckout(vertx)
mainRouter.initAccount(vertx)

frontendRouter.enableFrontendRouter(vertx, logger, authProvider)
websocketRouter.enableWebsocketRouter(vertx, logger)

vertx.createHttpServer()
.requestHandler(frontendRouter)
.listen(props.getProperty("FRONTEND_PORT").toInt()).onFailure {
logger.error { "Failed to start HTTP server: $it" }
vertx.eventBus().sendError(Exception("Failed to start the HTTP server"))
}.onSuccess { http ->
logger.info { "HTTP server started on port ${props.getProperty("FRONTEND_PORT")}" }
}

vertx.createHttpServer(
HttpServerOptions()
.setRegisterWebSocketWriteHandlers(true)
)
.requestHandler(websocketRouter)
.listen(props.getProperty("WEBSOCKET_PORT").toInt()).onFailure {
logger.error { "Failed to start HTTP server: $it" }
vertx.eventBus().sendError(Exception("Failed to start the HTTP server"))
}.onSuccess { _ ->
logger.info { "HTTP server started on port ${props.getProperty("WEBSOCKET_PORT")}" }
}

return vertx
.createHttpServer(
HttpServerOptions()
.setRegisterWebSocketWriteHandlers(true)
)
.requestHandler(mainRouter)
.listen(props.getProperty("FRONTEND_PORT").toInt()).onFailure { error ->
.listen(props.getProperty("BACKEND_PORT").toInt()).onFailure { error ->
logger.error { "Failed to start HTTP server: $error" }
vertx.eventBus().sendError(Exception("Failed to start the HTTP server"))
}.onSuccess { _ ->
logger.info { "HTTP server started on port ${props.getProperty("FRONTEND_PORT")}" }
}.onSuccess { http ->
logger.info { "HTTP server started on port ${props.getProperty("BACKEND_PORT")}" }
}
}
}
3 changes: 1 addition & 2 deletions src/main/kotlin/com/ex_dock/ex_dock/backend/BackendRouter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ import io.vertx.ext.web.Router
import io.vertx.ext.web.handler.CorsHandler
import io.vertx.ext.web.handler.JWTAuthHandler

fun Router.enableBackendRouter(vertx: Vertx, logger: KLogger) {
fun Router.enableBackendRouter(vertx: Vertx, logger: KLogger, authProvider: AuthProvider) {
val backendRouter: Router = Router.router(vertx)
val pairDeliveryOptions = DeliveryOptions().setCodecName("PairCodec")
val eventBus = vertx.eventBus()
val authProvider = AuthProvider()
val jwtAuth = JWTAuth.create(
vertx,
JWTAuthOptions()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.ex_dock.ex_dock.backend.v1.router.sales.initSalesRouter
import com.ex_dock.ex_dock.backend.v1.router.pages.enablePagesRouter
import com.ex_dock.ex_dock.backend.v1.router.system.enableSystemRouter
import com.ex_dock.ex_dock.backend.v1.router.template.initTemplateRouter
import com.ex_dock.ex_dock.backend.v1.router.url.initUrlRouter
import com.ex_dock.ex_dock.database.backend_block.BlockInfo
import com.ex_dock.ex_dock.database.product.ProductInfo
import com.ex_dock.ex_dock.frontend.template_engine.template_data.single_use.SingleUseTemplateData
Expand All @@ -32,7 +33,6 @@ fun Router.enableBackendV1Router(vertx: Vertx, absoluteMounting: Boolean = false
val listDeliveryOptions = DeliveryOptions().setCodecName("ListCodec")
val backendV1Router: Router = Router.router(vertx)
val eventBus: EventBus = vertx.eventBus()
val authProvider = AuthProvider()
val exDockAuthHandler = ExDockAuthHandler(vertx)

backendV1Router.route().handler(BodyHandler.create())
Expand Down Expand Up @@ -152,6 +152,7 @@ fun Router.enableBackendV1Router(vertx: Vertx, absoluteMounting: Boolean = false
backendV1Router.initProductsRouter(vertx)
backendV1Router.initTemplateRouter(vertx)
backendV1Router.enablePagesRouter(vertx)
backendV1Router.initUrlRouter(vertx)


this.route(
Expand All @@ -170,6 +171,8 @@ private fun JsonArray.convertAddresses(): JsonArray {
"category" -> resultArray.add(Pair("process.category.getCategoryById", address.getString("id")))
"template" -> resultArray.add(Pair("process.template.getTemplateByKey", address.getString("id")))
"templatesAll" -> resultArray.add(Pair("process.template.getAllTemplates", address.getString("id")))
"url" -> resultArray.add(Pair("process.url.getUrlByKey", address.getString("id")))
"urlsAll" -> resultArray.add(Pair("process.url.getAllUrlKeys", address.getString("id")))
else -> MainVerticle.logger.info { "Unknown address: $address" }
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.ex_dock.ex_dock.backend.v1.router.url

import com.ex_dock.ex_dock.MainVerticle
import com.ex_dock.ex_dock.database.url.UrlKeys
import com.ex_dock.ex_dock.database.url.toDocument
import io.vertx.core.Vertx
import io.vertx.core.eventbus.DeliveryOptions
import io.vertx.core.json.JsonObject
import io.vertx.ext.web.Router

fun Router.initUrlRouter(vertx: Vertx) {
val urlRouter = Router.router(vertx)
val eventBus = vertx.eventBus()
val urlDeliveryOptions = DeliveryOptions().setCodecName("UrlKeysCodec")


urlRouter["/getAll"].handler { ctx ->
eventBus.request<List<JsonObject>>("process.url.getAllUrlKeys", "").onFailure {
ctx.fail(500, it)
}.onSuccess {
ctx.response().putHeader("Content-Type", "application/json")
.end(JsonObject().put("urls", it.body()).encode())
}
}

urlRouter["/get/:key"].handler { ctx ->
val key = ctx.pathParam("key")
eventBus.request<JsonObject>("process.url.getUrlByKey", key).onFailure {
ctx.fail(500, it)
}.onSuccess {
ctx.response().putHeader("Content-Type", "application/json")
.end(it.body().encode())
}
}

urlRouter.post("/create").handler { ctx ->
val requestBody = ctx.body().asJsonObject()
val body = UrlKeys.fromJson(requestBody)
eventBus.request<UrlKeys>("process.url.createUrlKey", body, urlDeliveryOptions).onFailure {
ctx.fail(500, it)
MainVerticle.logger.error { it.localizedMessage }
}.onSuccess {
ctx.response().putHeader("Content-Type", "application/json")
.end(it.body().toDocument().encode())
}
}

urlRouter.put("/update").handler { ctx ->
val body = UrlKeys.fromJson(ctx.body().asJsonObject())
eventBus.request<UrlKeys>("process.url.updateUrlKey", body).onFailure {
ctx.fail(500, it)
MainVerticle.logger.error { it.localizedMessage }
}.onSuccess {
ctx.response().putHeader("Content-Type", "application/json")
.end(it.body().toDocument().encode())
}
}

urlRouter.delete("/delete/:key").handler { ctx ->
val key = ctx.pathParam("key")
eventBus.request<String>("process.url.deleteUrlKey", key).onFailure {
ctx.fail(500, it)
MainVerticle.logger.error { it.localizedMessage }
}.onSuccess {
ctx.end(it.body())
}
}


this.route("/url*").subRouter(urlRouter)
}
4 changes: 4 additions & 0 deletions src/main/kotlin/com/ex_dock/ex_dock/database/JDBCStarter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import com.ex_dock.ex_dock.database.checkout.CheckoutJdbcVerticle
import com.ex_dock.ex_dock.database.home.HomeJdbcVerticle
import com.ex_dock.ex_dock.database.image.Image
import com.ex_dock.ex_dock.database.image.ImageProduct
import com.ex_dock.ex_dock.database.list.ListVerticle
import com.ex_dock.ex_dock.database.product.ProductInfo
import com.ex_dock.ex_dock.database.product.ProductJdbcVerticle
import com.ex_dock.ex_dock.database.sales.*
Expand All @@ -28,6 +29,7 @@ import com.ex_dock.ex_dock.database.template.TemplateJdbcVerticle
import com.ex_dock.ex_dock.database.text_pages.TextPages
import com.ex_dock.ex_dock.database.text_pages.TextPagesJdbcVerticle
import com.ex_dock.ex_dock.database.url.UrlJdbcVerticle
import com.ex_dock.ex_dock.database.url.UrlKeys
import com.ex_dock.ex_dock.frontend.cache.CacheVerticle
import com.ex_dock.ex_dock.frontend.template_engine.TemplateEngineVerticle
import com.ex_dock.ex_dock.frontend.template_engine.template_data.single_use.SingleUseTemplateData
Expand Down Expand Up @@ -101,6 +103,7 @@ class JDBCStarter : VerticleBase() {
verticles.add(vertx.deployWorkerVerticleHelper(SystemVerticle::class))
verticles.add(vertx.deployWorkerVerticleHelper(SalesJdbcVerticle::class))
verticles.add(vertx.deployWorkerVerticleHelper(TemplateJdbcVerticle::class))
verticles.add(vertx.deployWorkerVerticleHelper(ListVerticle::class))
verticles.add(vertx.deployWorkerVerticleHelper(TemplateEngineVerticle::class, workerPoolSize = 5, poolName = "template-cache-isolation-pool"))
}

Expand All @@ -126,6 +129,7 @@ class JDBCStarter : VerticleBase() {
.registerGenericCodec(List::class)
.registerGenericCodec(SingleUseTemplateData::class)
.registerGenericCodec(ArrayList::class)
.registerGenericCodec(UrlKeys::class)

.registerGenericListCodec(FullUser::class)
.registerGenericListCodec(JsonObject::class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ class AuthenticationVerticle : VerticleBase() {
val newTokenOptions = JWTOptions()
.setAlgorithm("RS256")
.setExpiresInMinutes(15)
.setSubject(convertedUser.principal().getString("sub"))
.setSubject(convertedUser.principal().getString("id"))
.setIssuer(issuer)
val newClaims = JsonObject()
.put("permissions", permissions)
Expand All @@ -128,7 +128,7 @@ class AuthenticationVerticle : VerticleBase() {
val refreshTokenOptions = JWTOptions()
.setAlgorithm("RS256")
.setExpiresInMinutes(60 * 24 * 7)
.setSubject(user.principal().getString("id"))
.setSubject(user.principal().getString("sub"))
.setIssuer(issuer)
val refreshClaims = JsonObject()
refreshClaims.put("jti", "jti-" + UUID.randomUUID().toString())
Expand Down
46 changes: 46 additions & 0 deletions src/main/kotlin/com/ex_dock/ex_dock/database/list/ListVerticle.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.ex_dock.ex_dock.database.list

import io.vertx.core.Future
import io.vertx.core.VerticleBase
import io.vertx.core.eventbus.EventBus
import io.vertx.core.json.JsonArray
import io.vertx.core.json.JsonObject

class ListVerticle : VerticleBase() {
private lateinit var eventBus: EventBus
private val addressDictionary = mutableMapOf(
Pair("product", "process.product.getAllProducts"),
Pair("category", "process.category.getAllCategories"),
Pair("credit_memo", "process.sales.getAllCreditMemos"),
Pair("invoice", "process.sales.getAllInvoices"),
Pair("order", "process.sales.getAllOrders"),
Pair("shipment", "process.sales.getAllShipments"),
Pair("transaction", "process.sales.getAllTransactions"),
)

override fun start(): Future<*>? {
eventBus = vertx.eventBus()

delegateListRequest()

return super.start();
}

private fun delegateListRequest() {
eventBus.consumer("process.list.delegateRequest") { message ->
val listName = message.body()

if (addressDictionary.containsKey(listName)) {
val address = addressDictionary[listName]
eventBus.request< List<JsonObject>>(address, "").onFailure {
message.fail(500, it.localizedMessage)
}.onSuccess {
val reply = it.body()
val jsonArray = JsonArray(reply)
message.reply(jsonArray)
}
}
}
}

}
Loading
Loading