Use graphql directive for auth handling (#1671)

This commit is contained in:
schroda
2025-09-29 17:24:19 +02:00
committed by GitHub
parent 5e48b05270
commit 5c79672d84
35 changed files with 297 additions and 555 deletions

View File

@@ -0,0 +1,23 @@
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
package suwayomi.tachidesk.graphql.directives
import com.expediagroup.graphql.generator.annotations.GraphQLDirective
import graphql.introspection.Introspection.DirectiveLocation
@GraphQLDirective(
name = "requireAuth",
description = "Requires user authentication",
locations = [
DirectiveLocation.FIELD_DEFINITION,
DirectiveLocation.OBJECT,
],
)
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class RequireAuth

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
package suwayomi.tachidesk.graphql.directives
import com.expediagroup.graphql.generator.directives.KotlinFieldDirectiveEnvironment
import com.expediagroup.graphql.generator.directives.KotlinSchemaDirectiveWiring
import graphql.schema.DataFetcher
import graphql.schema.DataFetchingEnvironmentImpl
import graphql.schema.GraphQLFieldDefinition
import suwayomi.tachidesk.graphql.server.getAttribute
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.user.requireUser
private const val USER_ID_PARAM = "userId"
class RequireAuthDirectiveWiring : KotlinSchemaDirectiveWiring {
override fun onField(environment: KotlinFieldDirectiveEnvironment): GraphQLFieldDefinition {
val originalDataFetcher = environment.getDataFetcher()
val authDataFetcher =
DataFetcher { env ->
val user = env.graphQlContext.getAttribute(Attribute.TachideskUser)
val userId = user.requireUser()
if (env.arguments.containsKey(USER_ID_PARAM)) {
throw Exception("\"$USER_ID_PARAM\" is a reserved parameter for RequireAuth")
}
// Create a new environment with userId added to arguments
val newArguments: MutableMap<String, Any> = env.arguments.toMutableMap()
newArguments[USER_ID_PARAM] = userId
val modifiedEnv =
DataFetchingEnvironmentImpl
.newDataFetchingEnvironment(env)
.arguments(newArguments)
.build()
originalDataFetcher.get(modifiedEnv)
}
environment.setDataFetcher(authDataFetcher)
return environment.element
}
}

View File

@@ -1,21 +1,17 @@
package suwayomi.tachidesk.graphql.mutations package suwayomi.tachidesk.graphql.mutations
import graphql.schema.DataFetchingEnvironment
import io.javalin.http.UploadedFile import io.javalin.http.UploadedFile
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.withTimeout import kotlinx.coroutines.withTimeout
import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.server.TemporaryFileStorage import suwayomi.tachidesk.graphql.server.TemporaryFileStorage
import suwayomi.tachidesk.graphql.server.getAttribute
import suwayomi.tachidesk.graphql.types.BackupRestoreStatus import suwayomi.tachidesk.graphql.types.BackupRestoreStatus
import suwayomi.tachidesk.graphql.types.toStatus import suwayomi.tachidesk.graphql.types.toStatus
import suwayomi.tachidesk.manga.impl.backup.BackupFlags import suwayomi.tachidesk.manga.impl.backup.BackupFlags
import suwayomi.tachidesk.manga.impl.backup.proto.ProtoBackupExport import suwayomi.tachidesk.manga.impl.backup.proto.ProtoBackupExport
import suwayomi.tachidesk.manga.impl.backup.proto.ProtoBackupImport import suwayomi.tachidesk.manga.impl.backup.proto.ProtoBackupImport
import suwayomi.tachidesk.manga.impl.backup.proto.models.Backup 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.future
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.seconds
@@ -31,11 +27,8 @@ class BackupMutation {
val status: BackupRestoreStatus?, val status: BackupRestoreStatus?,
) )
fun restoreBackup( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun restoreBackup(input: RestoreBackupInput): CompletableFuture<RestoreBackupPayload> {
input: RestoreBackupInput,
): CompletableFuture<RestoreBackupPayload> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, backup) = input val (clientMutationId, backup) = input
return future { return future {
@@ -66,11 +59,8 @@ class BackupMutation {
val url: String, val url: String,
) )
fun createBackup( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun createBackup(input: CreateBackupInput? = null): CreateBackupPayload {
input: CreateBackupInput? = null,
): CreateBackupPayload {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val filename = Backup.getFilename() val filename = Backup.getFilename()
val backup = val backup =

View File

@@ -1,7 +1,6 @@
package suwayomi.tachidesk.graphql.mutations package suwayomi.tachidesk.graphql.mutations
import graphql.execution.DataFetcherResult import graphql.execution.DataFetcherResult
import graphql.schema.DataFetchingEnvironment
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.SqlExpressionBuilder.inList import org.jetbrains.exposed.sql.SqlExpressionBuilder.inList
import org.jetbrains.exposed.sql.SqlExpressionBuilder.minus import org.jetbrains.exposed.sql.SqlExpressionBuilder.minus
@@ -13,7 +12,7 @@ import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.update import org.jetbrains.exposed.sql.update
import suwayomi.tachidesk.graphql.asDataFetcherResult import suwayomi.tachidesk.graphql.asDataFetcherResult
import suwayomi.tachidesk.graphql.server.getAttribute import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.types.CategoryMetaType import suwayomi.tachidesk.graphql.types.CategoryMetaType
import suwayomi.tachidesk.graphql.types.CategoryType import suwayomi.tachidesk.graphql.types.CategoryType
import suwayomi.tachidesk.graphql.types.MangaType import suwayomi.tachidesk.graphql.types.MangaType
@@ -25,9 +24,6 @@ import suwayomi.tachidesk.manga.model.table.CategoryMangaTable
import suwayomi.tachidesk.manga.model.table.CategoryMetaTable import suwayomi.tachidesk.manga.model.table.CategoryMetaTable
import suwayomi.tachidesk.manga.model.table.CategoryTable import suwayomi.tachidesk.manga.model.table.CategoryTable
import suwayomi.tachidesk.manga.model.table.MangaTable import suwayomi.tachidesk.manga.model.table.MangaTable
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
class CategoryMutation { class CategoryMutation {
data class SetCategoryMetaInput( data class SetCategoryMetaInput(
@@ -40,12 +36,9 @@ class CategoryMutation {
val meta: CategoryMetaType, val meta: CategoryMetaType,
) )
fun setCategoryMeta( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun setCategoryMeta(input: SetCategoryMetaInput): DataFetcherResult<SetCategoryMetaPayload?> =
input: SetCategoryMetaInput,
): DataFetcherResult<SetCategoryMetaPayload?> =
asDataFetcherResult { asDataFetcherResult {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, meta) = input val (clientMutationId, meta) = input
Category.modifyMeta(meta.categoryId, meta.key, meta.value) Category.modifyMeta(meta.categoryId, meta.key, meta.value)
@@ -65,12 +58,9 @@ class CategoryMutation {
val category: CategoryType, val category: CategoryType,
) )
fun deleteCategoryMeta( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun deleteCategoryMeta(input: DeleteCategoryMetaInput): DataFetcherResult<DeleteCategoryMetaPayload?> =
input: DeleteCategoryMetaInput,
): DataFetcherResult<DeleteCategoryMetaPayload?> =
asDataFetcherResult { asDataFetcherResult {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, categoryId, key) = input val (clientMutationId, categoryId, key) = input
val (meta, category) = val (meta, category) =
@@ -163,12 +153,9 @@ class CategoryMutation {
} }
} }
fun updateCategory( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun updateCategory(input: UpdateCategoryInput): DataFetcherResult<UpdateCategoryPayload?> =
input: UpdateCategoryInput,
): DataFetcherResult<UpdateCategoryPayload?> =
asDataFetcherResult { asDataFetcherResult {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, id, patch) = input val (clientMutationId, id, patch) = input
updateCategories(listOf(id), patch) updateCategories(listOf(id), patch)
@@ -184,12 +171,9 @@ class CategoryMutation {
) )
} }
fun updateCategories( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun updateCategories(input: UpdateCategoriesInput): DataFetcherResult<UpdateCategoriesPayload?> =
input: UpdateCategoriesInput,
): DataFetcherResult<UpdateCategoriesPayload?> =
asDataFetcherResult { asDataFetcherResult {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, ids, patch) = input val (clientMutationId, ids, patch) = input
updateCategories(ids, patch) updateCategories(ids, patch)
@@ -216,12 +200,9 @@ class CategoryMutation {
val position: Int, val position: Int,
) )
fun updateCategoryOrder( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun updateCategoryOrder(input: UpdateCategoryOrderInput): DataFetcherResult<UpdateCategoryOrderPayload?> =
input: UpdateCategoryOrderInput,
): DataFetcherResult<UpdateCategoryOrderPayload?> =
asDataFetcherResult { asDataFetcherResult {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, categoryId, position) = input val (clientMutationId, categoryId, position) = input
require(position > 0) { require(position > 0) {
"'order' must not be <= 0" "'order' must not be <= 0"
@@ -278,12 +259,9 @@ class CategoryMutation {
val category: CategoryType, val category: CategoryType,
) )
fun createCategory( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun createCategory(input: CreateCategoryInput): DataFetcherResult<CreateCategoryPayload?> =
input: CreateCategoryInput,
): DataFetcherResult<CreateCategoryPayload?> =
asDataFetcherResult { asDataFetcherResult {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, name, order, default, includeInUpdate, includeInDownload) = input val (clientMutationId, name, order, default, includeInUpdate, includeInDownload) = input
transaction { transaction {
require(CategoryTable.selectAll().where { CategoryTable.name eq input.name }.isEmpty()) { require(CategoryTable.selectAll().where { CategoryTable.name eq input.name }.isEmpty()) {
@@ -341,12 +319,9 @@ class CategoryMutation {
val mangas: List<MangaType>, val mangas: List<MangaType>,
) )
fun deleteCategory( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun deleteCategory(input: DeleteCategoryInput): DataFetcherResult<DeleteCategoryPayload?> {
input: DeleteCategoryInput,
): DataFetcherResult<DeleteCategoryPayload?> {
return asDataFetcherResult { return asDataFetcherResult {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, categoryId) = input val (clientMutationId, categoryId) = input
if (categoryId == 0) { // Don't delete default category if (categoryId == 0) { // Don't delete default category
return@asDataFetcherResult DeleteCategoryPayload( return@asDataFetcherResult DeleteCategoryPayload(
@@ -434,12 +409,9 @@ class CategoryMutation {
} }
} }
fun updateMangaCategories( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun updateMangaCategories(input: UpdateMangaCategoriesInput): DataFetcherResult<UpdateMangaCategoriesPayload?> =
input: UpdateMangaCategoriesInput,
): DataFetcherResult<UpdateMangaCategoriesPayload?> =
asDataFetcherResult { asDataFetcherResult {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, id, patch) = input val (clientMutationId, id, patch) = input
updateMangas(listOf(id), patch) updateMangas(listOf(id), patch)
@@ -455,12 +427,9 @@ class CategoryMutation {
) )
} }
fun updateMangasCategories( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun updateMangasCategories(input: UpdateMangasCategoriesInput): DataFetcherResult<UpdateMangasCategoriesPayload?> =
input: UpdateMangasCategoriesInput,
): DataFetcherResult<UpdateMangasCategoriesPayload?> =
asDataFetcherResult { asDataFetcherResult {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, ids, patch) = input val (clientMutationId, ids, patch) = input
updateMangas(ids, patch) updateMangas(ids, patch)

View File

@@ -1,7 +1,6 @@
package suwayomi.tachidesk.graphql.mutations package suwayomi.tachidesk.graphql.mutations
import graphql.execution.DataFetcherResult import graphql.execution.DataFetcherResult
import graphql.schema.DataFetchingEnvironment
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.jetbrains.exposed.dao.id.EntityID import org.jetbrains.exposed.dao.id.EntityID
@@ -13,7 +12,7 @@ import org.jetbrains.exposed.sql.statements.BatchUpdateStatement
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.update import org.jetbrains.exposed.sql.update
import suwayomi.tachidesk.graphql.asDataFetcherResult import suwayomi.tachidesk.graphql.asDataFetcherResult
import suwayomi.tachidesk.graphql.server.getAttribute import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.types.ChapterMetaType import suwayomi.tachidesk.graphql.types.ChapterMetaType
import suwayomi.tachidesk.graphql.types.ChapterType import suwayomi.tachidesk.graphql.types.ChapterType
import suwayomi.tachidesk.graphql.types.SyncConflictInfoType import suwayomi.tachidesk.graphql.types.SyncConflictInfoType
@@ -22,10 +21,7 @@ import suwayomi.tachidesk.manga.impl.chapter.getChapterDownloadReadyById
import suwayomi.tachidesk.manga.impl.sync.KoreaderSyncService import suwayomi.tachidesk.manga.impl.sync.KoreaderSyncService
import suwayomi.tachidesk.manga.model.table.ChapterMetaTable import suwayomi.tachidesk.manga.model.table.ChapterMetaTable
import suwayomi.tachidesk.manga.model.table.ChapterTable import suwayomi.tachidesk.manga.model.table.ChapterTable
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.future import suwayomi.tachidesk.server.JavalinSetup.future
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
import java.net.URLEncoder import java.net.URLEncoder
import java.time.Instant import java.time.Instant
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
@@ -117,12 +113,9 @@ class ChapterMutation {
} }
} }
fun updateChapter( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun updateChapter(input: UpdateChapterInput): DataFetcherResult<UpdateChapterPayload?> =
input: UpdateChapterInput,
): DataFetcherResult<UpdateChapterPayload?> =
asDataFetcherResult { asDataFetcherResult {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, id, patch) = input val (clientMutationId, id, patch) = input
updateChapters(listOf(id), patch) updateChapters(listOf(id), patch)
@@ -138,12 +131,9 @@ class ChapterMutation {
) )
} }
fun updateChapters( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun updateChapters(input: UpdateChaptersInput): DataFetcherResult<UpdateChaptersPayload?> =
input: UpdateChaptersInput,
): DataFetcherResult<UpdateChaptersPayload?> =
asDataFetcherResult { asDataFetcherResult {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, ids, patch) = input val (clientMutationId, ids, patch) = input
updateChapters(ids, patch) updateChapters(ids, patch)
@@ -169,11 +159,8 @@ class ChapterMutation {
val chapters: List<ChapterType>, val chapters: List<ChapterType>,
) )
fun fetchChapters( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun fetchChapters(input: FetchChaptersInput): CompletableFuture<DataFetcherResult<FetchChaptersPayload?>> {
input: FetchChaptersInput,
): CompletableFuture<DataFetcherResult<FetchChaptersPayload?>> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, mangaId) = input val (clientMutationId, mangaId) = input
return future { return future {
@@ -207,12 +194,9 @@ class ChapterMutation {
val meta: ChapterMetaType, val meta: ChapterMetaType,
) )
fun setChapterMeta( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun setChapterMeta(input: SetChapterMetaInput): DataFetcherResult<SetChapterMetaPayload?> =
input: SetChapterMetaInput,
): DataFetcherResult<SetChapterMetaPayload?> =
asDataFetcherResult { asDataFetcherResult {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, meta) = input val (clientMutationId, meta) = input
Chapter.modifyChapterMeta(meta.chapterId, meta.key, meta.value) Chapter.modifyChapterMeta(meta.chapterId, meta.key, meta.value)
@@ -232,12 +216,9 @@ class ChapterMutation {
val chapter: ChapterType, val chapter: ChapterType,
) )
fun deleteChapterMeta( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun deleteChapterMeta(input: DeleteChapterMetaInput): DataFetcherResult<DeleteChapterMetaPayload?> =
input: DeleteChapterMetaInput,
): DataFetcherResult<DeleteChapterMetaPayload?> =
asDataFetcherResult { asDataFetcherResult {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, chapterId, key) = input val (clientMutationId, chapterId, key) = input
val (meta, chapter) = val (meta, chapter) =
@@ -285,11 +266,8 @@ class ChapterMutation {
val syncConflict: SyncConflictInfoType?, val syncConflict: SyncConflictInfoType?,
) )
fun fetchChapterPages( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun fetchChapterPages(input: FetchChapterPagesInput): CompletableFuture<DataFetcherResult<FetchChapterPagesPayload?>> {
input: FetchChapterPagesInput,
): CompletableFuture<DataFetcherResult<FetchChapterPagesPayload?>> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, chapterId) = input val (clientMutationId, chapterId) = input
val paramsMap = input.toParams() val paramsMap = input.toParams()

View File

@@ -1,13 +1,12 @@
package suwayomi.tachidesk.graphql.mutations package suwayomi.tachidesk.graphql.mutations
import graphql.execution.DataFetcherResult import graphql.execution.DataFetcherResult
import graphql.schema.DataFetchingEnvironment
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.withTimeout import kotlinx.coroutines.withTimeout
import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import suwayomi.tachidesk.graphql.asDataFetcherResult import suwayomi.tachidesk.graphql.asDataFetcherResult
import suwayomi.tachidesk.graphql.server.getAttribute import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.types.ChapterType import suwayomi.tachidesk.graphql.types.ChapterType
import suwayomi.tachidesk.graphql.types.DownloadStatus import suwayomi.tachidesk.graphql.types.DownloadStatus
import suwayomi.tachidesk.manga.impl.Chapter import suwayomi.tachidesk.manga.impl.Chapter
@@ -15,9 +14,7 @@ import suwayomi.tachidesk.manga.impl.download.DownloadManager
import suwayomi.tachidesk.manga.impl.download.model.DownloadUpdateType.DEQUEUED import suwayomi.tachidesk.manga.impl.download.model.DownloadUpdateType.DEQUEUED
import suwayomi.tachidesk.manga.impl.download.model.Status import suwayomi.tachidesk.manga.impl.download.model.Status
import suwayomi.tachidesk.manga.model.table.ChapterTable import suwayomi.tachidesk.manga.model.table.ChapterTable
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.future import suwayomi.tachidesk.server.JavalinSetup.future
import suwayomi.tachidesk.server.user.requireUser
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.seconds
@@ -32,11 +29,8 @@ class DownloadMutation {
val chapters: List<ChapterType>, val chapters: List<ChapterType>,
) )
fun deleteDownloadedChapters( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun deleteDownloadedChapters(input: DeleteDownloadedChaptersInput): DataFetcherResult<DeleteDownloadedChaptersPayload?> {
input: DeleteDownloadedChaptersInput,
): DataFetcherResult<DeleteDownloadedChaptersPayload?> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, chapters) = input val (clientMutationId, chapters) = input
return asDataFetcherResult { return asDataFetcherResult {
@@ -65,11 +59,8 @@ class DownloadMutation {
val chapters: ChapterType, val chapters: ChapterType,
) )
fun deleteDownloadedChapter( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun deleteDownloadedChapter(input: DeleteDownloadedChapterInput): DataFetcherResult<DeleteDownloadedChapterPayload?> {
input: DeleteDownloadedChapterInput,
): DataFetcherResult<DeleteDownloadedChapterPayload?> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, chapter) = input val (clientMutationId, chapter) = input
return asDataFetcherResult { return asDataFetcherResult {
@@ -95,11 +86,10 @@ class DownloadMutation {
val downloadStatus: DownloadStatus, val downloadStatus: DownloadStatus,
) )
@RequireAuth
fun enqueueChapterDownloads( fun enqueueChapterDownloads(
dataFetchingEnvironment: DataFetchingEnvironment,
input: EnqueueChapterDownloadsInput, input: EnqueueChapterDownloadsInput,
): CompletableFuture<DataFetcherResult<EnqueueChapterDownloadsPayload?>> { ): CompletableFuture<DataFetcherResult<EnqueueChapterDownloadsPayload?>> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, chapters) = input val (clientMutationId, chapters) = input
return future { return future {
@@ -132,11 +122,8 @@ class DownloadMutation {
val downloadStatus: DownloadStatus, val downloadStatus: DownloadStatus,
) )
fun enqueueChapterDownload( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun enqueueChapterDownload(input: EnqueueChapterDownloadInput): CompletableFuture<DataFetcherResult<EnqueueChapterDownloadPayload?>> {
input: EnqueueChapterDownloadInput,
): CompletableFuture<DataFetcherResult<EnqueueChapterDownloadPayload?>> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, chapter) = input val (clientMutationId, chapter) = input
return future { return future {
@@ -168,11 +155,10 @@ class DownloadMutation {
val downloadStatus: DownloadStatus, val downloadStatus: DownloadStatus,
) )
@RequireAuth
fun dequeueChapterDownloads( fun dequeueChapterDownloads(
dataFetchingEnvironment: DataFetchingEnvironment,
input: DequeueChapterDownloadsInput, input: DequeueChapterDownloadsInput,
): CompletableFuture<DataFetcherResult<DequeueChapterDownloadsPayload?>> { ): CompletableFuture<DataFetcherResult<DequeueChapterDownloadsPayload?>> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, chapters) = input val (clientMutationId, chapters) = input
return future { return future {
@@ -207,11 +193,8 @@ class DownloadMutation {
val downloadStatus: DownloadStatus, val downloadStatus: DownloadStatus,
) )
fun dequeueChapterDownload( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun dequeueChapterDownload(input: DequeueChapterDownloadInput): CompletableFuture<DataFetcherResult<DequeueChapterDownloadPayload?>> {
input: DequeueChapterDownloadInput,
): CompletableFuture<DataFetcherResult<DequeueChapterDownloadPayload?>> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, chapter) = input val (clientMutationId, chapter) = input
return future { return future {
@@ -245,13 +228,10 @@ class DownloadMutation {
val downloadStatus: DownloadStatus, val downloadStatus: DownloadStatus,
) )
fun startDownloader( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun startDownloader(input: StartDownloaderInput): CompletableFuture<DataFetcherResult<StartDownloaderPayload?>> =
input: StartDownloaderInput,
): CompletableFuture<DataFetcherResult<StartDownloaderPayload?>> =
future { future {
asDataFetcherResult { asDataFetcherResult {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
DownloadManager.start() DownloadManager.start()
StartDownloaderPayload( StartDownloaderPayload(
@@ -277,13 +257,10 @@ class DownloadMutation {
val downloadStatus: DownloadStatus, val downloadStatus: DownloadStatus,
) )
fun stopDownloader( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun stopDownloader(input: StopDownloaderInput): CompletableFuture<DataFetcherResult<StopDownloaderPayload?>> =
input: StopDownloaderInput,
): CompletableFuture<DataFetcherResult<StopDownloaderPayload?>> =
future { future {
asDataFetcherResult { asDataFetcherResult {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
DownloadManager.stop() DownloadManager.stop()
StopDownloaderPayload( StopDownloaderPayload(
@@ -309,13 +286,10 @@ class DownloadMutation {
val downloadStatus: DownloadStatus, val downloadStatus: DownloadStatus,
) )
fun clearDownloader( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun clearDownloader(input: ClearDownloaderInput): CompletableFuture<DataFetcherResult<ClearDownloaderPayload?>> =
input: ClearDownloaderInput,
): CompletableFuture<DataFetcherResult<ClearDownloaderPayload?>> =
future { future {
asDataFetcherResult { asDataFetcherResult {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
DownloadManager.clear() DownloadManager.clear()
ClearDownloaderPayload( ClearDownloaderPayload(
@@ -343,11 +317,8 @@ class DownloadMutation {
val downloadStatus: DownloadStatus, val downloadStatus: DownloadStatus,
) )
fun reorderChapterDownload( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun reorderChapterDownload(input: ReorderChapterDownloadInput): CompletableFuture<DataFetcherResult<ReorderChapterDownloadPayload?>> {
input: ReorderChapterDownloadInput,
): CompletableFuture<DataFetcherResult<ReorderChapterDownloadPayload?>> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, chapter, to) = input val (clientMutationId, chapter, to) = input
return future { return future {

View File

@@ -2,20 +2,16 @@ package suwayomi.tachidesk.graphql.mutations
import eu.kanade.tachiyomi.source.local.LocalSource import eu.kanade.tachiyomi.source.local.LocalSource
import graphql.execution.DataFetcherResult import graphql.execution.DataFetcherResult
import graphql.schema.DataFetchingEnvironment
import io.javalin.http.UploadedFile import io.javalin.http.UploadedFile
import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import suwayomi.tachidesk.graphql.asDataFetcherResult import suwayomi.tachidesk.graphql.asDataFetcherResult
import suwayomi.tachidesk.graphql.server.getAttribute import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.types.ExtensionType import suwayomi.tachidesk.graphql.types.ExtensionType
import suwayomi.tachidesk.manga.impl.extension.Extension import suwayomi.tachidesk.manga.impl.extension.Extension
import suwayomi.tachidesk.manga.impl.extension.ExtensionsList import suwayomi.tachidesk.manga.impl.extension.ExtensionsList
import suwayomi.tachidesk.manga.model.table.ExtensionTable import suwayomi.tachidesk.manga.model.table.ExtensionTable
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.future import suwayomi.tachidesk.server.JavalinSetup.future
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
class ExtensionMutation { class ExtensionMutation {
@@ -78,11 +74,8 @@ class ExtensionMutation {
} }
} }
fun updateExtension( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun updateExtension(input: UpdateExtensionInput): CompletableFuture<DataFetcherResult<UpdateExtensionPayload?>> {
input: UpdateExtensionInput,
): CompletableFuture<DataFetcherResult<UpdateExtensionPayload?>> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, id, patch) = input val (clientMutationId, id, patch) = input
return future { return future {
@@ -106,11 +99,8 @@ class ExtensionMutation {
} }
} }
fun updateExtensions( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun updateExtensions(input: UpdateExtensionsInput): CompletableFuture<DataFetcherResult<UpdateExtensionsPayload?>> {
input: UpdateExtensionsInput,
): CompletableFuture<DataFetcherResult<UpdateExtensionsPayload?>> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, ids, patch) = input val (clientMutationId, ids, patch) = input
return future { return future {
@@ -142,11 +132,8 @@ class ExtensionMutation {
val extensions: List<ExtensionType>, val extensions: List<ExtensionType>,
) )
fun fetchExtensions( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun fetchExtensions(input: FetchExtensionsInput): CompletableFuture<DataFetcherResult<FetchExtensionsPayload?>> {
input: FetchExtensionsInput,
): CompletableFuture<DataFetcherResult<FetchExtensionsPayload?>> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId) = input val (clientMutationId) = input
return future { return future {
@@ -179,11 +166,10 @@ class ExtensionMutation {
val extension: ExtensionType, val extension: ExtensionType,
) )
@RequireAuth
fun installExternalExtension( fun installExternalExtension(
dataFetchingEnvironment: DataFetchingEnvironment,
input: InstallExternalExtensionInput, input: InstallExternalExtensionInput,
): CompletableFuture<DataFetcherResult<InstallExternalExtensionPayload?>> { ): CompletableFuture<DataFetcherResult<InstallExternalExtensionPayload?>> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, extensionFile) = input val (clientMutationId, extensionFile) = input
return future { return future {

View File

@@ -1,12 +1,8 @@
package suwayomi.tachidesk.graphql.mutations package suwayomi.tachidesk.graphql.mutations
import graphql.schema.DataFetchingEnvironment import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.server.getAttribute
import suwayomi.tachidesk.manga.impl.util.storage.ImageResponse import suwayomi.tachidesk.manga.impl.util.storage.ImageResponse
import suwayomi.tachidesk.server.ApplicationDirs import suwayomi.tachidesk.server.ApplicationDirs
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
private val applicationDirs: ApplicationDirs by injectLazy() private val applicationDirs: ApplicationDirs by injectLazy()
@@ -26,11 +22,8 @@ class ImageMutation {
val cachedPages: Boolean?, val cachedPages: Boolean?,
) )
fun clearCachedImages( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun clearCachedImages(input: ClearCachedImagesInput): ClearCachedImagesPayload {
input: ClearCachedImagesInput,
): ClearCachedImagesPayload {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, downloadedThumbnails, cachedThumbnails, cachedPages) = input val (clientMutationId, downloadedThumbnails, cachedThumbnails, cachedPages) = input
val downloadedThumbnailsResult = val downloadedThumbnailsResult =

View File

@@ -1,20 +1,16 @@
package suwayomi.tachidesk.graphql.mutations package suwayomi.tachidesk.graphql.mutations
import graphql.execution.DataFetcherResult import graphql.execution.DataFetcherResult
import graphql.schema.DataFetchingEnvironment
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.withTimeout import kotlinx.coroutines.withTimeout
import suwayomi.tachidesk.graphql.asDataFetcherResult import suwayomi.tachidesk.graphql.asDataFetcherResult
import suwayomi.tachidesk.graphql.server.getAttribute import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.types.UpdateState.DOWNLOADING import suwayomi.tachidesk.graphql.types.UpdateState.DOWNLOADING
import suwayomi.tachidesk.graphql.types.UpdateState.ERROR import suwayomi.tachidesk.graphql.types.UpdateState.ERROR
import suwayomi.tachidesk.graphql.types.UpdateState.IDLE import suwayomi.tachidesk.graphql.types.UpdateState.IDLE
import suwayomi.tachidesk.graphql.types.WebUIFlavor import suwayomi.tachidesk.graphql.types.WebUIFlavor
import suwayomi.tachidesk.graphql.types.WebUIUpdateStatus import suwayomi.tachidesk.graphql.types.WebUIUpdateStatus
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.future import suwayomi.tachidesk.server.JavalinSetup.future
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
import suwayomi.tachidesk.server.util.WebInterfaceManager import suwayomi.tachidesk.server.util.WebInterfaceManager
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.seconds
@@ -29,13 +25,10 @@ class InfoMutation {
val updateStatus: WebUIUpdateStatus, val updateStatus: WebUIUpdateStatus,
) )
fun updateWebUI( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun updateWebUI(input: WebUIUpdateInput): CompletableFuture<DataFetcherResult<WebUIUpdatePayload?>> {
input: WebUIUpdateInput,
): CompletableFuture<DataFetcherResult<WebUIUpdatePayload?>> {
return future { return future {
asDataFetcherResult { asDataFetcherResult {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
withTimeout(30.seconds) { withTimeout(30.seconds) {
if (WebInterfaceManager.status.value.state === DOWNLOADING) { if (WebInterfaceManager.status.value.state === DOWNLOADING) {
return@withTimeout WebUIUpdatePayload(input.clientMutationId, WebInterfaceManager.status.value) return@withTimeout WebUIUpdatePayload(input.clientMutationId, WebInterfaceManager.status.value)
@@ -68,10 +61,10 @@ class InfoMutation {
} }
} }
fun resetWebUIUpdateStatus(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<DataFetcherResult<WebUIUpdateStatus?>> = @RequireAuth
fun resetWebUIUpdateStatus(): CompletableFuture<DataFetcherResult<WebUIUpdateStatus?>> =
future { future {
asDataFetcherResult { asDataFetcherResult {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
withTimeout(30.seconds) { withTimeout(30.seconds) {
val isUpdateFinished = WebInterfaceManager.status.value.state != DOWNLOADING val isUpdateFinished = WebInterfaceManager.status.value.state != DOWNLOADING
if (!isUpdateFinished) { if (!isUpdateFinished) {

View File

@@ -1,12 +1,11 @@
package suwayomi.tachidesk.graphql.mutations package suwayomi.tachidesk.graphql.mutations
import graphql.execution.DataFetcherResult import graphql.execution.DataFetcherResult
import graphql.schema.DataFetchingEnvironment
import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.update import org.jetbrains.exposed.sql.update
import suwayomi.tachidesk.graphql.asDataFetcherResult import suwayomi.tachidesk.graphql.asDataFetcherResult
import suwayomi.tachidesk.graphql.server.getAttribute import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.types.ChapterType import suwayomi.tachidesk.graphql.types.ChapterType
import suwayomi.tachidesk.graphql.types.KoSyncConnectPayload import suwayomi.tachidesk.graphql.types.KoSyncConnectPayload
import suwayomi.tachidesk.graphql.types.LogoutKoSyncAccountPayload import suwayomi.tachidesk.graphql.types.LogoutKoSyncAccountPayload
@@ -14,9 +13,7 @@ import suwayomi.tachidesk.graphql.types.SettingsType
import suwayomi.tachidesk.graphql.types.SyncConflictInfoType import suwayomi.tachidesk.graphql.types.SyncConflictInfoType
import suwayomi.tachidesk.manga.impl.sync.KoreaderSyncService import suwayomi.tachidesk.manga.impl.sync.KoreaderSyncService
import suwayomi.tachidesk.manga.model.table.ChapterTable import suwayomi.tachidesk.manga.model.table.ChapterTable
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.future import suwayomi.tachidesk.server.JavalinSetup.future
import suwayomi.tachidesk.server.user.requireUser
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
class KoreaderSyncMutation { class KoreaderSyncMutation {
@@ -26,12 +23,9 @@ class KoreaderSyncMutation {
val password: String, val password: String,
) )
fun connectKoSyncAccount( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun connectKoSyncAccount(input: ConnectKoSyncAccountInput): CompletableFuture<KoSyncConnectPayload> =
input: ConnectKoSyncAccountInput,
): CompletableFuture<KoSyncConnectPayload> =
future { future {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val result = KoreaderSyncService.connect(input.username, input.password) val result = KoreaderSyncService.connect(input.username, input.password)
KoSyncConnectPayload( KoSyncConnectPayload(
@@ -47,12 +41,9 @@ class KoreaderSyncMutation {
val clientMutationId: String? = null, val clientMutationId: String? = null,
) )
fun logoutKoSyncAccount( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun logoutKoSyncAccount(input: LogoutKoSyncAccountInput): CompletableFuture<LogoutKoSyncAccountPayload> =
input: LogoutKoSyncAccountInput,
): CompletableFuture<LogoutKoSyncAccountPayload> =
future { future {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
KoreaderSyncService.logout() KoreaderSyncService.logout()
LogoutKoSyncAccountPayload( LogoutKoSyncAccountPayload(
clientMutationId = input.clientMutationId, clientMutationId = input.clientMutationId,
@@ -72,14 +63,10 @@ class KoreaderSyncMutation {
val chapter: ChapterType?, val chapter: ChapterType?,
) )
fun pushKoSyncProgress( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun pushKoSyncProgress(input: PushKoSyncProgressInput): CompletableFuture<DataFetcherResult<PushKoSyncProgressPayload?>> =
input: PushKoSyncProgressInput,
): CompletableFuture<DataFetcherResult<PushKoSyncProgressPayload?>> =
future { future {
asDataFetcherResult { asDataFetcherResult {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
KoreaderSyncService.pushProgress(input.chapterId) KoreaderSyncService.pushProgress(input.chapterId)
val chapter = val chapter =
@@ -110,14 +97,10 @@ class KoreaderSyncMutation {
val syncConflict: SyncConflictInfoType?, val syncConflict: SyncConflictInfoType?,
) )
fun pullKoSyncProgress( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun pullKoSyncProgress(input: PullKoSyncProgressInput): CompletableFuture<DataFetcherResult<PullKoSyncProgressPayload?>> =
input: PullKoSyncProgressInput,
): CompletableFuture<DataFetcherResult<PullKoSyncProgressPayload?>> =
future { future {
asDataFetcherResult { asDataFetcherResult {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val syncResult = KoreaderSyncService.checkAndPullProgress(input.chapterId) val syncResult = KoreaderSyncService.checkAndPullProgress(input.chapterId)
var syncConflictInfo: SyncConflictInfoType? = null var syncConflictInfo: SyncConflictInfoType? = null

View File

@@ -1,7 +1,6 @@
package suwayomi.tachidesk.graphql.mutations package suwayomi.tachidesk.graphql.mutations
import graphql.execution.DataFetcherResult import graphql.execution.DataFetcherResult
import graphql.schema.DataFetchingEnvironment
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.and import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.deleteWhere import org.jetbrains.exposed.sql.deleteWhere
@@ -9,7 +8,7 @@ import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.update import org.jetbrains.exposed.sql.update
import suwayomi.tachidesk.graphql.asDataFetcherResult import suwayomi.tachidesk.graphql.asDataFetcherResult
import suwayomi.tachidesk.graphql.server.getAttribute import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.types.MangaMetaType import suwayomi.tachidesk.graphql.types.MangaMetaType
import suwayomi.tachidesk.graphql.types.MangaType import suwayomi.tachidesk.graphql.types.MangaType
import suwayomi.tachidesk.manga.impl.Library import suwayomi.tachidesk.manga.impl.Library
@@ -18,10 +17,7 @@ import suwayomi.tachidesk.manga.impl.update.IUpdater
import suwayomi.tachidesk.manga.model.table.MangaMetaTable import suwayomi.tachidesk.manga.model.table.MangaMetaTable
import suwayomi.tachidesk.manga.model.table.MangaTable import suwayomi.tachidesk.manga.model.table.MangaTable
import suwayomi.tachidesk.manga.model.table.toDataClass import suwayomi.tachidesk.manga.model.table.toDataClass
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.future import suwayomi.tachidesk.server.JavalinSetup.future
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.time.Instant import java.time.Instant
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
@@ -95,11 +91,8 @@ class MangaMutation {
} }
} }
fun updateManga( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun updateManga(input: UpdateMangaInput): CompletableFuture<DataFetcherResult<UpdateMangaPayload?>> {
input: UpdateMangaInput,
): CompletableFuture<DataFetcherResult<UpdateMangaPayload?>> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, id, patch) = input val (clientMutationId, id, patch) = input
return future { return future {
@@ -119,11 +112,8 @@ class MangaMutation {
} }
} }
fun updateMangas( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun updateMangas(input: UpdateMangasInput): CompletableFuture<DataFetcherResult<UpdateMangasPayload?>> {
input: UpdateMangasInput,
): CompletableFuture<DataFetcherResult<UpdateMangasPayload?>> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, ids, patch) = input val (clientMutationId, ids, patch) = input
return future { return future {
@@ -153,11 +143,8 @@ class MangaMutation {
val manga: MangaType, val manga: MangaType,
) )
fun fetchManga( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun fetchManga(input: FetchMangaInput): CompletableFuture<DataFetcherResult<FetchMangaPayload?>> {
input: FetchMangaInput,
): CompletableFuture<DataFetcherResult<FetchMangaPayload?>> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, id) = input val (clientMutationId, id) = input
return future { return future {
@@ -186,11 +173,8 @@ class MangaMutation {
val meta: MangaMetaType, val meta: MangaMetaType,
) )
fun setMangaMeta( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun setMangaMeta(input: SetMangaMetaInput): DataFetcherResult<SetMangaMetaPayload?> {
input: SetMangaMetaInput,
): DataFetcherResult<SetMangaMetaPayload?> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, meta) = input val (clientMutationId, meta) = input
return asDataFetcherResult { return asDataFetcherResult {
@@ -212,11 +196,8 @@ class MangaMutation {
val manga: MangaType, val manga: MangaType,
) )
fun deleteMangaMeta( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun deleteMangaMeta(input: DeleteMangaMetaInput): DataFetcherResult<DeleteMangaMetaPayload?> {
input: DeleteMangaMetaInput,
): DataFetcherResult<DeleteMangaMetaPayload?> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, mangaId, key) = input val (clientMutationId, mangaId, key) = input
return asDataFetcherResult { return asDataFetcherResult {

View File

@@ -1,7 +1,6 @@
package suwayomi.tachidesk.graphql.mutations package suwayomi.tachidesk.graphql.mutations
import graphql.execution.DataFetcherResult import graphql.execution.DataFetcherResult
import graphql.schema.DataFetchingEnvironment
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.deleteWhere import org.jetbrains.exposed.sql.deleteWhere
import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.selectAll
@@ -9,11 +8,8 @@ import org.jetbrains.exposed.sql.transactions.transaction
import suwayomi.tachidesk.global.impl.GlobalMeta import suwayomi.tachidesk.global.impl.GlobalMeta
import suwayomi.tachidesk.global.model.table.GlobalMetaTable import suwayomi.tachidesk.global.model.table.GlobalMetaTable
import suwayomi.tachidesk.graphql.asDataFetcherResult import suwayomi.tachidesk.graphql.asDataFetcherResult
import suwayomi.tachidesk.graphql.server.getAttribute import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.types.GlobalMetaType import suwayomi.tachidesk.graphql.types.GlobalMetaType
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
class MetaMutation { class MetaMutation {
data class SetGlobalMetaInput( data class SetGlobalMetaInput(
@@ -26,11 +22,8 @@ class MetaMutation {
val meta: GlobalMetaType, val meta: GlobalMetaType,
) )
fun setGlobalMeta( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun setGlobalMeta(input: SetGlobalMetaInput): DataFetcherResult<SetGlobalMetaPayload?> {
input: SetGlobalMetaInput,
): DataFetcherResult<SetGlobalMetaPayload?> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, meta) = input val (clientMutationId, meta) = input
return asDataFetcherResult { return asDataFetcherResult {
@@ -50,11 +43,8 @@ class MetaMutation {
val meta: GlobalMetaType?, val meta: GlobalMetaType?,
) )
fun deleteGlobalMeta( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun deleteGlobalMeta(input: DeleteGlobalMetaInput): DataFetcherResult<DeleteGlobalMetaPayload?> {
input: DeleteGlobalMetaInput,
): DataFetcherResult<DeleteGlobalMetaPayload?> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, key) = input val (clientMutationId, key) = input
return asDataFetcherResult { return asDataFetcherResult {

View File

@@ -1,17 +1,14 @@
package suwayomi.tachidesk.graphql.mutations package suwayomi.tachidesk.graphql.mutations
import com.expediagroup.graphql.generator.annotations.GraphQLIgnore import com.expediagroup.graphql.generator.annotations.GraphQLIgnore
import graphql.schema.DataFetchingEnvironment import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.server.getAttribute
import suwayomi.tachidesk.graphql.types.PartialSettingsType import suwayomi.tachidesk.graphql.types.PartialSettingsType
import suwayomi.tachidesk.graphql.types.Settings import suwayomi.tachidesk.graphql.types.Settings
import suwayomi.tachidesk.graphql.types.SettingsType import suwayomi.tachidesk.graphql.types.SettingsType
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.SERVER_CONFIG_MODULE_NAME import suwayomi.tachidesk.server.SERVER_CONFIG_MODULE_NAME
import suwayomi.tachidesk.server.ServerConfig import suwayomi.tachidesk.server.ServerConfig
import suwayomi.tachidesk.server.settings.SettingsUpdater import suwayomi.tachidesk.server.settings.SettingsUpdater
import suwayomi.tachidesk.server.settings.SettingsValidator import suwayomi.tachidesk.server.settings.SettingsValidator
import suwayomi.tachidesk.server.user.requireUser
import xyz.nulldev.ts.config.GlobalConfigManager import xyz.nulldev.ts.config.GlobalConfigManager
class SettingsMutation { class SettingsMutation {
@@ -35,11 +32,8 @@ class SettingsMutation {
SettingsUpdater.updateAll(settings) SettingsUpdater.updateAll(settings)
} }
fun setSettings( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun setSettings(input: SetSettingsInput): SetSettingsPayload {
input: SetSettingsInput,
): SetSettingsPayload {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, settings) = input val (clientMutationId, settings) = input
updateSettings(settings) updateSettings(settings)
@@ -56,11 +50,8 @@ class SettingsMutation {
val settings: SettingsType, val settings: SettingsType,
) )
fun resetSettings( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun resetSettings(input: ResetSettingsInput): ResetSettingsPayload {
input: ResetSettingsInput,
): ResetSettingsPayload {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId) = input val (clientMutationId) = input
GlobalConfigManager.resetUserConfig() GlobalConfigManager.resetUserConfig()

View File

@@ -6,14 +6,13 @@ import androidx.preference.ListPreference
import androidx.preference.MultiSelectListPreference import androidx.preference.MultiSelectListPreference
import androidx.preference.SwitchPreferenceCompat import androidx.preference.SwitchPreferenceCompat
import graphql.execution.DataFetcherResult import graphql.execution.DataFetcherResult
import graphql.schema.DataFetchingEnvironment
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.and import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.deleteWhere import org.jetbrains.exposed.sql.deleteWhere
import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import suwayomi.tachidesk.graphql.asDataFetcherResult import suwayomi.tachidesk.graphql.asDataFetcherResult
import suwayomi.tachidesk.graphql.server.getAttribute import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.types.FilterChange import suwayomi.tachidesk.graphql.types.FilterChange
import suwayomi.tachidesk.graphql.types.MangaType import suwayomi.tachidesk.graphql.types.MangaType
import suwayomi.tachidesk.graphql.types.Preference import suwayomi.tachidesk.graphql.types.Preference
@@ -27,10 +26,7 @@ import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource
import suwayomi.tachidesk.manga.model.table.MangaTable import suwayomi.tachidesk.manga.model.table.MangaTable
import suwayomi.tachidesk.manga.model.table.SourceMetaTable import suwayomi.tachidesk.manga.model.table.SourceMetaTable
import suwayomi.tachidesk.manga.model.table.SourceTable import suwayomi.tachidesk.manga.model.table.SourceTable
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.future import suwayomi.tachidesk.server.JavalinSetup.future
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
class SourceMutation { class SourceMutation {
@@ -44,11 +40,8 @@ class SourceMutation {
val meta: SourceMetaType, val meta: SourceMetaType,
) )
fun setSourceMeta( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun setSourceMeta(input: SetSourceMetaInput): DataFetcherResult<SetSourceMetaPayload?> {
input: SetSourceMetaInput,
): DataFetcherResult<SetSourceMetaPayload?> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, meta) = input val (clientMutationId, meta) = input
return asDataFetcherResult { return asDataFetcherResult {
@@ -70,11 +63,8 @@ class SourceMutation {
val source: SourceType?, val source: SourceType?,
) )
fun deleteSourceMeta( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun deleteSourceMeta(input: DeleteSourceMetaInput): DataFetcherResult<DeleteSourceMetaPayload?> {
input: DeleteSourceMetaInput,
): DataFetcherResult<DeleteSourceMetaPayload?> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, sourceId, key) = input val (clientMutationId, sourceId, key) = input
return asDataFetcherResult { return asDataFetcherResult {
@@ -129,11 +119,8 @@ class SourceMutation {
val hasNextPage: Boolean, val hasNextPage: Boolean,
) )
fun fetchSourceManga( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun fetchSourceManga(input: FetchSourceMangaInput): CompletableFuture<DataFetcherResult<FetchSourceMangaPayload?>> {
input: FetchSourceMangaInput,
): CompletableFuture<DataFetcherResult<FetchSourceMangaPayload?>> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, sourceId, type, page, query, filters) = input val (clientMutationId, sourceId, type, page, query, filters) = input
return future { return future {
@@ -199,11 +186,8 @@ class SourceMutation {
val source: SourceType, val source: SourceType,
) )
fun updateSourcePreference( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun updateSourcePreference(input: UpdateSourcePreferenceInput): DataFetcherResult<UpdateSourcePreferencePayload?> {
input: UpdateSourcePreferenceInput,
): DataFetcherResult<UpdateSourcePreferencePayload?> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, sourceId, change) = input val (clientMutationId, sourceId, change) = input
return asDataFetcherResult { return asDataFetcherResult {

View File

@@ -3,21 +3,17 @@ package suwayomi.tachidesk.graphql.mutations
import com.expediagroup.graphql.generator.annotations.GraphQLDeprecated import com.expediagroup.graphql.generator.annotations.GraphQLDeprecated
import com.expediagroup.graphql.generator.annotations.GraphQLDescription import com.expediagroup.graphql.generator.annotations.GraphQLDescription
import graphql.execution.DataFetcherResult import graphql.execution.DataFetcherResult
import graphql.schema.DataFetchingEnvironment
import org.jetbrains.exposed.sql.and import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import suwayomi.tachidesk.graphql.asDataFetcherResult import suwayomi.tachidesk.graphql.asDataFetcherResult
import suwayomi.tachidesk.graphql.server.getAttribute import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.types.TrackRecordType import suwayomi.tachidesk.graphql.types.TrackRecordType
import suwayomi.tachidesk.graphql.types.TrackerType import suwayomi.tachidesk.graphql.types.TrackerType
import suwayomi.tachidesk.manga.impl.track.Track import suwayomi.tachidesk.manga.impl.track.Track
import suwayomi.tachidesk.manga.impl.track.tracker.TrackerManager import suwayomi.tachidesk.manga.impl.track.tracker.TrackerManager
import suwayomi.tachidesk.manga.model.table.TrackRecordTable import suwayomi.tachidesk.manga.model.table.TrackRecordTable
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.future import suwayomi.tachidesk.server.JavalinSetup.future
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
class TrackMutation { class TrackMutation {
@@ -33,11 +29,8 @@ class TrackMutation {
val tracker: TrackerType, val tracker: TrackerType,
) )
fun loginTrackerOAuth( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun loginTrackerOAuth(input: LoginTrackerOAuthInput): CompletableFuture<LoginTrackerOAuthPayload> {
input: LoginTrackerOAuthInput,
): CompletableFuture<LoginTrackerOAuthPayload> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val tracker = val tracker =
requireNotNull(TrackerManager.getTracker(input.trackerId)) { requireNotNull(TrackerManager.getTracker(input.trackerId)) {
"Could not find tracker" "Could not find tracker"
@@ -66,11 +59,8 @@ class TrackMutation {
val tracker: TrackerType, val tracker: TrackerType,
) )
fun loginTrackerCredentials( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun loginTrackerCredentials(input: LoginTrackerCredentialsInput): CompletableFuture<LoginTrackerCredentialsPayload> {
input: LoginTrackerCredentialsInput,
): CompletableFuture<LoginTrackerCredentialsPayload> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val tracker = val tracker =
requireNotNull(TrackerManager.getTracker(input.trackerId)) { requireNotNull(TrackerManager.getTracker(input.trackerId)) {
"Could not find tracker" "Could not find tracker"
@@ -97,11 +87,8 @@ class TrackMutation {
val tracker: TrackerType, val tracker: TrackerType,
) )
fun logoutTracker( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun logoutTracker(input: LogoutTrackerInput): CompletableFuture<LogoutTrackerPayload> {
input: LogoutTrackerInput,
): CompletableFuture<LogoutTrackerPayload> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val tracker = val tracker =
requireNotNull(TrackerManager.getTracker(input.trackerId)) { requireNotNull(TrackerManager.getTracker(input.trackerId)) {
"Could not find tracker" "Could not find tracker"
@@ -134,11 +121,8 @@ class TrackMutation {
val trackRecord: TrackRecordType, val trackRecord: TrackRecordType,
) )
fun bindTrack( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun bindTrack(input: BindTrackInput): CompletableFuture<BindTrackPayload> {
input: BindTrackInput,
): CompletableFuture<BindTrackPayload> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, mangaId, trackerId, remoteId, private) = input val (clientMutationId, mangaId, trackerId, remoteId, private) = input
return future { return future {
@@ -173,11 +157,8 @@ class TrackMutation {
val trackRecord: TrackRecordType, val trackRecord: TrackRecordType,
) )
fun fetchTrack( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun fetchTrack(input: FetchTrackInput): CompletableFuture<FetchTrackPayload> {
input: FetchTrackInput,
): CompletableFuture<FetchTrackPayload> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, recordId) = input val (clientMutationId, recordId) = input
return future { return future {
@@ -209,11 +190,8 @@ class TrackMutation {
val trackRecord: TrackRecordType?, val trackRecord: TrackRecordType?,
) )
fun unbindTrack( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun unbindTrack(input: UnbindTrackInput): CompletableFuture<UnbindTrackPayload> {
input: UnbindTrackInput,
): CompletableFuture<UnbindTrackPayload> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, recordId, deleteRemoteTrack) = input val (clientMutationId, recordId, deleteRemoteTrack) = input
return future { return future {
@@ -243,11 +221,8 @@ class TrackMutation {
val trackRecords: List<TrackRecordType>, val trackRecords: List<TrackRecordType>,
) )
fun trackProgress( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun trackProgress(input: TrackProgressInput): CompletableFuture<DataFetcherResult<TrackProgressPayload?>> {
input: TrackProgressInput,
): CompletableFuture<DataFetcherResult<TrackProgressPayload?>> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (clientMutationId, mangaId) = input val (clientMutationId, mangaId) = input
return future { return future {
@@ -289,12 +264,9 @@ class TrackMutation {
val trackRecord: TrackRecordType?, val trackRecord: TrackRecordType?,
) )
fun updateTrack( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun updateTrack(input: UpdateTrackInput): CompletableFuture<UpdateTrackPayload> =
input: UpdateTrackInput,
): CompletableFuture<UpdateTrackPayload> =
future { future {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
Track.update( Track.update(
Track.UpdateInput( Track.UpdateInput(
input.recordId, input.recordId,

View File

@@ -1,19 +1,15 @@
package suwayomi.tachidesk.graphql.mutations package suwayomi.tachidesk.graphql.mutations
import graphql.execution.DataFetcherResult import graphql.execution.DataFetcherResult
import graphql.schema.DataFetchingEnvironment
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.withTimeout import kotlinx.coroutines.withTimeout
import suwayomi.tachidesk.graphql.asDataFetcherResult import suwayomi.tachidesk.graphql.asDataFetcherResult
import suwayomi.tachidesk.graphql.server.getAttribute import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.types.LibraryUpdateStatus import suwayomi.tachidesk.graphql.types.LibraryUpdateStatus
import suwayomi.tachidesk.graphql.types.UpdateStatus import suwayomi.tachidesk.graphql.types.UpdateStatus
import suwayomi.tachidesk.manga.impl.Category import suwayomi.tachidesk.manga.impl.Category
import suwayomi.tachidesk.manga.impl.update.IUpdater import suwayomi.tachidesk.manga.impl.update.IUpdater
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.future import suwayomi.tachidesk.server.JavalinSetup.future
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.seconds
@@ -31,11 +27,8 @@ class UpdateMutation {
val updateStatus: LibraryUpdateStatus, val updateStatus: LibraryUpdateStatus,
) )
fun updateLibrary( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun updateLibrary(input: UpdateLibraryInput): CompletableFuture<DataFetcherResult<UpdateLibraryPayload?>> {
input: UpdateLibraryInput,
): CompletableFuture<DataFetcherResult<UpdateLibraryPayload?>> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
updater.addCategoriesToUpdateQueue( updater.addCategoriesToUpdateQueue(
Category.getCategoryList().filter { input.categories?.contains(it.id) ?: true }, Category.getCategoryList().filter { input.categories?.contains(it.id) ?: true },
clear = true, clear = true,
@@ -66,12 +59,9 @@ class UpdateMutation {
val updateStatus: UpdateStatus, val updateStatus: UpdateStatus,
) )
fun updateLibraryManga( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun updateLibraryManga(input: UpdateLibraryMangaInput): CompletableFuture<DataFetcherResult<UpdateLibraryMangaPayload?>> {
input: UpdateLibraryMangaInput,
): CompletableFuture<DataFetcherResult<UpdateLibraryMangaPayload?>> {
updateLibrary( updateLibrary(
dataFetchingEnvironment,
UpdateLibraryInput( UpdateLibraryInput(
clientMutationId = input.clientMutationId, clientMutationId = input.clientMutationId,
categories = null, categories = null,
@@ -101,12 +91,9 @@ class UpdateMutation {
val updateStatus: UpdateStatus, val updateStatus: UpdateStatus,
) )
fun updateCategoryManga( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun updateCategoryManga(input: UpdateCategoryMangaInput): CompletableFuture<DataFetcherResult<UpdateCategoryMangaPayload?>> {
input: UpdateCategoryMangaInput,
): CompletableFuture<DataFetcherResult<UpdateCategoryMangaPayload?>> {
updateLibrary( updateLibrary(
dataFetchingEnvironment,
UpdateLibraryInput( UpdateLibraryInput(
clientMutationId = input.clientMutationId, clientMutationId = input.clientMutationId,
categories = input.categories, categories = input.categories,
@@ -134,11 +121,8 @@ class UpdateMutation {
val clientMutationId: String?, val clientMutationId: String?,
) )
fun updateStop( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun updateStop(input: UpdateStopInput): UpdateStopPayload {
input: UpdateStopInput,
): UpdateStopPayload {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
updater.reset() updater.reset()
return UpdateStopPayload(input.clientMutationId) return UpdateStopPayload(input.clientMutationId)
} }

View File

@@ -2,9 +2,9 @@ package suwayomi.tachidesk.graphql.mutations
import graphql.schema.DataFetchingEnvironment import graphql.schema.DataFetchingEnvironment
import suwayomi.tachidesk.global.impl.util.Jwt import suwayomi.tachidesk.global.impl.util.Jwt
import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.server.getAttribute import suwayomi.tachidesk.graphql.server.getAttribute
import suwayomi.tachidesk.server.JavalinSetup.Attribute import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.serverConfig import suwayomi.tachidesk.server.serverConfig
import suwayomi.tachidesk.server.user.UserType import suwayomi.tachidesk.server.user.UserType

View File

@@ -1,15 +1,11 @@
package suwayomi.tachidesk.graphql.queries package suwayomi.tachidesk.graphql.queries
import graphql.schema.DataFetchingEnvironment
import io.javalin.http.UploadedFile import io.javalin.http.UploadedFile
import suwayomi.tachidesk.graphql.server.getAttribute import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.types.BackupRestoreStatus import suwayomi.tachidesk.graphql.types.BackupRestoreStatus
import suwayomi.tachidesk.graphql.types.toStatus import suwayomi.tachidesk.graphql.types.toStatus
import suwayomi.tachidesk.manga.impl.backup.proto.ProtoBackupImport import suwayomi.tachidesk.manga.impl.backup.proto.ProtoBackupImport
import suwayomi.tachidesk.manga.impl.backup.proto.ProtoBackupValidator import suwayomi.tachidesk.manga.impl.backup.proto.ProtoBackupValidator
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
class BackupQuery { class BackupQuery {
data class ValidateBackupInput( data class ValidateBackupInput(
@@ -30,11 +26,8 @@ class BackupQuery {
val missingTrackers: List<ValidateBackupTracker>, val missingTrackers: List<ValidateBackupTracker>,
) )
fun validateBackup( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun validateBackup(input: ValidateBackupInput): ValidateBackupResult {
input: ValidateBackupInput,
): ValidateBackupResult {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val result = ProtoBackupValidator.validate(input.backup.content()) val result = ProtoBackupValidator.validate(input.backup.content())
return ValidateBackupResult( return ValidateBackupResult(
result.missingSourceIds.map { ValidateBackupSource(it.first, it.second) }, result.missingSourceIds.map { ValidateBackupSource(it.first, it.second) },
@@ -42,11 +35,6 @@ class BackupQuery {
) )
} }
fun restoreStatus( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun restoreStatus(id: String): BackupRestoreStatus? = ProtoBackupImport.getRestoreState(id)?.toStatus()
id: String,
): BackupRestoreStatus? {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
return ProtoBackupImport.getRestoreState(id)?.toStatus()
}
} }

View File

@@ -17,6 +17,7 @@ import org.jetbrains.exposed.sql.SqlExpressionBuilder.greater
import org.jetbrains.exposed.sql.SqlExpressionBuilder.less import org.jetbrains.exposed.sql.SqlExpressionBuilder.less
import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.queries.filter.BooleanFilter import suwayomi.tachidesk.graphql.queries.filter.BooleanFilter
import suwayomi.tachidesk.graphql.queries.filter.Filter import suwayomi.tachidesk.graphql.queries.filter.Filter
import suwayomi.tachidesk.graphql.queries.filter.HasGetOp import suwayomi.tachidesk.graphql.queries.filter.HasGetOp
@@ -27,7 +28,6 @@ import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompare
import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareEntity import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareEntity
import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareString import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareString
import suwayomi.tachidesk.graphql.queries.filter.applyOps import suwayomi.tachidesk.graphql.queries.filter.applyOps
import suwayomi.tachidesk.graphql.server.getAttribute
import suwayomi.tachidesk.graphql.server.primitives.Cursor import suwayomi.tachidesk.graphql.server.primitives.Cursor
import suwayomi.tachidesk.graphql.server.primitives.Order import suwayomi.tachidesk.graphql.server.primitives.Order
import suwayomi.tachidesk.graphql.server.primitives.OrderBy import suwayomi.tachidesk.graphql.server.primitives.OrderBy
@@ -40,19 +40,14 @@ import suwayomi.tachidesk.graphql.server.primitives.maybeSwap
import suwayomi.tachidesk.graphql.types.CategoryNodeList import suwayomi.tachidesk.graphql.types.CategoryNodeList
import suwayomi.tachidesk.graphql.types.CategoryType import suwayomi.tachidesk.graphql.types.CategoryType
import suwayomi.tachidesk.manga.model.table.CategoryTable import suwayomi.tachidesk.manga.model.table.CategoryTable
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
class CategoryQuery { class CategoryQuery {
@RequireAuth
fun category( fun category(
dataFetchingEnvironment: DataFetchingEnvironment, dataFetchingEnvironment: DataFetchingEnvironment,
id: Int, id: Int,
): CompletableFuture<CategoryType> { ): CompletableFuture<CategoryType> = dataFetchingEnvironment.getValueFromDataLoader("CategoryDataLoader", id)
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
return dataFetchingEnvironment.getValueFromDataLoader("CategoryDataLoader", id)
}
enum class CategoryOrderBy( enum class CategoryOrderBy(
override val column: Column<*>, override val column: Column<*>,
@@ -127,8 +122,8 @@ class CategoryQuery {
) )
} }
@RequireAuth
fun categories( fun categories(
dataFetchingEnvironment: DataFetchingEnvironment,
condition: CategoryCondition? = null, condition: CategoryCondition? = null,
filter: CategoryFilter? = null, filter: CategoryFilter? = null,
@GraphQLDeprecated( @GraphQLDeprecated(
@@ -148,7 +143,6 @@ class CategoryQuery {
last: Int? = null, last: Int? = null,
offset: Int? = null, offset: Int? = null,
): CategoryNodeList { ): CategoryNodeList {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val queryResults = val queryResults =
transaction { transaction {
val res = CategoryTable.selectAll() val res = CategoryTable.selectAll()

View File

@@ -18,6 +18,7 @@ import org.jetbrains.exposed.sql.SqlExpressionBuilder.less
import org.jetbrains.exposed.sql.andWhere import org.jetbrains.exposed.sql.andWhere
import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.queries.filter.BooleanFilter import suwayomi.tachidesk.graphql.queries.filter.BooleanFilter
import suwayomi.tachidesk.graphql.queries.filter.Filter import suwayomi.tachidesk.graphql.queries.filter.Filter
import suwayomi.tachidesk.graphql.queries.filter.FloatFilter import suwayomi.tachidesk.graphql.queries.filter.FloatFilter
@@ -30,7 +31,6 @@ import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompare
import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareEntity import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareEntity
import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareString import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareString
import suwayomi.tachidesk.graphql.queries.filter.applyOps import suwayomi.tachidesk.graphql.queries.filter.applyOps
import suwayomi.tachidesk.graphql.server.getAttribute
import suwayomi.tachidesk.graphql.server.primitives.Cursor import suwayomi.tachidesk.graphql.server.primitives.Cursor
import suwayomi.tachidesk.graphql.server.primitives.Order import suwayomi.tachidesk.graphql.server.primitives.Order
import suwayomi.tachidesk.graphql.server.primitives.OrderBy import suwayomi.tachidesk.graphql.server.primitives.OrderBy
@@ -44,9 +44,6 @@ import suwayomi.tachidesk.graphql.types.ChapterNodeList
import suwayomi.tachidesk.graphql.types.ChapterType import suwayomi.tachidesk.graphql.types.ChapterType
import suwayomi.tachidesk.manga.model.table.ChapterTable import suwayomi.tachidesk.manga.model.table.ChapterTable
import suwayomi.tachidesk.manga.model.table.MangaTable import suwayomi.tachidesk.manga.model.table.MangaTable
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
/** /**
@@ -55,6 +52,7 @@ import java.util.concurrent.CompletableFuture
* - Get page list? * - Get page list?
*/ */
class ChapterQuery { class ChapterQuery {
@RequireAuth
fun chapter( fun chapter(
dataFetchingEnvironment: DataFetchingEnvironment, dataFetchingEnvironment: DataFetchingEnvironment,
id: Int, id: Int,
@@ -200,8 +198,8 @@ class ChapterQuery {
fun getLibraryOp() = andFilterWithCompare(MangaTable.inLibrary, inLibrary) fun getLibraryOp() = andFilterWithCompare(MangaTable.inLibrary, inLibrary)
} }
@RequireAuth
fun chapters( fun chapters(
dataFetchingEnvironment: DataFetchingEnvironment,
condition: ChapterCondition? = null, condition: ChapterCondition? = null,
filter: ChapterFilter? = null, filter: ChapterFilter? = null,
@GraphQLDeprecated( @GraphQLDeprecated(
@@ -221,7 +219,6 @@ class ChapterQuery {
last: Int? = null, last: Int? = null,
offset: Int? = null, offset: Int? = null,
): ChapterNodeList { ): ChapterNodeList {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val queryResults = val queryResults =
transaction { transaction {
val res = ChapterTable.selectAll() val res = ChapterTable.selectAll()

View File

@@ -1,19 +1,15 @@
package suwayomi.tachidesk.graphql.queries package suwayomi.tachidesk.graphql.queries
import graphql.schema.DataFetchingEnvironment import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.server.getAttribute
import suwayomi.tachidesk.graphql.types.DownloadStatus import suwayomi.tachidesk.graphql.types.DownloadStatus
import suwayomi.tachidesk.manga.impl.download.DownloadManager import suwayomi.tachidesk.manga.impl.download.DownloadManager
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.future import suwayomi.tachidesk.server.JavalinSetup.future
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
class DownloadQuery { class DownloadQuery {
fun downloadStatus(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<DownloadStatus> = @RequireAuth
fun downloadStatus(): CompletableFuture<DownloadStatus> =
future { future {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
DownloadStatus(DownloadManager.getStatus()) DownloadStatus(DownloadManager.getStatus())
} }
} }

View File

@@ -19,6 +19,7 @@ import org.jetbrains.exposed.sql.SqlExpressionBuilder.less
import org.jetbrains.exposed.sql.SqlExpressionBuilder.neq import org.jetbrains.exposed.sql.SqlExpressionBuilder.neq
import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.queries.filter.BooleanFilter import suwayomi.tachidesk.graphql.queries.filter.BooleanFilter
import suwayomi.tachidesk.graphql.queries.filter.Filter import suwayomi.tachidesk.graphql.queries.filter.Filter
import suwayomi.tachidesk.graphql.queries.filter.HasGetOp import suwayomi.tachidesk.graphql.queries.filter.HasGetOp
@@ -28,7 +29,6 @@ import suwayomi.tachidesk.graphql.queries.filter.StringFilter
import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompare import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompare
import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareString import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareString
import suwayomi.tachidesk.graphql.queries.filter.applyOps import suwayomi.tachidesk.graphql.queries.filter.applyOps
import suwayomi.tachidesk.graphql.server.getAttribute
import suwayomi.tachidesk.graphql.server.primitives.Cursor import suwayomi.tachidesk.graphql.server.primitives.Cursor
import suwayomi.tachidesk.graphql.server.primitives.Order import suwayomi.tachidesk.graphql.server.primitives.Order
import suwayomi.tachidesk.graphql.server.primitives.OrderBy import suwayomi.tachidesk.graphql.server.primitives.OrderBy
@@ -41,19 +41,14 @@ import suwayomi.tachidesk.graphql.server.primitives.maybeSwap
import suwayomi.tachidesk.graphql.types.ExtensionNodeList import suwayomi.tachidesk.graphql.types.ExtensionNodeList
import suwayomi.tachidesk.graphql.types.ExtensionType import suwayomi.tachidesk.graphql.types.ExtensionType
import suwayomi.tachidesk.manga.model.table.ExtensionTable import suwayomi.tachidesk.manga.model.table.ExtensionTable
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
class ExtensionQuery { class ExtensionQuery {
@RequireAuth
fun extension( fun extension(
dataFetchingEnvironment: DataFetchingEnvironment, dataFetchingEnvironment: DataFetchingEnvironment,
pkgName: String, pkgName: String,
): CompletableFuture<ExtensionType> { ): CompletableFuture<ExtensionType> = dataFetchingEnvironment.getValueFromDataLoader("ExtensionDataLoader", pkgName)
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
return dataFetchingEnvironment.getValueFromDataLoader("ExtensionDataLoader", pkgName)
}
enum class ExtensionOrderBy( enum class ExtensionOrderBy(
override val column: Column<*>, override val column: Column<*>,
@@ -159,8 +154,8 @@ class ExtensionQuery {
) )
} }
@RequireAuth
fun extensions( fun extensions(
dataFetchingEnvironment: DataFetchingEnvironment,
condition: ExtensionCondition? = null, condition: ExtensionCondition? = null,
filter: ExtensionFilter? = null, filter: ExtensionFilter? = null,
@GraphQLDeprecated( @GraphQLDeprecated(
@@ -180,7 +175,6 @@ class ExtensionQuery {
last: Int? = null, last: Int? = null,
offset: Int? = null, offset: Int? = null,
): ExtensionNodeList { ): ExtensionNodeList {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val queryResults = val queryResults =
transaction { transaction {
val res = ExtensionTable.selectAll() val res = ExtensionTable.selectAll()

View File

@@ -1,19 +1,15 @@
package suwayomi.tachidesk.graphql.queries package suwayomi.tachidesk.graphql.queries
import com.expediagroup.graphql.generator.annotations.GraphQLDeprecated import com.expediagroup.graphql.generator.annotations.GraphQLDeprecated
import graphql.schema.DataFetchingEnvironment
import suwayomi.tachidesk.global.impl.AppUpdate import suwayomi.tachidesk.global.impl.AppUpdate
import suwayomi.tachidesk.graphql.server.getAttribute import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.types.AboutWebUI import suwayomi.tachidesk.graphql.types.AboutWebUI
import suwayomi.tachidesk.graphql.types.WebUIFlavor import suwayomi.tachidesk.graphql.types.WebUIFlavor
import suwayomi.tachidesk.graphql.types.WebUIUpdateCheck import suwayomi.tachidesk.graphql.types.WebUIUpdateCheck
import suwayomi.tachidesk.graphql.types.WebUIUpdateStatus import suwayomi.tachidesk.graphql.types.WebUIUpdateStatus
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.future import suwayomi.tachidesk.server.JavalinSetup.future
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.generated.BuildConfig import suwayomi.tachidesk.server.generated.BuildConfig
import suwayomi.tachidesk.server.serverConfig import suwayomi.tachidesk.server.serverConfig
import suwayomi.tachidesk.server.user.requireUser
import suwayomi.tachidesk.server.util.WebInterfaceManager import suwayomi.tachidesk.server.util.WebInterfaceManager
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
@@ -47,9 +43,9 @@ class InfoQuery {
val url: String, val url: String,
) )
fun checkForServerUpdates(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<List<CheckForServerUpdatesPayload>> = @RequireAuth
fun checkForServerUpdates(): CompletableFuture<List<CheckForServerUpdatesPayload>> =
future { future {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
AppUpdate.checkUpdate().map { AppUpdate.checkUpdate().map {
CheckForServerUpdatesPayload( CheckForServerUpdatesPayload(
channel = it.channel, channel = it.channel,
@@ -59,15 +55,15 @@ class InfoQuery {
} }
} }
fun aboutWebUI(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<AboutWebUI> = @RequireAuth
fun aboutWebUI(): CompletableFuture<AboutWebUI> =
future { future {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
WebInterfaceManager.getAboutInfo() WebInterfaceManager.getAboutInfo()
} }
fun checkForWebUIUpdate(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<WebUIUpdateCheck> = @RequireAuth
fun checkForWebUIUpdate(): CompletableFuture<WebUIUpdateCheck> =
future { future {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (version, updateAvailable) = WebInterfaceManager.isUpdateAvailable(WebUIFlavor.current, raiseError = true) val (version, updateAvailable) = WebInterfaceManager.isUpdateAvailable(WebUIFlavor.current, raiseError = true)
WebUIUpdateCheck( WebUIUpdateCheck(
channel = serverConfig.webUIChannel.value, channel = serverConfig.webUIChannel.value,
@@ -76,8 +72,6 @@ class InfoQuery {
) )
} }
fun getWebUIUpdateStatus(dataFetchingEnvironment: DataFetchingEnvironment): WebUIUpdateStatus { @RequireAuth
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser() fun getWebUIUpdateStatus(): WebUIUpdateStatus = WebInterfaceManager.status.value
return WebInterfaceManager.status.value
}
} }

View File

@@ -1,19 +1,15 @@
package suwayomi.tachidesk.graphql.queries package suwayomi.tachidesk.graphql.queries
import graphql.schema.DataFetchingEnvironment import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.server.getAttribute
import suwayomi.tachidesk.graphql.types.KoSyncStatusPayload import suwayomi.tachidesk.graphql.types.KoSyncStatusPayload
import suwayomi.tachidesk.manga.impl.sync.KoreaderSyncService import suwayomi.tachidesk.manga.impl.sync.KoreaderSyncService
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.future import suwayomi.tachidesk.server.JavalinSetup.future
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
class KoreaderSyncQuery { class KoreaderSyncQuery {
fun koSyncStatus(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<KoSyncStatusPayload> = @RequireAuth
fun koSyncStatus(): CompletableFuture<KoSyncStatusPayload> =
future { future {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
KoreaderSyncService.getStatus() KoreaderSyncService.getStatus()
} }
} }

View File

@@ -16,6 +16,7 @@ import org.jetbrains.exposed.sql.SortOrder
import org.jetbrains.exposed.sql.SqlExpressionBuilder.greater import org.jetbrains.exposed.sql.SqlExpressionBuilder.greater
import org.jetbrains.exposed.sql.SqlExpressionBuilder.less import org.jetbrains.exposed.sql.SqlExpressionBuilder.less
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.queries.filter.BooleanFilter import suwayomi.tachidesk.graphql.queries.filter.BooleanFilter
import suwayomi.tachidesk.graphql.queries.filter.ComparableScalarFilter import suwayomi.tachidesk.graphql.queries.filter.ComparableScalarFilter
import suwayomi.tachidesk.graphql.queries.filter.Filter import suwayomi.tachidesk.graphql.queries.filter.Filter
@@ -28,7 +29,6 @@ import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompare
import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareEntity import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareEntity
import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareString import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareString
import suwayomi.tachidesk.graphql.queries.filter.applyOps import suwayomi.tachidesk.graphql.queries.filter.applyOps
import suwayomi.tachidesk.graphql.server.getAttribute
import suwayomi.tachidesk.graphql.server.primitives.Cursor import suwayomi.tachidesk.graphql.server.primitives.Cursor
import suwayomi.tachidesk.graphql.server.primitives.Order import suwayomi.tachidesk.graphql.server.primitives.Order
import suwayomi.tachidesk.graphql.server.primitives.OrderBy import suwayomi.tachidesk.graphql.server.primitives.OrderBy
@@ -43,19 +43,14 @@ import suwayomi.tachidesk.graphql.types.MangaType
import suwayomi.tachidesk.manga.model.table.CategoryMangaTable import suwayomi.tachidesk.manga.model.table.CategoryMangaTable
import suwayomi.tachidesk.manga.model.table.MangaStatus import suwayomi.tachidesk.manga.model.table.MangaStatus
import suwayomi.tachidesk.manga.model.table.MangaTable import suwayomi.tachidesk.manga.model.table.MangaTable
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
class MangaQuery { class MangaQuery {
@RequireAuth
fun manga( fun manga(
dataFetchingEnvironment: DataFetchingEnvironment, dataFetchingEnvironment: DataFetchingEnvironment,
id: Int, id: Int,
): CompletableFuture<MangaType> { ): CompletableFuture<MangaType> = dataFetchingEnvironment.getValueFromDataLoader("MangaDataLoader", id)
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
return dataFetchingEnvironment.getValueFromDataLoader("MangaDataLoader", id)
}
enum class MangaOrderBy( enum class MangaOrderBy(
override val column: Column<*>, override val column: Column<*>,
@@ -222,8 +217,8 @@ class MangaQuery {
) )
} }
@RequireAuth
fun mangas( fun mangas(
dataFetchingEnvironment: DataFetchingEnvironment,
condition: MangaCondition? = null, condition: MangaCondition? = null,
filter: MangaFilter? = null, filter: MangaFilter? = null,
@GraphQLDeprecated( @GraphQLDeprecated(
@@ -243,7 +238,6 @@ class MangaQuery {
last: Int? = null, last: Int? = null,
offset: Int? = null, offset: Int? = null,
): MangaNodeList { ): MangaNodeList {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val queryResults = val queryResults =
transaction { transaction {
val res = val res =

View File

@@ -18,13 +18,13 @@ import org.jetbrains.exposed.sql.SqlExpressionBuilder.less
import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import suwayomi.tachidesk.global.model.table.GlobalMetaTable import suwayomi.tachidesk.global.model.table.GlobalMetaTable
import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.queries.filter.Filter import suwayomi.tachidesk.graphql.queries.filter.Filter
import suwayomi.tachidesk.graphql.queries.filter.HasGetOp import suwayomi.tachidesk.graphql.queries.filter.HasGetOp
import suwayomi.tachidesk.graphql.queries.filter.OpAnd import suwayomi.tachidesk.graphql.queries.filter.OpAnd
import suwayomi.tachidesk.graphql.queries.filter.StringFilter import suwayomi.tachidesk.graphql.queries.filter.StringFilter
import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareString import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareString
import suwayomi.tachidesk.graphql.queries.filter.applyOps import suwayomi.tachidesk.graphql.queries.filter.applyOps
import suwayomi.tachidesk.graphql.server.getAttribute
import suwayomi.tachidesk.graphql.server.primitives.Cursor import suwayomi.tachidesk.graphql.server.primitives.Cursor
import suwayomi.tachidesk.graphql.server.primitives.Order import suwayomi.tachidesk.graphql.server.primitives.Order
import suwayomi.tachidesk.graphql.server.primitives.OrderBy import suwayomi.tachidesk.graphql.server.primitives.OrderBy
@@ -36,19 +36,14 @@ import suwayomi.tachidesk.graphql.server.primitives.lessNotUnique
import suwayomi.tachidesk.graphql.server.primitives.maybeSwap import suwayomi.tachidesk.graphql.server.primitives.maybeSwap
import suwayomi.tachidesk.graphql.types.GlobalMetaNodeList import suwayomi.tachidesk.graphql.types.GlobalMetaNodeList
import suwayomi.tachidesk.graphql.types.GlobalMetaType import suwayomi.tachidesk.graphql.types.GlobalMetaType
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
class MetaQuery { class MetaQuery {
@RequireAuth
fun meta( fun meta(
dataFetchingEnvironment: DataFetchingEnvironment, dataFetchingEnvironment: DataFetchingEnvironment,
key: String, key: String,
): CompletableFuture<GlobalMetaType> { ): CompletableFuture<GlobalMetaType> = dataFetchingEnvironment.getValueFromDataLoader("GlobalMetaDataLoader", key)
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
return dataFetchingEnvironment.getValueFromDataLoader("GlobalMetaDataLoader", key)
}
enum class MetaOrderBy( enum class MetaOrderBy(
override val column: Column<*>, override val column: Column<*>,
@@ -111,8 +106,8 @@ class MetaQuery {
) )
} }
@RequireAuth
fun metas( fun metas(
dataFetchingEnvironment: DataFetchingEnvironment,
condition: MetaCondition? = null, condition: MetaCondition? = null,
filter: MetaFilter? = null, filter: MetaFilter? = null,
@GraphQLDeprecated( @GraphQLDeprecated(
@@ -132,7 +127,6 @@ class MetaQuery {
last: Int? = null, last: Int? = null,
offset: Int? = null, offset: Int? = null,
): GlobalMetaNodeList { ): GlobalMetaNodeList {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val queryResults = val queryResults =
transaction { transaction {
val res = GlobalMetaTable.selectAll() val res = GlobalMetaTable.selectAll()

View File

@@ -1,15 +1,9 @@
package suwayomi.tachidesk.graphql.queries package suwayomi.tachidesk.graphql.queries
import graphql.schema.DataFetchingEnvironment import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.server.getAttribute
import suwayomi.tachidesk.graphql.types.SettingsType import suwayomi.tachidesk.graphql.types.SettingsType
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
class SettingsQuery { class SettingsQuery {
fun settings(dataFetchingEnvironment: DataFetchingEnvironment): SettingsType { @RequireAuth
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser() fun settings(): SettingsType = SettingsType()
return SettingsType()
}
} }

View File

@@ -17,6 +17,7 @@ import org.jetbrains.exposed.sql.SqlExpressionBuilder.greater
import org.jetbrains.exposed.sql.SqlExpressionBuilder.less import org.jetbrains.exposed.sql.SqlExpressionBuilder.less
import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.queries.filter.BooleanFilter import suwayomi.tachidesk.graphql.queries.filter.BooleanFilter
import suwayomi.tachidesk.graphql.queries.filter.Filter import suwayomi.tachidesk.graphql.queries.filter.Filter
import suwayomi.tachidesk.graphql.queries.filter.HasGetOp import suwayomi.tachidesk.graphql.queries.filter.HasGetOp
@@ -27,7 +28,6 @@ import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompare
import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareEntity import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareEntity
import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareString import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareString
import suwayomi.tachidesk.graphql.queries.filter.applyOps import suwayomi.tachidesk.graphql.queries.filter.applyOps
import suwayomi.tachidesk.graphql.server.getAttribute
import suwayomi.tachidesk.graphql.server.primitives.Cursor import suwayomi.tachidesk.graphql.server.primitives.Cursor
import suwayomi.tachidesk.graphql.server.primitives.Order import suwayomi.tachidesk.graphql.server.primitives.Order
import suwayomi.tachidesk.graphql.server.primitives.OrderBy import suwayomi.tachidesk.graphql.server.primitives.OrderBy
@@ -40,19 +40,14 @@ import suwayomi.tachidesk.graphql.server.primitives.maybeSwap
import suwayomi.tachidesk.graphql.types.SourceNodeList import suwayomi.tachidesk.graphql.types.SourceNodeList
import suwayomi.tachidesk.graphql.types.SourceType import suwayomi.tachidesk.graphql.types.SourceType
import suwayomi.tachidesk.manga.model.table.SourceTable import suwayomi.tachidesk.manga.model.table.SourceTable
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
class SourceQuery { class SourceQuery {
@RequireAuth
fun source( fun source(
dataFetchingEnvironment: DataFetchingEnvironment, dataFetchingEnvironment: DataFetchingEnvironment,
id: Long, id: Long,
): CompletableFuture<SourceType> { ): CompletableFuture<SourceType> = dataFetchingEnvironment.getValueFromDataLoader("SourceDataLoader", id)
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
return dataFetchingEnvironment.getValueFromDataLoader("SourceDataLoader", id)
}
enum class SourceOrderBy( enum class SourceOrderBy(
override val column: Column<*>, override val column: Column<*>,
@@ -127,8 +122,8 @@ class SourceQuery {
) )
} }
@RequireAuth
fun sources( fun sources(
dataFetchingEnvironment: DataFetchingEnvironment,
condition: SourceCondition? = null, condition: SourceCondition? = null,
filter: SourceFilter? = null, filter: SourceFilter? = null,
@GraphQLDeprecated( @GraphQLDeprecated(
@@ -148,7 +143,6 @@ class SourceQuery {
last: Int? = null, last: Int? = null,
offset: Int? = null, offset: Int? = null,
): SourceNodeList { ): SourceNodeList {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (queryResults, resultsAsType) = val (queryResults, resultsAsType) =
transaction { transaction {
val res = SourceTable.selectAll() val res = SourceTable.selectAll()

View File

@@ -10,6 +10,7 @@ import org.jetbrains.exposed.sql.SqlExpressionBuilder.greater
import org.jetbrains.exposed.sql.SqlExpressionBuilder.less import org.jetbrains.exposed.sql.SqlExpressionBuilder.less
import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.queries.filter.BooleanFilter import suwayomi.tachidesk.graphql.queries.filter.BooleanFilter
import suwayomi.tachidesk.graphql.queries.filter.DoubleFilter import suwayomi.tachidesk.graphql.queries.filter.DoubleFilter
import suwayomi.tachidesk.graphql.queries.filter.Filter import suwayomi.tachidesk.graphql.queries.filter.Filter
@@ -22,7 +23,6 @@ import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompare
import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareEntity import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareEntity
import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareString import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareString
import suwayomi.tachidesk.graphql.queries.filter.applyOps import suwayomi.tachidesk.graphql.queries.filter.applyOps
import suwayomi.tachidesk.graphql.server.getAttribute
import suwayomi.tachidesk.graphql.server.primitives.Cursor import suwayomi.tachidesk.graphql.server.primitives.Cursor
import suwayomi.tachidesk.graphql.server.primitives.Order import suwayomi.tachidesk.graphql.server.primitives.Order
import suwayomi.tachidesk.graphql.server.primitives.OrderBy import suwayomi.tachidesk.graphql.server.primitives.OrderBy
@@ -40,20 +40,15 @@ import suwayomi.tachidesk.graphql.types.TrackerType
import suwayomi.tachidesk.manga.impl.track.tracker.TrackerManager import suwayomi.tachidesk.manga.impl.track.tracker.TrackerManager
import suwayomi.tachidesk.manga.model.table.TrackRecordTable import suwayomi.tachidesk.manga.model.table.TrackRecordTable
import suwayomi.tachidesk.manga.model.table.insertAll import suwayomi.tachidesk.manga.model.table.insertAll
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.future import suwayomi.tachidesk.server.JavalinSetup.future
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
class TrackQuery { class TrackQuery {
@RequireAuth
fun tracker( fun tracker(
dataFetchingEnvironment: DataFetchingEnvironment, dataFetchingEnvironment: DataFetchingEnvironment,
id: Int, id: Int,
): CompletableFuture<TrackerType> { ): CompletableFuture<TrackerType> = dataFetchingEnvironment.getValueFromDataLoader<Int, TrackerType>("TrackerDataLoader", id)
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
return dataFetchingEnvironment.getValueFromDataLoader<Int, TrackerType>("TrackerDataLoader", id)
}
enum class TrackerOrderBy { enum class TrackerOrderBy {
ID, ID,
@@ -121,8 +116,8 @@ class TrackQuery {
val not: TrackerFilter? = null, val not: TrackerFilter? = null,
) )
@RequireAuth
fun trackers( fun trackers(
dataFetchingEnvironment: DataFetchingEnvironment,
condition: TrackerCondition? = null, condition: TrackerCondition? = null,
@GraphQLDeprecated( @GraphQLDeprecated(
"Replaced with order", "Replaced with order",
@@ -141,7 +136,6 @@ class TrackQuery {
last: Int? = null, last: Int? = null,
offset: Int? = null, offset: Int? = null,
): TrackerNodeList { ): TrackerNodeList {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val (queryResults, resultsAsType) = val (queryResults, resultsAsType) =
run { run {
var res = TrackerManager.services.map { TrackerType(it) } var res = TrackerManager.services.map { TrackerType(it) }
@@ -246,13 +240,12 @@ class TrackQuery {
) )
} }
@RequireAuth
fun trackRecord( fun trackRecord(
dataFetchingEnvironment: DataFetchingEnvironment, dataFetchingEnvironment: DataFetchingEnvironment,
id: Int, id: Int,
): CompletableFuture<TrackRecordType> { ): CompletableFuture<TrackRecordType> =
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser() dataFetchingEnvironment.getValueFromDataLoader<Int, TrackRecordType>("TrackRecordDataLoader", id)
return dataFetchingEnvironment.getValueFromDataLoader<Int, TrackRecordType>("TrackRecordDataLoader", id)
}
enum class TrackRecordOrderBy( enum class TrackRecordOrderBy(
override val column: Column<*>, override val column: Column<*>,
@@ -399,8 +392,8 @@ class TrackQuery {
) )
} }
@RequireAuth
fun trackRecords( fun trackRecords(
dataFetchingEnvironment: DataFetchingEnvironment,
condition: TrackRecordCondition? = null, condition: TrackRecordCondition? = null,
filter: TrackRecordFilter? = null, filter: TrackRecordFilter? = null,
@GraphQLDeprecated( @GraphQLDeprecated(
@@ -420,7 +413,6 @@ class TrackQuery {
last: Int? = null, last: Int? = null,
offset: Int? = null, offset: Int? = null,
): TrackRecordNodeList { ): TrackRecordNodeList {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val queryResults = val queryResults =
transaction { transaction {
val res = TrackRecordTable.selectAll() val res = TrackRecordTable.selectAll()
@@ -503,12 +495,9 @@ class TrackQuery {
val trackSearches: List<TrackSearchType>, val trackSearches: List<TrackSearchType>,
) )
fun searchTracker( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun searchTracker(input: SearchTrackerInput): CompletableFuture<SearchTrackerPayload> =
input: SearchTrackerInput,
): CompletableFuture<SearchTrackerPayload> =
future { future {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val tracker = val tracker =
requireNotNull(TrackerManager.getTracker(input.trackerId)) { requireNotNull(TrackerManager.getTracker(input.trackerId)) {
"Tracker not found" "Tracker not found"

View File

@@ -1,16 +1,12 @@
package suwayomi.tachidesk.graphql.queries package suwayomi.tachidesk.graphql.queries
import com.expediagroup.graphql.generator.annotations.GraphQLDeprecated import com.expediagroup.graphql.generator.annotations.GraphQLDeprecated
import graphql.schema.DataFetchingEnvironment
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import suwayomi.tachidesk.graphql.server.getAttribute import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.types.LibraryUpdateStatus import suwayomi.tachidesk.graphql.types.LibraryUpdateStatus
import suwayomi.tachidesk.graphql.types.UpdateStatus import suwayomi.tachidesk.graphql.types.UpdateStatus
import suwayomi.tachidesk.manga.impl.update.IUpdater import suwayomi.tachidesk.manga.impl.update.IUpdater
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.future import suwayomi.tachidesk.server.JavalinSetup.future
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
@@ -18,15 +14,15 @@ class UpdateQuery {
private val updater: IUpdater by injectLazy() private val updater: IUpdater by injectLazy()
@GraphQLDeprecated("Replaced with libraryUpdateStatus", ReplaceWith("libraryUpdateStatus")) @GraphQLDeprecated("Replaced with libraryUpdateStatus", ReplaceWith("libraryUpdateStatus"))
fun updateStatus(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<UpdateStatus> = @RequireAuth
fun updateStatus(): CompletableFuture<UpdateStatus> =
future { future {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
UpdateStatus(updater.status.first()) UpdateStatus(updater.status.first())
} }
fun libraryUpdateStatus(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<LibraryUpdateStatus> = @RequireAuth
fun libraryUpdateStatus(): CompletableFuture<LibraryUpdateStatus> =
future { future {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
LibraryUpdateStatus(updater.getStatus()) LibraryUpdateStatus(updater.getStatus())
} }
@@ -34,8 +30,6 @@ class UpdateQuery {
val timestamp: Long, val timestamp: Long,
) )
fun lastUpdateTimestamp(dataFetchingEnvironment: DataFetchingEnvironment): LastUpdateTimestampPayload { @RequireAuth
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser() fun lastUpdateTimestamp(): LastUpdateTimestampPayload = LastUpdateTimestampPayload(updater.getLastUpdateTimestamp())
return LastUpdateTimestampPayload(updater.getLastUpdateTimestamp())
}
} }

View File

@@ -9,10 +9,12 @@ package suwayomi.tachidesk.graphql.server
import com.expediagroup.graphql.generator.SchemaGeneratorConfig import com.expediagroup.graphql.generator.SchemaGeneratorConfig
import com.expediagroup.graphql.generator.TopLevelObject import com.expediagroup.graphql.generator.TopLevelObject
import com.expediagroup.graphql.generator.directives.KotlinDirectiveWiringFactory
import com.expediagroup.graphql.generator.hooks.FlowSubscriptionSchemaGeneratorHooks import com.expediagroup.graphql.generator.hooks.FlowSubscriptionSchemaGeneratorHooks
import com.expediagroup.graphql.generator.toSchema import com.expediagroup.graphql.generator.toSchema
import graphql.schema.GraphQLType import graphql.schema.GraphQLType
import io.javalin.http.UploadedFile import io.javalin.http.UploadedFile
import suwayomi.tachidesk.graphql.directives.RequireAuthDirectiveWiring
import suwayomi.tachidesk.graphql.mutations.BackupMutation import suwayomi.tachidesk.graphql.mutations.BackupMutation
import suwayomi.tachidesk.graphql.mutations.CategoryMutation import suwayomi.tachidesk.graphql.mutations.CategoryMutation
import suwayomi.tachidesk.graphql.mutations.ChapterMutation import suwayomi.tachidesk.graphql.mutations.ChapterMutation
@@ -54,6 +56,11 @@ import kotlin.reflect.KType
import kotlin.time.Duration import kotlin.time.Duration
class CustomSchemaGeneratorHooks : FlowSubscriptionSchemaGeneratorHooks() { class CustomSchemaGeneratorHooks : FlowSubscriptionSchemaGeneratorHooks() {
override val wiringFactory =
KotlinDirectiveWiringFactory(
manualWiring = mapOf("requireAuth" to RequireAuthDirectiveWiring()),
)
override fun willGenerateGraphQLType(type: KType): GraphQLType? = override fun willGenerateGraphQLType(type: KType): GraphQLType? =
when (type.classifier as? KClass<*>) { when (type.classifier as? KClass<*>) {
Long::class -> GraphQLLongAsString // encode to string for JS Long::class -> GraphQLLongAsString // encode to string for JS

View File

@@ -16,6 +16,7 @@ import graphql.GraphQL
import graphql.execution.AsyncExecutionStrategy import graphql.execution.AsyncExecutionStrategy
import graphql.execution.DataFetcherExceptionHandler import graphql.execution.DataFetcherExceptionHandler
import graphql.execution.DataFetcherExceptionHandlerResult import graphql.execution.DataFetcherExceptionHandlerResult
import graphql.schema.idl.RuntimeWiring
import io.github.oshai.kotlinlogging.KotlinLogging import io.github.oshai.kotlinlogging.KotlinLogging
import io.javalin.http.Context import io.javalin.http.Context
import io.javalin.websocket.WsCloseContext import io.javalin.websocket.WsCloseContext

View File

@@ -9,25 +9,20 @@ package suwayomi.tachidesk.graphql.subscriptions
import com.expediagroup.graphql.generator.annotations.GraphQLDeprecated import com.expediagroup.graphql.generator.annotations.GraphQLDeprecated
import com.expediagroup.graphql.generator.annotations.GraphQLDescription import com.expediagroup.graphql.generator.annotations.GraphQLDescription
import graphql.schema.DataFetchingEnvironment
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import suwayomi.tachidesk.graphql.server.getAttribute import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.types.DownloadStatus import suwayomi.tachidesk.graphql.types.DownloadStatus
import suwayomi.tachidesk.graphql.types.DownloadUpdates import suwayomi.tachidesk.graphql.types.DownloadUpdates
import suwayomi.tachidesk.manga.impl.download.DownloadManager import suwayomi.tachidesk.manga.impl.download.DownloadManager
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
class DownloadSubscription { class DownloadSubscription {
@GraphQLDeprecated("Replaced with downloadStatusChanged", ReplaceWith("downloadStatusChanged(input)")) @GraphQLDeprecated("Replaced with downloadStatusChanged", ReplaceWith("downloadStatusChanged(input)"))
fun downloadChanged(dataFetchingEnvironment: DataFetchingEnvironment): Flow<DownloadStatus> { @RequireAuth
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser() fun downloadChanged(): Flow<DownloadStatus> =
return DownloadManager.status.map { downloadStatus -> DownloadManager.status.map { downloadStatus ->
DownloadStatus(downloadStatus) DownloadStatus(downloadStatus)
} }
}
data class DownloadChangedInput( data class DownloadChangedInput(
@GraphQLDescription( @GraphQLDescription(
@@ -40,11 +35,8 @@ class DownloadSubscription {
val maxUpdates: Int?, val maxUpdates: Int?,
) )
fun downloadStatusChanged( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun downloadStatusChanged(input: DownloadChangedInput): Flow<DownloadUpdates> {
input: DownloadChangedInput,
): Flow<DownloadUpdates> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val omitUpdates = input.maxUpdates != null val omitUpdates = input.maxUpdates != null
val maxUpdates = input.maxUpdates ?: 50 val maxUpdates = input.maxUpdates ?: 50

View File

@@ -1,17 +1,11 @@
package suwayomi.tachidesk.graphql.subscriptions package suwayomi.tachidesk.graphql.subscriptions
import graphql.schema.DataFetchingEnvironment
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import suwayomi.tachidesk.graphql.server.getAttribute import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.types.WebUIUpdateStatus import suwayomi.tachidesk.graphql.types.WebUIUpdateStatus
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
import suwayomi.tachidesk.server.util.WebInterfaceManager import suwayomi.tachidesk.server.util.WebInterfaceManager
class InfoSubscription { class InfoSubscription {
fun webUIUpdateStatusChange(dataFetchingEnvironment: DataFetchingEnvironment): Flow<WebUIUpdateStatus> { @RequireAuth
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser() fun webUIUpdateStatusChange(): Flow<WebUIUpdateStatus> = WebInterfaceManager.status
return WebInterfaceManager.status
}
} }

View File

@@ -9,29 +9,24 @@ package suwayomi.tachidesk.graphql.subscriptions
import com.expediagroup.graphql.generator.annotations.GraphQLDeprecated import com.expediagroup.graphql.generator.annotations.GraphQLDeprecated
import com.expediagroup.graphql.generator.annotations.GraphQLDescription import com.expediagroup.graphql.generator.annotations.GraphQLDescription
import graphql.schema.DataFetchingEnvironment
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import suwayomi.tachidesk.graphql.server.getAttribute import suwayomi.tachidesk.graphql.directives.RequireAuth
import suwayomi.tachidesk.graphql.types.UpdateStatus import suwayomi.tachidesk.graphql.types.UpdateStatus
import suwayomi.tachidesk.graphql.types.UpdaterUpdates import suwayomi.tachidesk.graphql.types.UpdaterUpdates
import suwayomi.tachidesk.manga.impl.update.IUpdater import suwayomi.tachidesk.manga.impl.update.IUpdater
import suwayomi.tachidesk.manga.impl.update.UpdateUpdates import suwayomi.tachidesk.manga.impl.update.UpdateUpdates
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
class UpdateSubscription { class UpdateSubscription {
private val updater: IUpdater by injectLazy() private val updater: IUpdater by injectLazy()
@GraphQLDeprecated("Replaced with updates", ReplaceWith("updates(input)")) @GraphQLDeprecated("Replaced with updates", ReplaceWith("updates(input)"))
fun updateStatusChanged(dataFetchingEnvironment: DataFetchingEnvironment): Flow<UpdateStatus> { @RequireAuth
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser() fun updateStatusChanged(): Flow<UpdateStatus> =
return updater.status.map { updateStatus -> updater.status.map { updateStatus ->
UpdateStatus(updateStatus) UpdateStatus(updateStatus)
} }
}
data class LibraryUpdateStatusChangedInput( data class LibraryUpdateStatusChangedInput(
@GraphQLDescription( @GraphQLDescription(
@@ -44,11 +39,8 @@ class UpdateSubscription {
val maxUpdates: Int?, val maxUpdates: Int?,
) )
fun libraryUpdateStatusChanged( @RequireAuth
dataFetchingEnvironment: DataFetchingEnvironment, fun libraryUpdateStatusChanged(input: LibraryUpdateStatusChangedInput): Flow<UpdaterUpdates> {
input: LibraryUpdateStatusChangedInput,
): Flow<UpdaterUpdates> {
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
val omitUpdates = input.maxUpdates != null val omitUpdates = input.maxUpdates != null
val maxUpdates = input.maxUpdates ?: 50 val maxUpdates = input.maxUpdates ?: 50