mirror of
https://github.com/Suwayomi/Suwayomi-Server.git
synced 2026-07-11 23:04:33 -05:00
Basic JWT implementation (#1524)
* Basic JWT implementation * Move JWT to UI_LOGIN mode and bring back SIMPLE_LOGIN as before * Update server/src/main/kotlin/suwayomi/tachidesk/global/impl/util/Jwt.kt Co-authored-by: Mitchell Syer <Syer10@users.noreply.github.com> * Refresh: Update only access token Co-authored-by: Mitchell Syer <Syer10@users.noreply.github.com> * Implement JWT Audience * Store JWT key Generates the key on startup if not set * Handle invalid Base64 * Make JWT expiry configurable * Missing value parse * Update server/src/main/kotlin/suwayomi/tachidesk/global/impl/util/Jwt.kt Co-authored-by: Mitchell Syer <Syer10@users.noreply.github.com> * Simplify Duration parsing * JWT Protect Mutations * JWT Protect Queries and Subscriptions * JWT Protect v1 WebSockets * WebSockets allow sending token via protocol header * Also respect the `suwayomi-server-token` cookie * JWT reduce default token expiry * JWT Support cookie on WebSocket as well * Lint * Authenticate graphql subscription via connection_init payload * WebView: Prefer explicit token over cookie This hack was implemented because WebView sent `"null"` if no token was supplied, just don't send a bad token, then we can do this properly * WebView: Implement basic login dialog if no token supplied --------- Co-authored-by: Mitchell Syer <Syer10@users.noreply.github.com> Co-authored-by: schroda <50052685+schroda@users.noreply.github.com>
This commit is contained in:
@@ -6,7 +6,10 @@ import suwayomi.tachidesk.manga.impl.backup.proto.ProtoBackupExport
|
||||
import suwayomi.tachidesk.manga.impl.backup.proto.ProtoBackupImport
|
||||
import suwayomi.tachidesk.manga.impl.backup.proto.ProtoBackupValidator
|
||||
import suwayomi.tachidesk.manga.impl.backup.proto.models.Backup
|
||||
import suwayomi.tachidesk.server.JavalinSetup.Attribute
|
||||
import suwayomi.tachidesk.server.JavalinSetup.future
|
||||
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
|
||||
import suwayomi.tachidesk.server.user.requireUser
|
||||
import suwayomi.tachidesk.server.util.handler
|
||||
import suwayomi.tachidesk.server.util.withOperation
|
||||
|
||||
@@ -28,6 +31,7 @@ object BackupController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.future {
|
||||
future {
|
||||
ProtoBackupImport.restoreLegacy(ctx.bodyInputStream())
|
||||
@@ -55,6 +59,7 @@ object BackupController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
// TODO: rewrite this with ctx.uploadedFiles(), don't call the multipart field "backup.proto.gz"
|
||||
ctx.future {
|
||||
future {
|
||||
@@ -80,6 +85,7 @@ object BackupController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.contentType("application/octet-stream")
|
||||
ctx.future {
|
||||
future {
|
||||
@@ -112,6 +118,7 @@ object BackupController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.contentType("application/octet-stream")
|
||||
|
||||
ctx.header("Content-Disposition", """attachment; filename="${Backup.getFilename()}"""")
|
||||
@@ -146,6 +153,7 @@ object BackupController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.future {
|
||||
future {
|
||||
ProtoBackupValidator.validate(ctx.bodyInputStream())
|
||||
@@ -177,6 +185,7 @@ object BackupController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.future {
|
||||
future {
|
||||
ProtoBackupValidator.validate(ctx.uploadedFile("backup.proto.gz")!!.content())
|
||||
|
||||
@@ -12,6 +12,9 @@ import suwayomi.tachidesk.manga.impl.Category
|
||||
import suwayomi.tachidesk.manga.impl.CategoryManga
|
||||
import suwayomi.tachidesk.manga.model.dataclass.CategoryDataClass
|
||||
import suwayomi.tachidesk.manga.model.dataclass.MangaDataClass
|
||||
import suwayomi.tachidesk.server.JavalinSetup.Attribute
|
||||
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
|
||||
import suwayomi.tachidesk.server.user.requireUser
|
||||
import suwayomi.tachidesk.server.util.formParam
|
||||
import suwayomi.tachidesk.server.util.handler
|
||||
import suwayomi.tachidesk.server.util.pathParam
|
||||
@@ -28,6 +31,7 @@ object CategoryController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.json(Category.getCategoryList())
|
||||
},
|
||||
withResults = {
|
||||
@@ -46,6 +50,7 @@ object CategoryController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, name ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
if (Category.createCategory(name) != -1) {
|
||||
ctx.status(200)
|
||||
} else {
|
||||
@@ -73,6 +78,7 @@ object CategoryController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, categoryId, name, isDefault, includeInUpdate, includeInDownload ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
Category.updateCategory(categoryId, name, isDefault, includeInUpdate, includeInDownload)
|
||||
ctx.status(200)
|
||||
},
|
||||
@@ -92,6 +98,7 @@ object CategoryController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, categoryId ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
Category.removeCategory(categoryId)
|
||||
ctx.status(200)
|
||||
},
|
||||
@@ -111,6 +118,7 @@ object CategoryController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, categoryId ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.json(CategoryManga.getCategoryMangaList(categoryId))
|
||||
},
|
||||
withResults = {
|
||||
@@ -130,6 +138,7 @@ object CategoryController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, from, to ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
Category.reorderCategory(from, to)
|
||||
ctx.status(200)
|
||||
},
|
||||
@@ -151,6 +160,7 @@ object CategoryController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, categoryId, key, value ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
Category.modifyMeta(categoryId, key, value)
|
||||
ctx.status(200)
|
||||
},
|
||||
|
||||
@@ -12,7 +12,10 @@ import io.javalin.websocket.WsConfig
|
||||
import kotlinx.serialization.json.Json
|
||||
import suwayomi.tachidesk.manga.impl.download.DownloadManager
|
||||
import suwayomi.tachidesk.manga.impl.download.DownloadManager.EnqueueInput
|
||||
import suwayomi.tachidesk.server.JavalinSetup.Attribute
|
||||
import suwayomi.tachidesk.server.JavalinSetup.future
|
||||
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
|
||||
import suwayomi.tachidesk.server.user.requireUser
|
||||
import suwayomi.tachidesk.server.util.handler
|
||||
import suwayomi.tachidesk.server.util.pathParam
|
||||
import suwayomi.tachidesk.server.util.withOperation
|
||||
@@ -24,6 +27,7 @@ object DownloadController {
|
||||
/** Download queue stats */
|
||||
fun downloadsWS(ws: WsConfig) {
|
||||
ws.onConnect { ctx ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
DownloadManager.addClient(ctx)
|
||||
DownloadManager.notifyClient(ctx)
|
||||
}
|
||||
@@ -44,7 +48,8 @@ object DownloadController {
|
||||
description("Start the downloader")
|
||||
}
|
||||
},
|
||||
behaviorOf = {
|
||||
behaviorOf = { ctx ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
DownloadManager.start()
|
||||
},
|
||||
withResults = {
|
||||
@@ -62,6 +67,7 @@ object DownloadController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.future {
|
||||
future { DownloadManager.stop() }
|
||||
.thenApply { ctx.status(HttpStatus.OK) }
|
||||
@@ -82,6 +88,7 @@ object DownloadController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.future {
|
||||
future { DownloadManager.clear() }
|
||||
.thenApply { ctx.status(HttpStatus.OK) }
|
||||
@@ -104,6 +111,7 @@ object DownloadController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, chapterIndex, mangaId ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.future {
|
||||
future {
|
||||
DownloadManager.enqueueWithChapterIndex(mangaId, chapterIndex)
|
||||
@@ -126,6 +134,7 @@ object DownloadController {
|
||||
body<EnqueueInput>()
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
val inputs = json.decodeFromString<EnqueueInput>(ctx.body())
|
||||
ctx.future {
|
||||
future {
|
||||
@@ -149,6 +158,7 @@ object DownloadController {
|
||||
body<EnqueueInput>()
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
val input = json.decodeFromString<EnqueueInput>(ctx.body())
|
||||
ctx.future {
|
||||
future {
|
||||
@@ -173,6 +183,7 @@ object DownloadController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, chapterIndex, mangaId ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
DownloadManager.dequeue(chapterIndex, mangaId)
|
||||
|
||||
ctx.status(200)
|
||||
@@ -194,7 +205,8 @@ object DownloadController {
|
||||
description("Reorder chapter in download queue")
|
||||
}
|
||||
},
|
||||
behaviorOf = { _, chapterIndex, mangaId, to ->
|
||||
behaviorOf = { ctx, chapterIndex, mangaId, to ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
DownloadManager.reorder(chapterIndex, mangaId, to)
|
||||
},
|
||||
withResults = {
|
||||
|
||||
@@ -12,7 +12,10 @@ import io.javalin.http.HttpStatus
|
||||
import suwayomi.tachidesk.manga.impl.extension.Extension
|
||||
import suwayomi.tachidesk.manga.impl.extension.ExtensionsList
|
||||
import suwayomi.tachidesk.manga.model.dataclass.ExtensionDataClass
|
||||
import suwayomi.tachidesk.server.JavalinSetup.Attribute
|
||||
import suwayomi.tachidesk.server.JavalinSetup.future
|
||||
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
|
||||
import suwayomi.tachidesk.server.user.requireUser
|
||||
import suwayomi.tachidesk.server.util.handler
|
||||
import suwayomi.tachidesk.server.util.pathParam
|
||||
import suwayomi.tachidesk.server.util.withOperation
|
||||
@@ -31,6 +34,7 @@ object ExtensionController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.future {
|
||||
future {
|
||||
ExtensionsList.getExtensionList()
|
||||
@@ -55,6 +59,7 @@ object ExtensionController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, pkgName ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.future {
|
||||
future {
|
||||
Extension.installExtension(pkgName)
|
||||
@@ -84,6 +89,7 @@ object ExtensionController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
val uploadedFile = ctx.uploadedFile("file")!!
|
||||
logger.debug { "Uploaded extension file name: " + uploadedFile.filename() }
|
||||
|
||||
@@ -116,6 +122,7 @@ object ExtensionController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, pkgName ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.future {
|
||||
future {
|
||||
Extension.updateExtension(pkgName)
|
||||
@@ -143,6 +150,7 @@ object ExtensionController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, pkgName ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
Extension.uninstallExtension(pkgName)
|
||||
ctx.status(200)
|
||||
},
|
||||
@@ -165,6 +173,7 @@ object ExtensionController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, apkName ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.future {
|
||||
future { Extension.getExtensionIcon(apkName) }
|
||||
.thenApply {
|
||||
|
||||
@@ -26,7 +26,10 @@ import suwayomi.tachidesk.manga.model.dataclass.CategoryDataClass
|
||||
import suwayomi.tachidesk.manga.model.dataclass.ChapterDataClass
|
||||
import suwayomi.tachidesk.manga.model.dataclass.MangaDataClass
|
||||
import suwayomi.tachidesk.manga.model.table.ChapterTable
|
||||
import suwayomi.tachidesk.server.JavalinSetup.Attribute
|
||||
import suwayomi.tachidesk.server.JavalinSetup.future
|
||||
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
|
||||
import suwayomi.tachidesk.server.user.requireUser
|
||||
import suwayomi.tachidesk.server.util.formParam
|
||||
import suwayomi.tachidesk.server.util.handler
|
||||
import suwayomi.tachidesk.server.util.pathParam
|
||||
@@ -49,6 +52,7 @@ object MangaController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, mangaId, onlineFetch ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.future {
|
||||
future {
|
||||
Manga.getManga(mangaId, onlineFetch)
|
||||
@@ -73,6 +77,7 @@ object MangaController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, mangaId, onlineFetch ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.future {
|
||||
future {
|
||||
Manga.getMangaFull(mangaId, onlineFetch)
|
||||
@@ -96,6 +101,7 @@ object MangaController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, mangaId ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.future {
|
||||
future { Manga.getMangaThumbnail(mangaId) }
|
||||
.thenApply {
|
||||
@@ -123,6 +129,7 @@ object MangaController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, mangaId ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.future {
|
||||
future { Library.addMangaToLibrary(mangaId) }
|
||||
.thenApply { ctx.status(HttpStatus.OK) }
|
||||
@@ -145,6 +152,7 @@ object MangaController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, mangaId ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.future {
|
||||
future { Library.removeMangaFromLibrary(mangaId) }
|
||||
.thenApply { ctx.status(HttpStatus.OK) }
|
||||
@@ -167,6 +175,7 @@ object MangaController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, mangaId ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.json(CategoryManga.getMangaCategories(mangaId))
|
||||
},
|
||||
withResults = {
|
||||
@@ -186,6 +195,7 @@ object MangaController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, mangaId, categoryId ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
CategoryManga.addMangaToCategory(mangaId, categoryId)
|
||||
ctx.status(200)
|
||||
},
|
||||
@@ -206,6 +216,7 @@ object MangaController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, mangaId, categoryId ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
CategoryManga.removeMangaFromCategory(mangaId, categoryId)
|
||||
ctx.status(200)
|
||||
},
|
||||
@@ -227,6 +238,7 @@ object MangaController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, mangaId, key, value ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
Manga.modifyMangaMeta(mangaId, key, value)
|
||||
ctx.status(200)
|
||||
},
|
||||
@@ -252,6 +264,7 @@ object MangaController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, mangaId, onlineFetch ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.future {
|
||||
future { Chapter.getChapterList(mangaId, onlineFetch) }
|
||||
.thenApply { ctx.json(it) }
|
||||
@@ -275,6 +288,7 @@ object MangaController {
|
||||
body<Chapter.MangaChapterBatchEditInput>()
|
||||
},
|
||||
behaviorOf = { ctx, mangaId ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
val input = json.decodeFromString<Chapter.MangaChapterBatchEditInput>(ctx.body())
|
||||
Chapter.modifyChapters(input, mangaId)
|
||||
},
|
||||
@@ -294,6 +308,7 @@ object MangaController {
|
||||
body<Chapter.ChapterBatchEditInput>()
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
val input = json.decodeFromString<Chapter.ChapterBatchEditInput>(ctx.body())
|
||||
Chapter.modifyChapters(
|
||||
Chapter.MangaChapterBatchEditInput(
|
||||
@@ -320,6 +335,7 @@ object MangaController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, mangaId, chapterIndex ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.future {
|
||||
future {
|
||||
var chapter = getChapterDownloadReadyByIndex(chapterIndex, mangaId)
|
||||
@@ -368,6 +384,7 @@ object MangaController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, mangaId, chapterIndex, read, bookmarked, markPrevRead, lastPageRead ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
val chapterId = Chapter.modifyChapter(mangaId, chapterIndex, read, bookmarked, markPrevRead, lastPageRead)
|
||||
|
||||
// Sync with KoreaderSync when progress is updated
|
||||
@@ -394,6 +411,7 @@ object MangaController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, mangaId, chapterIndex ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
Chapter.deleteChapter(mangaId, chapterIndex)
|
||||
|
||||
ctx.status(200)
|
||||
@@ -418,6 +436,7 @@ object MangaController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, mangaId, chapterIndex, key, value ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
Chapter.modifyChapterMeta(mangaId, chapterIndex, key, value)
|
||||
|
||||
ctx.status(200)
|
||||
@@ -445,6 +464,7 @@ object MangaController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, mangaId, chapterIndex, index, updateProgress, format ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.future {
|
||||
future { Page.getPageImage(mangaId, chapterIndex, index, format, null) }
|
||||
.thenApply {
|
||||
@@ -480,6 +500,7 @@ object MangaController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, chapterId, markAsRead ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
if (ctx.method() == HandlerType.HEAD) {
|
||||
ctx.future {
|
||||
future { ChapterDownloadHelper.getCbzMetadataForDownload(chapterId) }
|
||||
|
||||
@@ -17,7 +17,10 @@ import suwayomi.tachidesk.manga.impl.Source
|
||||
import suwayomi.tachidesk.manga.impl.Source.SourcePreferenceChange
|
||||
import suwayomi.tachidesk.manga.model.dataclass.PagedMangaListDataClass
|
||||
import suwayomi.tachidesk.manga.model.dataclass.SourceDataClass
|
||||
import suwayomi.tachidesk.server.JavalinSetup.Attribute
|
||||
import suwayomi.tachidesk.server.JavalinSetup.future
|
||||
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
|
||||
import suwayomi.tachidesk.server.user.requireUser
|
||||
import suwayomi.tachidesk.server.util.handler
|
||||
import suwayomi.tachidesk.server.util.pathParam
|
||||
import suwayomi.tachidesk.server.util.queryParam
|
||||
@@ -35,6 +38,7 @@ object SourceController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.json(Source.getSourceList())
|
||||
},
|
||||
withResults = {
|
||||
@@ -53,6 +57,7 @@ object SourceController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, sourceId ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.json(Source.getSource(sourceId)!!)
|
||||
},
|
||||
withResults = {
|
||||
@@ -73,6 +78,7 @@ object SourceController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, sourceId, pageNum ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.future {
|
||||
future {
|
||||
MangaList.getMangaList(sourceId, pageNum, popular = true)
|
||||
@@ -96,6 +102,7 @@ object SourceController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, sourceId, pageNum ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.future {
|
||||
future {
|
||||
MangaList.getMangaList(sourceId, pageNum, popular = false)
|
||||
@@ -118,6 +125,7 @@ object SourceController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, sourceId ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.json(Source.getSourcePreferences(sourceId))
|
||||
},
|
||||
withResults = {
|
||||
@@ -137,6 +145,7 @@ object SourceController {
|
||||
body<SourcePreferenceChange>()
|
||||
},
|
||||
behaviorOf = { ctx, sourceId ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
val preferenceChange = ctx.bodyAsClass(SourcePreferenceChange::class.java)
|
||||
ctx.json(Source.setSourcePreference(sourceId, preferenceChange.position, preferenceChange.value))
|
||||
},
|
||||
@@ -157,6 +166,7 @@ object SourceController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, sourceId, reset ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.json(Search.getFilterList(sourceId, reset))
|
||||
},
|
||||
withResults = {
|
||||
@@ -179,6 +189,7 @@ object SourceController {
|
||||
body<Array<FilterChange>>()
|
||||
},
|
||||
behaviorOf = { ctx, sourceId ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
val filterChange =
|
||||
try {
|
||||
json.decodeFromString<List<FilterChange>>(ctx.body())
|
||||
@@ -206,6 +217,7 @@ object SourceController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, sourceId, searchTerm, pageNum ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.future {
|
||||
future { Search.sourceSearch(sourceId, searchTerm, pageNum) }
|
||||
.thenApply { ctx.json(it) }
|
||||
@@ -229,6 +241,7 @@ object SourceController {
|
||||
body<FilterData>()
|
||||
},
|
||||
behaviorOf = { ctx, sourceId, pageNum ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
val filter = json.decodeFromString<FilterData>(ctx.body())
|
||||
ctx.future {
|
||||
future { Search.sourceFilter(sourceId, pageNum, filter) }
|
||||
@@ -251,6 +264,7 @@ object SourceController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, searchTerm ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
// TODO
|
||||
ctx.json(Search.sourceGlobalSearch(searchTerm))
|
||||
},
|
||||
|
||||
@@ -12,7 +12,10 @@ import io.javalin.http.HttpStatus
|
||||
import kotlinx.serialization.json.Json
|
||||
import suwayomi.tachidesk.manga.impl.track.Track
|
||||
import suwayomi.tachidesk.manga.model.dataclass.TrackerDataClass
|
||||
import suwayomi.tachidesk.server.JavalinSetup.Attribute
|
||||
import suwayomi.tachidesk.server.JavalinSetup.future
|
||||
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
|
||||
import suwayomi.tachidesk.server.user.requireUser
|
||||
import suwayomi.tachidesk.server.util.handler
|
||||
import suwayomi.tachidesk.server.util.pathParam
|
||||
import suwayomi.tachidesk.server.util.queryParam
|
||||
@@ -33,6 +36,7 @@ object TrackController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.json(Track.getTrackerList())
|
||||
},
|
||||
withResults = {
|
||||
@@ -50,6 +54,7 @@ object TrackController {
|
||||
body<Track.LoginInput>()
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
val input = json.decodeFromString<Track.LoginInput>(ctx.body())
|
||||
logger.debug { "tracker login $input" }
|
||||
ctx.future {
|
||||
@@ -73,6 +78,7 @@ object TrackController {
|
||||
body<Track.LogoutInput>()
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
val input = json.decodeFromString<Track.LogoutInput>(ctx.body())
|
||||
logger.debug { "tracker logout $input" }
|
||||
ctx.future {
|
||||
@@ -96,6 +102,7 @@ object TrackController {
|
||||
body<Track.SearchInput>()
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
val input = json.decodeFromString<Track.SearchInput>(ctx.body())
|
||||
logger.debug { "tracker search $input" }
|
||||
ctx.future {
|
||||
@@ -122,6 +129,7 @@ object TrackController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, mangaId, trackerId, remoteId, private ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.future {
|
||||
future { Track.bind(mangaId, trackerId, remoteId.toLong(), private) }
|
||||
.thenApply { ctx.status(HttpStatus.OK) }
|
||||
@@ -142,6 +150,7 @@ object TrackController {
|
||||
body<Track.UpdateInput>()
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
val input = json.decodeFromString<Track.UpdateInput>(ctx.body())
|
||||
logger.debug { "tracker update $input" }
|
||||
ctx.future {
|
||||
@@ -164,6 +173,7 @@ object TrackController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, trackerId ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.future {
|
||||
future { Track.getTrackerThumbnail(trackerId) }
|
||||
.thenApply {
|
||||
|
||||
@@ -10,7 +10,10 @@ import suwayomi.tachidesk.manga.impl.update.UpdateStatus
|
||||
import suwayomi.tachidesk.manga.impl.update.UpdaterSocket
|
||||
import suwayomi.tachidesk.manga.model.dataclass.MangaChapterDataClass
|
||||
import suwayomi.tachidesk.manga.model.dataclass.PaginatedList
|
||||
import suwayomi.tachidesk.server.JavalinSetup.Attribute
|
||||
import suwayomi.tachidesk.server.JavalinSetup.future
|
||||
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
|
||||
import suwayomi.tachidesk.server.user.requireUser
|
||||
import suwayomi.tachidesk.server.util.formParam
|
||||
import suwayomi.tachidesk.server.util.handler
|
||||
import suwayomi.tachidesk.server.util.pathParam
|
||||
@@ -39,6 +42,7 @@ object UpdateController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, pageNum ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
ctx.future {
|
||||
future {
|
||||
Chapter.getRecentChapters(pageNum)
|
||||
@@ -66,6 +70,7 @@ object UpdateController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, categoryId ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
val updater = Injekt.get<IUpdater>()
|
||||
if (categoryId == null) {
|
||||
logger.info { "Adding Library to Update Queue" }
|
||||
@@ -96,6 +101,7 @@ object UpdateController {
|
||||
|
||||
fun categoryUpdateWS(ws: WsConfig) {
|
||||
ws.onConnect { ctx ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
UpdaterSocket.addClient(ctx)
|
||||
}
|
||||
ws.onMessage { ctx ->
|
||||
@@ -115,6 +121,7 @@ object UpdateController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
val updater = Injekt.get<IUpdater>()
|
||||
ctx.json(updater.statusDeprecated.value)
|
||||
},
|
||||
@@ -132,6 +139,7 @@ object UpdateController {
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.getAttribute(Attribute.TachideskUser).requireUser()
|
||||
val updater = Injekt.get<IUpdater>()
|
||||
logger.info { "Resetting Updater" }
|
||||
ctx.future {
|
||||
|
||||
Reference in New Issue
Block a user