From 4337020b6bc1e8f676cbadb4071bda13343482c4 Mon Sep 17 00:00:00 2001 From: Graham Date: Thu, 1 Apr 2021 22:51:21 +0100 Subject: [PATCH] Add endpoint for exporting all keys in bulk Signed-off-by: Graham --- .../org/openrs2/archive/key/KeyExporter.kt | 52 +++++++++++++++++-- .../org/openrs2/archive/web/KeysController.kt | 26 ++++++++++ .../org/openrs2/archive/web/WebServer.kt | 4 ++ .../openrs2/archive/templates/keys/index.html | 35 +++++++++++++ .../org/openrs2/archive/templates/layout.html | 3 ++ 5 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 archive/src/main/kotlin/org/openrs2/archive/web/KeysController.kt create mode 100644 archive/src/main/resources/org/openrs2/archive/templates/keys/index.html diff --git a/archive/src/main/kotlin/org/openrs2/archive/key/KeyExporter.kt b/archive/src/main/kotlin/org/openrs2/archive/key/KeyExporter.kt index 10188f06e5..30da09d608 100644 --- a/archive/src/main/kotlin/org/openrs2/archive/key/KeyExporter.kt +++ b/archive/src/main/kotlin/org/openrs2/archive/key/KeyExporter.kt @@ -9,16 +9,45 @@ import javax.inject.Singleton public class KeyExporter @Inject constructor( private val database: Database ) { - public suspend fun exportValid(): List { + public suspend fun count(): Pair { return database.execute { connection -> connection.prepareStatement( """ - SELECT (k.key).k0, (k.key).k1, (k.key).k2, (k.key).k3 + SELECT + COUNT(DISTINCT k.id), + COUNT(DISTINCT k.id) FILTER (WHERE c.key_id IS NOT NULL) FROM keys k - JOIN containers c ON c.key_id = k.id - ORDER BY k.id ASC + LEFT JOIN containers c ON c.key_id = k.id """.trimIndent() ).use { stmt -> + stmt.executeQuery().use { rows -> + check(rows.next()) + + val all = rows.getLong(1) + val valid = rows.getLong(2) + Pair(all, valid) + } + } + } + } + + public suspend fun exportAll(): List { + return export(validOnly = false) + } + + public suspend fun exportValid(): List { + return export(validOnly = true) + } + + private suspend fun export(validOnly: Boolean): List { + return database.execute { connection -> + val query = if (validOnly) { + EXPORT_VALID_QUERY + } else { + EXPORT_ALL_QUERY + } + + connection.prepareStatement(query).use { stmt -> stmt.executeQuery().use { rows -> val keys = mutableListOf() @@ -35,4 +64,19 @@ public class KeyExporter @Inject constructor( } } } + + private companion object { + private val EXPORT_ALL_QUERY = """ + SELECT (k.key).k0, (k.key).k1, (k.key).k2, (k.key).k3 + FROM keys k + ORDER BY k.id ASC + """.trimIndent() + + private val EXPORT_VALID_QUERY = """ + SELECT (k.key).k0, (k.key).k1, (k.key).k2, (k.key).k3 + FROM keys k + JOIN containers c ON c.key_id = k.id + ORDER BY k.id ASC + """.trimIndent() + } } diff --git a/archive/src/main/kotlin/org/openrs2/archive/web/KeysController.kt b/archive/src/main/kotlin/org/openrs2/archive/web/KeysController.kt new file mode 100644 index 0000000000..4d692cf319 --- /dev/null +++ b/archive/src/main/kotlin/org/openrs2/archive/web/KeysController.kt @@ -0,0 +1,26 @@ +package org.openrs2.archive.web + +import io.ktor.application.ApplicationCall +import io.ktor.response.respond +import io.ktor.thymeleaf.ThymeleafContent +import org.openrs2.archive.key.KeyExporter +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +public class KeysController @Inject constructor( + private val exporter: KeyExporter +) { + public suspend fun index(call: ApplicationCall) { + val (all, valid) = exporter.count() + call.respond(ThymeleafContent("keys/index.html", mapOf("all" to all, "valid" to valid))) + } + + public suspend fun exportAll(call: ApplicationCall) { + call.respond(exporter.exportAll()) + } + + public suspend fun exportValid(call: ApplicationCall) { + call.respond(exporter.exportValid()) + } +} diff --git a/archive/src/main/kotlin/org/openrs2/archive/web/WebServer.kt b/archive/src/main/kotlin/org/openrs2/archive/web/WebServer.kt index 6bbfbfe3b7..dd2c67bbc8 100644 --- a/archive/src/main/kotlin/org/openrs2/archive/web/WebServer.kt +++ b/archive/src/main/kotlin/org/openrs2/archive/web/WebServer.kt @@ -29,6 +29,7 @@ import javax.inject.Singleton @Singleton public class WebServer @Inject constructor( private val cachesController: CachesController, + private val keysController: KeysController, @Json private val mapper: ObjectMapper ) { public fun start(address: String, port: Int) { @@ -68,6 +69,9 @@ public class WebServer @Inject constructor( get("/caches/{id}/keys.json") { cachesController.exportKeysJson(call) } get("/caches/{id}/keys.zip") { cachesController.exportKeysZip(call) } get("/caches/{id}/map.png") { cachesController.renderMap(call) } + get("/keys") { keysController.index(call) } + get("/keys/all.json") { keysController.exportAll(call) } + get("/keys/valid.json") { keysController.exportValid(call) } static("/static") { resources("/org/openrs2/archive/static") } } }.start(wait = true) diff --git a/archive/src/main/resources/org/openrs2/archive/templates/keys/index.html b/archive/src/main/resources/org/openrs2/archive/templates/keys/index.html new file mode 100644 index 0000000000..ac33361e0e --- /dev/null +++ b/archive/src/main/resources/org/openrs2/archive/templates/keys/index.html @@ -0,0 +1,35 @@ + + + + Keys - OpenRS2 Archive + + + + + + + +
+

Keys

+

+ There are 0 candidate keys in + the database, of which 0 have + been validated against at least one encrypted group. +

+

Download

+

+ This page allows all raw keys in the database to be exported in + bulk. It doesn't include the archive/group IDs or versions each + key is valid for. To export the keys for a particular build of + the cache, use the download link on the + caches page instead. +

+ +
+ + diff --git a/archive/src/main/resources/org/openrs2/archive/templates/layout.html b/archive/src/main/resources/org/openrs2/archive/templates/layout.html index 0f23c13d17..994d0987d1 100644 --- a/archive/src/main/resources/org/openrs2/archive/templates/layout.html +++ b/archive/src/main/resources/org/openrs2/archive/templates/layout.html @@ -17,6 +17,9 @@ +