diff --git a/README.md b/README.md index 18ba788..aceddc0 100644 --- a/README.md +++ b/README.md @@ -5,5 +5,7 @@ The rapid API for Bundle powered by Ktor and kotlinx.coroutines. Configuration is managed by environment variables, shown below: 1. `PORT` - The port the server should run on, default 8080 2. `GITHUB_AUTH_USER` - The login for github api requests (optional, but increases ratelimit drastically) -3. `GITHUV_AUTH_PASS` - The password for github api requests -(you can use a client id/clientvsecret pair, or a username/personal access token pair for github auth) +3. `GITHUB_AUTH_PASS` - The password for github api requests +4. `INTERNAL_AUTH` - The authentication string for internal api calls + +(you can use a client id/client secret pair, or a username/personal access token pair for github auth) diff --git a/src/main/kotlin/org/bundleproject/plugins/Routing.kt b/src/main/kotlin/org/bundleproject/plugins/Routing.kt index a496653..53241d2 100644 --- a/src/main/kotlin/org/bundleproject/plugins/Routing.kt +++ b/src/main/kotlin/org/bundleproject/plugins/Routing.kt @@ -8,16 +8,12 @@ import io.ktor.request.* import io.ktor.response.* import io.ktor.routing.* import java.nio.file.Paths -import java.util.* import kotlinx.coroutines.launch import org.bundleproject.json.request.ModRequest import org.bundleproject.json.responses.BulkModResponse import org.bundleproject.json.responses.ModResponse import org.bundleproject.json.responses.ModResponseData -import org.bundleproject.utils.AssetsCache -import org.bundleproject.utils.getBulkMods -import org.bundleproject.utils.getModFromRequest -import org.bundleproject.utils.resolveUrl +import org.bundleproject.utils.* fun Application.configureRouting() { // Preload assets in background @@ -57,6 +53,19 @@ fun Application.configureRouting() { get("/v1/mods/bulk/{bulk}") { call.respond(HttpStatusCode.OK, BulkModResponse(mods = getBulkMods(call))) } + + post("/v1/internal/invalidate-cache") { + if (authentication == null) throw IllegalStateException() + + val params = call.receiveParameters() + val auth = params["password"] ?: throw NoAuthenticationException() + if (auth != authentication) { + call.respond(HttpStatusCode.Forbidden) + } else { + AssetsCache.invalidateCache() + call.respond(HttpStatusCode.OK) + } + } } } } diff --git a/src/main/kotlin/org/bundleproject/plugins/StatusPages.kt b/src/main/kotlin/org/bundleproject/plugins/StatusPages.kt index b9ba416..e9ae9ce 100644 --- a/src/main/kotlin/org/bundleproject/plugins/StatusPages.kt +++ b/src/main/kotlin/org/bundleproject/plugins/StatusPages.kt @@ -5,7 +5,9 @@ import io.ktor.features.* import io.ktor.http.* import io.ktor.response.* import org.bundleproject.json.responses.ErrorResponse +import org.bundleproject.utils.ModDownloadNotAvailableException import org.bundleproject.utils.ModNotFoundException +import org.bundleproject.utils.NoAuthenticationException fun Application.configureStatusPages() { install(StatusPages) { @@ -15,5 +17,17 @@ fun Application.configureStatusPages() { ErrorResponse(error = "Unable to find mod") ) } + exception { + call.respond( + HttpStatusCode.InternalServerError, + ErrorResponse(error = "Could not find mod download") + ) + } + exception { + call.respond( + HttpStatusCode.NonAuthoritativeInformation, + ErrorResponse(error = "Incorrect auth!") + ) + } } } diff --git a/src/main/kotlin/org/bundleproject/utils/Assets.kt b/src/main/kotlin/org/bundleproject/utils/Assets.kt index 89acf70..0c4f392 100644 --- a/src/main/kotlin/org/bundleproject/utils/Assets.kt +++ b/src/main/kotlin/org/bundleproject/utils/Assets.kt @@ -4,6 +4,7 @@ import com.github.zafarkhaja.semver.Version import com.google.gson.Gson import com.google.gson.JsonParser import io.ktor.application.* +import io.ktor.client.features.* import io.ktor.client.request.* import io.ktor.http.* import io.ktor.response.* @@ -45,6 +46,10 @@ object AssetsCache { this.cached!! } } + + suspend fun invalidateCache() { + cached = null + } } suspend fun resolveUrl(modData: ModData): String { @@ -52,7 +57,13 @@ suspend fun resolveUrl(modData: ModData): String { ModSource.DIRECT -> modData.ref ModSource.GITHUB -> { val releases: GithubReleases = - httpClient.get("$githubApiUrl/repos/${modData.ref}/releases") + try { + httpClient.get("$githubApiUrl/repos/${modData.ref}/releases") + } catch (e: ClientRequestException) { + e.printStackTrace() + throw ModDownloadNotAvailableException() + } + releases .find { it.tagName == modData.version || it.tagName == "v${modData.version}" } ?.assets @@ -61,13 +72,22 @@ suspend fun resolveUrl(modData: ModData): String { ?: throw ModNotFoundException() } ModSource.MODRINTH -> { - var id = modData.id - if (id == null) { - val mod: ModrinthMod = httpClient.get("$modrinthApiUrl/mod/${modData.name}") - id = mod.id - } + val id = + try { + httpClient.get("$modrinthApiUrl/mod/${modData.ref}").id + } catch (e: ClientRequestException) { + e.printStackTrace() + throw ModDownloadNotAvailableException() + } + val modVersions: ModrinthModVersions = - httpClient.get("$modrinthApiUrl/mod/${id}/version") + try { + httpClient.get("$modrinthApiUrl/mod/$id/version") + } catch (e: ClientRequestException) { + e.printStackTrace() + throw ModDownloadNotAvailableException() + } + modVersions.find { it.versionNumber == modData.version }?.files?.getOrNull(0)?.url ?: throw ModNotFoundException() } diff --git a/src/main/kotlin/org/bundleproject/utils/Constants.kt b/src/main/kotlin/org/bundleproject/utils/Constants.kt index 2dfb788..54ac4f8 100644 --- a/src/main/kotlin/org/bundleproject/utils/Constants.kt +++ b/src/main/kotlin/org/bundleproject/utils/Constants.kt @@ -3,11 +3,10 @@ package org.bundleproject.utils val port = env("PORT")?.toIntOrNull() ?: 8080 val githubAuth = listOf( - env("GITHUB_AUTH_USER") - ?: throw IllegalArgumentException("No github username/clientid provided"), - env("GITHUB_AUTH_PASS") - ?: throw IllegalArgumentException("No github password/secret provided") + env("GITHUB_AUTH_USER") ?: error("No github username/clientid provided"), + env("GITHUB_AUTH_PASS") ?: error("No github password/secret provided") ) +val authentication = env("INTERNAL_AUTH") fun getAssetsUrl(ref: String) = "$assetsUrlPrefix$ref$assetsUrlSuffix" diff --git a/src/main/kotlin/org/bundleproject/utils/Errors.kt b/src/main/kotlin/org/bundleproject/utils/Errors.kt index ac0be38..10f125a 100644 --- a/src/main/kotlin/org/bundleproject/utils/Errors.kt +++ b/src/main/kotlin/org/bundleproject/utils/Errors.kt @@ -1,5 +1,12 @@ package org.bundleproject.utils +/* Mods */ class ModNotFoundException : Exception() +class ModDownloadNotAvailableException : Exception() + +/* Authentication */ +class NoAuthenticationException : Exception() + +/* Testing */ class CannotFindTestModException : Exception()