mirror of
https://github.com/revanced/revanced-api.git
synced 2025-04-29 22:24:31 +02:00
feat: Add manager route
This commit is contained in:
parent
a34b7c8c31
commit
f814fe5825
@ -1,6 +1,7 @@
|
||||
organization = "revanced"
|
||||
patches = { repository = "revanced-patches", asset-regex = "jar$", signature-asset-regex = "asc$", public-key-file = "patches-public-key.asc" }
|
||||
integrations = { repository = "revanced-integrations", asset-regex = "apk$", signature-asset-regex = "asc$", public-key-file = "integrations-public-key.asc" }
|
||||
manager = { repository = "revanced-manager", asset-regex = "apk$" }
|
||||
contributors-repositories = [
|
||||
"revanced-patcher",
|
||||
"revanced-patches",
|
||||
|
@ -134,6 +134,7 @@ fun Application.configureDependencies(
|
||||
singleOf(::AnnouncementService)
|
||||
singleOf(::SignatureService)
|
||||
singleOf(::PatchesService)
|
||||
singleOf(::ManagerService)
|
||||
singleOf(::ApiService)
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package app.revanced.api.configuration
|
||||
|
||||
import app.revanced.api.configuration.repository.ConfigurationRepository
|
||||
import app.revanced.api.configuration.routes.*
|
||||
import app.revanced.api.configuration.routes.announcementsRoute
|
||||
import app.revanced.api.configuration.routes.apiRoute
|
||||
import app.revanced.api.configuration.routes.oldApiRoute
|
||||
@ -22,6 +23,7 @@ internal fun Application.configureRouting() = routing {
|
||||
route("/v${configuration.apiVersion}") {
|
||||
announcementsRoute()
|
||||
patchesRoute()
|
||||
managerRoute()
|
||||
apiRoute()
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package app.revanced.api.configuration.repository
|
||||
|
||||
import app.revanced.api.configuration.services.ManagerService
|
||||
import app.revanced.api.configuration.services.PatchesService
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.SerialName
|
||||
@ -17,6 +18,7 @@ import java.io.File
|
||||
* @property organization The API backends organization name where the repositories for the patches and integrations are.
|
||||
* @property patches The source of the patches.
|
||||
* @property integrations The source of the integrations.
|
||||
* @property manager The source of the manager.
|
||||
* @property contributorsRepositoryNames The names of the repositories to get contributors from.
|
||||
* @property apiVersion The version to use for the API.
|
||||
* @property corsAllowedHosts The hosts allowed to make requests to the API.
|
||||
@ -26,8 +28,9 @@ import java.io.File
|
||||
@Serializable
|
||||
internal class ConfigurationRepository(
|
||||
val organization: String,
|
||||
val patches: AssetConfiguration,
|
||||
val integrations: AssetConfiguration,
|
||||
val patches: SignedAssetConfiguration,
|
||||
val integrations: SignedAssetConfiguration,
|
||||
val manager: AssetConfiguration,
|
||||
@SerialName("contributors-repositories")
|
||||
val contributorsRepositoryNames: Set<String>,
|
||||
@SerialName("api-version")
|
||||
@ -39,9 +42,9 @@ internal class ConfigurationRepository(
|
||||
val oldApiEndpoint: String,
|
||||
) {
|
||||
/**
|
||||
* An asset configuration.
|
||||
* Am asset configuration whose asset is signed.
|
||||
*
|
||||
* [PatchesService] uses [BackendRepository] to get assets from its releases.
|
||||
* [PatchesService] for example uses [BackendRepository] to get assets from its releases.
|
||||
* A release contains multiple assets.
|
||||
*
|
||||
* This configuration is used in [ConfigurationRepository]
|
||||
@ -54,7 +57,7 @@ internal class ConfigurationRepository(
|
||||
* @property publicKeyId The ID of the public key to verify the signature of the asset.
|
||||
*/
|
||||
@Serializable
|
||||
internal class AssetConfiguration(
|
||||
internal class SignedAssetConfiguration(
|
||||
val repository: String,
|
||||
@Serializable(with = RegexSerializer::class)
|
||||
@SerialName("asset-regex")
|
||||
@ -68,6 +71,26 @@ internal class ConfigurationRepository(
|
||||
@SerialName("public-key-id")
|
||||
val publicKeyId: Long,
|
||||
)
|
||||
|
||||
/**
|
||||
* Am asset configuration.
|
||||
*
|
||||
* [ManagerService] for example uses [BackendRepository] to get assets from its releases.
|
||||
* A release contains multiple assets.
|
||||
*
|
||||
* This configuration is used in [ConfigurationRepository]
|
||||
* to determine which release assets from repositories to get and to verify them.
|
||||
*
|
||||
* @property repository The repository in which releases are made to get an asset.
|
||||
* @property assetRegex The regex matching the asset name.
|
||||
*/
|
||||
@Serializable
|
||||
internal class AssetConfiguration(
|
||||
val repository: String,
|
||||
@Serializable(with = RegexSerializer::class)
|
||||
@SerialName("asset-regex")
|
||||
val assetRegex: Regex,
|
||||
)
|
||||
}
|
||||
|
||||
private object RegexSerializer : KSerializer<Regex> {
|
||||
|
@ -82,7 +82,7 @@ internal fun Route.apiRoute() {
|
||||
}
|
||||
}
|
||||
|
||||
fun Route.installRateLimitRouteDocumentation() = installNotarizedRoute {
|
||||
private fun Route.installRateLimitRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("API")
|
||||
|
||||
get = GetInfo.builder {
|
||||
@ -97,7 +97,7 @@ fun Route.installRateLimitRouteDocumentation() = installNotarizedRoute {
|
||||
}
|
||||
}
|
||||
|
||||
fun Route.installPingRouteDocumentation() = installNotarizedRoute {
|
||||
private fun Route.installPingRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("API")
|
||||
|
||||
head = HeadInfo.builder {
|
||||
@ -111,7 +111,7 @@ fun Route.installPingRouteDocumentation() = installNotarizedRoute {
|
||||
}
|
||||
}
|
||||
|
||||
fun Route.installTeamRouteDocumentation() = installNotarizedRoute {
|
||||
private fun Route.installTeamRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("API")
|
||||
|
||||
get = GetInfo.builder {
|
||||
@ -126,7 +126,7 @@ fun Route.installTeamRouteDocumentation() = installNotarizedRoute {
|
||||
}
|
||||
}
|
||||
|
||||
fun Route.installContributorsRouteDocumentation() = installNotarizedRoute {
|
||||
private fun Route.installContributorsRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("API")
|
||||
|
||||
get = GetInfo.builder {
|
||||
@ -141,7 +141,7 @@ fun Route.installContributorsRouteDocumentation() = installNotarizedRoute {
|
||||
}
|
||||
}
|
||||
|
||||
fun Route.installTokenRouteDocumentation() = installNotarizedRoute {
|
||||
private fun Route.installTokenRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("API")
|
||||
|
||||
get = GetInfo.builder {
|
||||
|
@ -0,0 +1,66 @@
|
||||
package app.revanced.api.configuration.routes
|
||||
|
||||
import app.revanced.api.configuration.installNotarizedRoute
|
||||
import app.revanced.api.configuration.schema.APIManagerAsset
|
||||
import app.revanced.api.configuration.schema.APIRelease
|
||||
import app.revanced.api.configuration.schema.APIReleaseVersion
|
||||
import app.revanced.api.configuration.services.ManagerService
|
||||
import io.bkbn.kompendium.core.metadata.GetInfo
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.plugins.ratelimit.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
import org.koin.ktor.ext.get as koinGet
|
||||
|
||||
internal fun Route.managerRoute() = route("manager") {
|
||||
val managerService = koinGet<ManagerService>()
|
||||
|
||||
route("latest") {
|
||||
installLatestManagerRouteDocumentation()
|
||||
|
||||
rateLimit(RateLimitName("weak")) {
|
||||
get {
|
||||
call.respond(managerService.latestRelease())
|
||||
}
|
||||
|
||||
route("version") {
|
||||
installLatestManagerVersionRouteDocumentation()
|
||||
|
||||
get {
|
||||
call.respond(managerService.latestVersion())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Route.installLatestManagerRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("Manager")
|
||||
|
||||
get = GetInfo.builder {
|
||||
description("Get the latest manager release")
|
||||
summary("Get latest Manager release")
|
||||
response {
|
||||
description("The latest manager release")
|
||||
mediaTypes("application/json")
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<APIRelease<APIManagerAsset>>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Route.installLatestManagerVersionRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("Manager")
|
||||
|
||||
get = GetInfo.builder {
|
||||
description("Get the latest manager release version")
|
||||
summary("Get latest manager release version")
|
||||
response {
|
||||
description("The latest manager release version")
|
||||
mediaTypes("application/json")
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<APIReleaseVersion>()
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ package app.revanced.api.configuration.routes
|
||||
import app.revanced.api.configuration.installCache
|
||||
import app.revanced.api.configuration.installNotarizedRoute
|
||||
import app.revanced.api.configuration.schema.APIAssetPublicKeys
|
||||
import app.revanced.api.configuration.schema.APIPatchesAsset
|
||||
import app.revanced.api.configuration.schema.APIRelease
|
||||
import app.revanced.api.configuration.schema.APIReleaseVersion
|
||||
import app.revanced.api.configuration.services.PatchesService
|
||||
@ -59,7 +60,7 @@ internal fun Route.patchesRoute() = route("patches") {
|
||||
}
|
||||
}
|
||||
|
||||
fun Route.installLatestPatchesRouteDocumentation() = installNotarizedRoute {
|
||||
private fun Route.installLatestPatchesRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("Patches")
|
||||
|
||||
get = GetInfo.builder {
|
||||
@ -69,12 +70,12 @@ fun Route.installLatestPatchesRouteDocumentation() = installNotarizedRoute {
|
||||
description("The latest patches release")
|
||||
mediaTypes("application/json")
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<APIRelease>()
|
||||
responseType<APIRelease<APIPatchesAsset>>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Route.installLatestPatchesVersionRouteDocumentation() = installNotarizedRoute {
|
||||
private fun Route.installLatestPatchesVersionRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("Patches")
|
||||
|
||||
get = GetInfo.builder {
|
||||
@ -89,7 +90,7 @@ fun Route.installLatestPatchesVersionRouteDocumentation() = installNotarizedRout
|
||||
}
|
||||
}
|
||||
|
||||
fun Route.installLatestPatchesListRouteDocumentation() = installNotarizedRoute {
|
||||
private fun Route.installLatestPatchesListRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("Patches")
|
||||
|
||||
get = GetInfo.builder {
|
||||
@ -104,7 +105,7 @@ fun Route.installLatestPatchesListRouteDocumentation() = installNotarizedRoute {
|
||||
}
|
||||
}
|
||||
|
||||
fun Route.installPatchesPublicKeyRouteDocumentation() = installNotarizedRoute {
|
||||
private fun Route.installPatchesPublicKeyRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("Patches")
|
||||
|
||||
get = GetInfo.builder {
|
||||
|
@ -3,15 +3,6 @@ package app.revanced.api.configuration.schema
|
||||
import kotlinx.datetime.LocalDateTime
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
class APIRelease(
|
||||
val version: String,
|
||||
val createdAt: LocalDateTime,
|
||||
val description: String,
|
||||
// Using a list instead of a set because set semantics are unnecessary here.
|
||||
val assets: List<APIAsset>,
|
||||
)
|
||||
|
||||
interface APIUser {
|
||||
val name: String
|
||||
val avatarUrl: String
|
||||
@ -48,7 +39,21 @@ class APIContributable(
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class APIAsset(
|
||||
class APIRelease<T>(
|
||||
val version: String,
|
||||
val createdAt: LocalDateTime,
|
||||
val description: String,
|
||||
// Using a list instead of a set because set semantics are unnecessary here.
|
||||
val assets: List<T>,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class APIManagerAsset(
|
||||
val downloadUrl: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class APIPatchesAsset(
|
||||
val downloadUrl: String,
|
||||
val signatureDownloadUrl: String,
|
||||
// TODO: Remove this eventually when integrations are merged into patches.
|
||||
|
@ -0,0 +1,38 @@
|
||||
package app.revanced.api.configuration.services
|
||||
|
||||
import app.revanced.api.configuration.repository.BackendRepository
|
||||
import app.revanced.api.configuration.repository.BackendRepository.BackendOrganization.BackendRepository.BackendRelease.Companion.first
|
||||
import app.revanced.api.configuration.repository.ConfigurationRepository
|
||||
import app.revanced.api.configuration.schema.*
|
||||
|
||||
internal class ManagerService(
|
||||
private val backendRepository: BackendRepository,
|
||||
private val configurationRepository: ConfigurationRepository,
|
||||
) {
|
||||
suspend fun latestRelease(): APIRelease<APIManagerAsset> {
|
||||
val managerRelease = backendRepository.release(
|
||||
configurationRepository.organization,
|
||||
configurationRepository.manager.repository,
|
||||
)
|
||||
|
||||
val managerAsset = APIManagerAsset(
|
||||
managerRelease.assets.first(configurationRepository.manager.assetRegex).downloadUrl,
|
||||
)
|
||||
|
||||
return APIRelease(
|
||||
managerRelease.tag,
|
||||
managerRelease.createdAt,
|
||||
managerRelease.releaseNote,
|
||||
listOf(managerAsset),
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun latestVersion(): APIReleaseVersion {
|
||||
val managerRelease = backendRepository.release(
|
||||
configurationRepository.organization,
|
||||
configurationRepository.manager.repository,
|
||||
)
|
||||
|
||||
return APIReleaseVersion(managerRelease.tag)
|
||||
}
|
||||
}
|
@ -18,7 +18,7 @@ internal class PatchesService(
|
||||
private val backendRepository: BackendRepository,
|
||||
private val configurationRepository: ConfigurationRepository,
|
||||
) {
|
||||
suspend fun latestRelease(): APIRelease {
|
||||
suspend fun latestRelease(): APIRelease<APIPatchesAsset> {
|
||||
val patchesRelease = backendRepository.release(
|
||||
configurationRepository.organization,
|
||||
configurationRepository.patches.repository,
|
||||
@ -29,10 +29,10 @@ internal class PatchesService(
|
||||
configurationRepository.integrations.repository,
|
||||
)
|
||||
|
||||
fun ConfigurationRepository.AssetConfiguration.asset(
|
||||
fun ConfigurationRepository.SignedAssetConfiguration.asset(
|
||||
release: BackendRepository.BackendOrganization.BackendRepository.BackendRelease,
|
||||
assetName: APIAssetName,
|
||||
) = APIAsset(
|
||||
) = APIPatchesAsset(
|
||||
release.assets.first(assetRegex).downloadUrl,
|
||||
release.assets.first(signatureAssetRegex).downloadUrl,
|
||||
assetName,
|
||||
@ -113,8 +113,8 @@ internal class PatchesService(
|
||||
}
|
||||
|
||||
fun publicKeys(): APIAssetPublicKeys {
|
||||
fun publicKeyBase64(getAssetConfiguration: ConfigurationRepository.() -> ConfigurationRepository.AssetConfiguration) =
|
||||
configurationRepository.getAssetConfiguration().publicKeyFile.readBytes().encodeBase64()
|
||||
fun publicKeyBase64(getSignedAssetConfiguration: ConfigurationRepository.() -> ConfigurationRepository.SignedAssetConfiguration) =
|
||||
configurationRepository.getSignedAssetConfiguration().publicKeyFile.readBytes().encodeBase64()
|
||||
|
||||
return APIAssetPublicKeys(
|
||||
publicKeyBase64 { patches },
|
||||
|
Loading…
x
Reference in New Issue
Block a user