Add file uploads

This commit is contained in:
TheKodeToad 2024-06-10 22:07:55 +01:00
parent 13487b5234
commit 1d9b12b8a8
No known key found for this signature in database
GPG key ID: 5E39D70B4C93C38E
4 changed files with 89 additions and 29 deletions

View file

@ -0,0 +1,14 @@
package dev.frogmc
object Config {
val POSTGRES_DATABASE = getEnv("DATABASE", "frogmc")
val POSTGRES_USER = getEnv("USER", "postgres")
val POSTGRES_PASSWORD = getEnv("PASSWORD", "example")
val POSTGRES_HOST = getEnv("HOST", "localhost")
val POSTGRES_PORT = getEnv("PORT", "5432")
val UPLOAD_SECRET = getEnv("UPLOAD_SECRET", "").toByteArray()
private fun getEnv(key: String, default: String): String {
return System.getenv("FROGMC_META_$key") ?: default
}
}

View file

@ -14,18 +14,12 @@ object DB {
fun init(): Boolean {
// use postgresql
try {
val database = getEnv("FROGMC_META_DATABASE", "frogmc")
val user = getEnv("FROGMC_META_USER", "postgres")
val password = getEnv("FROGMC_META_PASSWORD", "example")
val host = getEnv("FROGMC_META_HOST", "localhost")
val port = getEnv("FROGMC_META_PORT", "5432")
logger.info("Connecting to the database...")
val d = Database.connect(
url = "jdbc:postgresql://$host:$port/$database",
url = "jdbc:postgresql://${Config.POSTGRES_HOST}:${Config.POSTGRES_PORT}/${Config.POSTGRES_DATABASE}",
driver = "org.postgresql.Driver",
user,
password
Config.POSTGRES_USER,
Config.POSTGRES_PASSWORD
)
db = d
transaction(db) {
@ -45,10 +39,6 @@ object DB {
logger.error(e.stackTraceToString())
return false
}
if (db == null) {
logger.error("Failed to connect to the database.")
return false
}
logger.info(db!!.name)
return true
}

View file

@ -0,0 +1,16 @@
package dev.frogmc.plugins
import dev.frogmc.Config
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.response.*
import java.nio.charset.StandardCharsets
import java.security.MessageDigest
val authPlugin = createRouteScopedPlugin("auth") {
onCall {
val authorization = it.request.headers["Authorization"]
if (authorization.isNullOrEmpty() || !MessageDigest.isEqual(authorization.toByteArray(), Config.UPLOAD_SECRET))
it.respond(HttpStatusCode.Unauthorized);
}
}

View file

@ -1,6 +1,8 @@
package dev.frogmc.plugins
import dev.frogmc.DB
import dev.frogmc.types.LoaderVersion
import dev.frogmc.types.LoaderVersions
import dev.frogmc.types.ModrinthVersion
import io.ktor.client.*
import io.ktor.client.call.*
@ -9,14 +11,17 @@ import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.html.*
import io.ktor.server.http.content.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import kotlinx.datetime.LocalDateTime
import kotlinx.html.*
import kotlinx.serialization.json.Json
fun BODY.route(block: DIV.() -> Unit) =
div(classes = "route", block)
import org.jetbrains.exposed.exceptions.ExposedSQLException
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.deleteWhere
import org.jetbrains.exposed.sql.insert
import org.jetbrains.exposed.sql.transactions.transaction
fun Application.configureRouting() {
routing {
@ -55,6 +60,16 @@ fun Application.configureRouting() {
p { +"Fetches the download URL of a specific version of FrogMC loader." }
}
br()
div(classes = "route") {
code { +"POST /v1/loader/versions" }
p { +"Uploads a version of the loader. This endpoint requires authorization." }
}
br()
div(classes = "route") {
code { +"DELETE /v1/loader/versions/{version}" }
p { +"Deletes a version of the loader. This endpoint requires authorization." }
}
br()
div(classes = "route") {
code { +"GET /v1/library/versions" }
p { +"Fetches all versions of FrogMC library." }
@ -89,10 +104,7 @@ fun Application.configureRouting() {
call.respond(versions.first())
}
get("/versions/{version}/download") {
val version = call.parameters["version"] ?: return@get call.respond(
HttpStatusCode.BadRequest,
"message" to "Invalid version."
)
val version = call.parameters["version"] ?: return@get call.respond(HttpStatusCode.BadRequest)
val versions = DB.getLoaderVersions()
val versionObj = versions.find { it.version == version } ?: return@get call.respond(
HttpStatusCode.NotFound,
@ -101,17 +113,45 @@ fun Application.configureRouting() {
call.respond("url" to versionObj.downloadUrl)
}
get("/versions/{version}") {
val version = call.parameters["version"] ?: return@get call.respond(
HttpStatusCode.BadRequest,
"message" to "Invalid version."
)
val version = call.parameters["version"] ?: return@get call.respond(HttpStatusCode.BadRequest)
val versions = DB.getLoaderVersions()
val versionObj = versions.find { it.version == version } ?: return@get call.respond(
HttpStatusCode.NotFound,
"message" to "Version not found."
)
val versionObj =
versions.find { it.version == version } ?: return@get call.respond(HttpStatusCode.NotFound)
call.respond(versionObj)
}
route("/versions") {
install(authPlugin)
post {
val versionObj = call.receive<LoaderVersion>()
try {
transaction {
LoaderVersions.insert {
it[version] = versionObj.version
it[releaseDate] = versionObj.releaseDate
it[downloadUrl] = versionObj.downloadUrl
}
}
} catch (e: ExposedSQLException) { // TODO: this catches EVERYTHING
call.respond(HttpStatusCode.Conflict)
return@post
}
call.respond(HttpStatusCode.OK)
}
}
route("/versions/{version}") {
install(authPlugin)
delete {
val version =
call.parameters["version"] ?: return@delete call.respond(HttpStatusCode.BadRequest)
transaction {
LoaderVersions.deleteWhere {
LoaderVersions.version eq version
}
}
call.respond(HttpStatusCode.OK)
}
}
}
route("/library") {
get("/versions") {