Stuff #1
14
src/main/kotlin/dev/frogmc/Config.kt
Normal file
14
src/main/kotlin/dev/frogmc/Config.kt
Normal 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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
16
src/main/kotlin/dev/frogmc/plugins/Auth.kt
Normal file
16
src/main/kotlin/dev/frogmc/plugins/Auth.kt
Normal 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);
|
||||
}
|
||||
}
|
|
@ -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") {
|
||||
|
|
Loading…
Reference in a new issue