mirror of
https://github.com/ReVanced/revanced-api.git
synced 2026-01-24 03:31:05 +00:00
refactor: Refactor into services and repositories
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
package app.revanced.api.configuration
|
||||
|
||||
import app.revanced.api.repository.AnnouncementRepository
|
||||
import app.revanced.api.repository.ConfigurationRepository
|
||||
import app.revanced.api.repository.backend.BackendRepository
|
||||
import app.revanced.api.repository.backend.github.GitHubBackendRepository
|
||||
import app.revanced.api.services.AnnouncementService
|
||||
import app.revanced.api.services.ApiService
|
||||
import app.revanced.api.services.AuthService
|
||||
import app.revanced.api.services.PatchesService
|
||||
import com.akuleshov7.ktoml.Toml
|
||||
import com.akuleshov7.ktoml.source.decodeFromStream
|
||||
import io.github.cdimascio.dotenv.Dotenv
|
||||
import io.ktor.server.application.*
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
import org.koin.core.module.dsl.singleOf
|
||||
import org.koin.dsl.bind
|
||||
import org.koin.dsl.module
|
||||
import org.koin.ktor.plugin.Koin
|
||||
import java.io.File
|
||||
|
||||
fun Application.configureDependencies() {
|
||||
val globalModule = module {
|
||||
single {
|
||||
Dotenv.configure()
|
||||
.systemProperties()
|
||||
.load()
|
||||
}
|
||||
}
|
||||
|
||||
val repositoryModule = module {
|
||||
single {
|
||||
val dotenv = get<Dotenv>()
|
||||
|
||||
Database.connect(
|
||||
url = dotenv["DB_URL"],
|
||||
user = dotenv["DB_USER"],
|
||||
password = dotenv["DB_PASSWORD"],
|
||||
driver = "org.h2.Driver",
|
||||
)
|
||||
}
|
||||
|
||||
single {
|
||||
val configFilePath = get<Dotenv>()["CONFIG_FILE_PATH"]
|
||||
val configFile = File(configFilePath).inputStream()
|
||||
|
||||
Toml.decodeFromStream<ConfigurationRepository>(configFile)
|
||||
}
|
||||
|
||||
singleOf(::AnnouncementRepository)
|
||||
}
|
||||
|
||||
val serviceModule = module {
|
||||
single {
|
||||
val dotenv = get<Dotenv>()
|
||||
|
||||
val jwtSecret = dotenv["JWT_SECRET"]
|
||||
val issuer = dotenv["JWT_ISSUER"]
|
||||
val validityInMin = dotenv["JWT_VALIDITY_IN_MIN"].toInt()
|
||||
|
||||
val basicUsername = dotenv["BASIC_USERNAME"]
|
||||
val basicPassword = dotenv["BASIC_PASSWORD"]
|
||||
|
||||
AuthService(issuer, validityInMin, jwtSecret, basicUsername, basicPassword)
|
||||
}
|
||||
single {
|
||||
val token = get<Dotenv>()["GITHUB_TOKEN"]
|
||||
|
||||
GitHubBackendRepository(token)
|
||||
} bind BackendRepository::class
|
||||
singleOf(::AnnouncementService)
|
||||
singleOf(::PatchesService)
|
||||
singleOf(::ApiService)
|
||||
}
|
||||
|
||||
install(Koin) {
|
||||
modules(
|
||||
globalModule,
|
||||
repositoryModule,
|
||||
serviceModule,
|
||||
)
|
||||
}
|
||||
}
|
||||
26
src/main/kotlin/app/revanced/api/configuration/HTTP.kt
Normal file
26
src/main/kotlin/app/revanced/api/configuration/HTTP.kt
Normal file
@@ -0,0 +1,26 @@
|
||||
package app.revanced.api.configuration
|
||||
|
||||
import io.ktor.http.*
|
||||
import io.ktor.http.content.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.plugins.cachingheaders.*
|
||||
import io.ktor.server.plugins.conditionalheaders.*
|
||||
import io.ktor.server.plugins.cors.routing.*
|
||||
import kotlin.time.Duration.Companion.minutes
|
||||
|
||||
fun Application.configureHTTP(
|
||||
allowedHost: String,
|
||||
) {
|
||||
install(ConditionalHeaders)
|
||||
install(CORS) {
|
||||
allowMethod(HttpMethod.Options)
|
||||
allowMethod(HttpMethod.Put)
|
||||
allowMethod(HttpMethod.Delete)
|
||||
allowMethod(HttpMethod.Patch)
|
||||
allowHeader(HttpHeaders.Authorization)
|
||||
allowHost(allowedHost)
|
||||
}
|
||||
install(CachingHeaders) {
|
||||
options { _, _ -> CachingOptions(CacheControl.MaxAge(maxAgeSeconds = 5.minutes.inWholeSeconds.toInt())) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package app.revanced.api.configuration
|
||||
|
||||
import app.revanced.api.services.AuthService
|
||||
import io.ktor.server.application.*
|
||||
import org.koin.ktor.ext.get
|
||||
|
||||
fun Application.configureSecurity() {
|
||||
get<AuthService>().configureSecurity(this)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package app.revanced.api.configuration
|
||||
|
||||
import io.ktor.serialization.kotlinx.json.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.plugins.contentnegotiation.*
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonNamingStrategy
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
fun Application.configureSerialization() {
|
||||
install(ContentNegotiation) {
|
||||
json(
|
||||
Json {
|
||||
namingStrategy = JsonNamingStrategy.SnakeCase
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package app.revanced.api.configuration.routing
|
||||
|
||||
import app.revanced.api.configuration.routing.routes.configureAnnouncementsRoute
|
||||
import app.revanced.api.configuration.routing.routes.configurePatchesRoute
|
||||
import app.revanced.api.configuration.routing.routes.configureRootRoute
|
||||
import app.revanced.api.repository.ConfigurationRepository
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.routing.*
|
||||
import org.koin.ktor.ext.get
|
||||
|
||||
internal fun Application.configureRouting() = routing {
|
||||
val configuration = get<ConfigurationRepository>()
|
||||
|
||||
route("/v${configuration.apiVersion}") {
|
||||
configureRootRoute()
|
||||
configurePatchesRoute()
|
||||
configureAnnouncementsRoute()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package app.revanced.api.configuration.routing.routes
|
||||
|
||||
import app.revanced.api.schema.APIAnnouncement
|
||||
import app.revanced.api.schema.APIAnnouncementArchivedAt
|
||||
import app.revanced.api.services.AnnouncementService
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.auth.*
|
||||
import io.ktor.server.request.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
import io.ktor.server.util.*
|
||||
import org.koin.ktor.ext.get as koinGet
|
||||
|
||||
internal fun Route.configureAnnouncementsRoute() = route("/announcements") {
|
||||
val announcementService = koinGet<AnnouncementService>()
|
||||
|
||||
route("/{channel}/latest") {
|
||||
get("/id") {
|
||||
val channel: String by call.parameters
|
||||
|
||||
call.respond(
|
||||
announcementService.latestId(channel) ?: return@get call.respond(HttpStatusCode.NotFound),
|
||||
)
|
||||
}
|
||||
|
||||
get {
|
||||
val channel: String by call.parameters
|
||||
|
||||
call.respond(
|
||||
announcementService.latest(channel) ?: return@get call.respond(HttpStatusCode.NotFound),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
get("/{channel}") {
|
||||
val channel: String by call.parameters
|
||||
|
||||
call.respond(announcementService.all(channel))
|
||||
}
|
||||
|
||||
route("/latest") {
|
||||
get("/id") {
|
||||
call.respond(announcementService.latestId() ?: return@get call.respond(HttpStatusCode.NotFound))
|
||||
}
|
||||
|
||||
get {
|
||||
call.respond(announcementService.latest() ?: return@get call.respond(HttpStatusCode.NotFound))
|
||||
}
|
||||
}
|
||||
|
||||
get {
|
||||
call.respond(announcementService.all())
|
||||
}
|
||||
|
||||
authenticate("jwt") {
|
||||
post {
|
||||
announcementService.new(call.receive<APIAnnouncement>())
|
||||
}
|
||||
|
||||
post("/{id}/archive") {
|
||||
val id: Int by call.parameters
|
||||
val archivedAt = call.receiveNullable<APIAnnouncementArchivedAt>()?.archivedAt
|
||||
|
||||
announcementService.archive(id, archivedAt)
|
||||
}
|
||||
|
||||
post("/{id}/unarchive") {
|
||||
val id: Int by call.parameters
|
||||
|
||||
announcementService.unarchive(id)
|
||||
}
|
||||
|
||||
patch("/{id}") {
|
||||
val id: Int by call.parameters
|
||||
|
||||
announcementService.update(id, call.receive<APIAnnouncement>())
|
||||
}
|
||||
|
||||
delete("/{id}") {
|
||||
val id: Int by call.parameters
|
||||
|
||||
announcementService.delete(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package app.revanced.api.configuration.routing.routes
|
||||
|
||||
import app.revanced.api.services.ApiService
|
||||
import app.revanced.api.services.AuthService
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.auth.*
|
||||
import io.ktor.server.http.content.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
import org.koin.ktor.ext.get
|
||||
|
||||
internal fun Route.configureRootRoute() {
|
||||
val apiService = get<ApiService>()
|
||||
val authService = get<AuthService>()
|
||||
|
||||
get("/contributors") {
|
||||
call.respond(apiService.contributors())
|
||||
}
|
||||
|
||||
get("/team") {
|
||||
call.respond(apiService.team())
|
||||
}
|
||||
|
||||
route("/ping") {
|
||||
handle {
|
||||
call.respond(HttpStatusCode.NoContent)
|
||||
}
|
||||
}
|
||||
|
||||
authenticate("basic") {
|
||||
get("/token") {
|
||||
call.respond(authService.newToken())
|
||||
}
|
||||
}
|
||||
|
||||
staticResources("/", "/static/api") {
|
||||
contentType { ContentType.Application.Json }
|
||||
extensions("json")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package app.revanced.api.configuration.routing.routes
|
||||
|
||||
import app.revanced.api.services.PatchesService
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
import org.koin.ktor.ext.get as koinGet
|
||||
|
||||
internal fun Route.configurePatchesRoute() = route("/patches") {
|
||||
val patchesService = koinGet<PatchesService>()
|
||||
|
||||
route("latest") {
|
||||
get {
|
||||
call.respond(patchesService.latestRelease())
|
||||
}
|
||||
|
||||
get("/version") {
|
||||
call.respond(patchesService.latestVersion())
|
||||
}
|
||||
|
||||
get("/list") {
|
||||
call.respondBytes(ContentType.Application.Json) { patchesService.list() }
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user