mirror of
https://github.com/Suwayomi/Suwayomi-Server.git
synced 2026-07-04 03:14:40 -05:00
Feature/graphql settings add jwt settings (#1612)
* Add jwt settings to grapqhl SettingsType * Sort proto BackupServerSettings by ProtNumber
This commit is contained in:
@@ -182,6 +182,9 @@ class SettingsMutation {
|
||||
|
||||
// Authentication
|
||||
updateSetting(settings.authMode, serverConfig.authMode)
|
||||
updateSetting(settings.jwtAudience, serverConfig.jwtAudience)
|
||||
updateSetting(settings.jwtTokenExpiry, serverConfig.jwtTokenExpiry)
|
||||
updateSetting(settings.jwtRefreshExpiry, serverConfig.jwtRefreshExpiry)
|
||||
updateSetting(settings.authUsername, serverConfig.authUsername)
|
||||
updateSetting(settings.authPassword, serverConfig.authPassword)
|
||||
updateSetting(settings.basicAuthEnabled, serverConfig.basicAuthEnabled)
|
||||
|
||||
@@ -43,6 +43,7 @@ import suwayomi.tachidesk.graphql.queries.TrackQuery
|
||||
import suwayomi.tachidesk.graphql.queries.UpdateQuery
|
||||
import suwayomi.tachidesk.graphql.server.primitives.Cursor
|
||||
import suwayomi.tachidesk.graphql.server.primitives.GraphQLCursor
|
||||
import suwayomi.tachidesk.graphql.server.primitives.GraphQLDurationAsString
|
||||
import suwayomi.tachidesk.graphql.server.primitives.GraphQLLongAsString
|
||||
import suwayomi.tachidesk.graphql.server.primitives.GraphQLUpload
|
||||
import suwayomi.tachidesk.graphql.subscriptions.DownloadSubscription
|
||||
@@ -50,11 +51,13 @@ import suwayomi.tachidesk.graphql.subscriptions.InfoSubscription
|
||||
import suwayomi.tachidesk.graphql.subscriptions.UpdateSubscription
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.time.Duration
|
||||
|
||||
class CustomSchemaGeneratorHooks : FlowSubscriptionSchemaGeneratorHooks() {
|
||||
override fun willGenerateGraphQLType(type: KType): GraphQLType? =
|
||||
when (type.classifier as? KClass<*>) {
|
||||
Long::class -> GraphQLLongAsString // encode to string for JS
|
||||
Duration::class -> GraphQLDurationAsString // encode Duration as ISO-8601 string
|
||||
Cursor::class -> GraphQLCursor
|
||||
UploadedFile::class -> GraphQLUpload
|
||||
else -> super.willGenerateGraphQLType(type)
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
package suwayomi.tachidesk.graphql.server.primitives
|
||||
|
||||
import graphql.GraphQLContext
|
||||
import graphql.execution.CoercedVariables
|
||||
import graphql.language.StringValue
|
||||
import graphql.language.Value
|
||||
import graphql.scalar.CoercingUtil
|
||||
import graphql.schema.Coercing
|
||||
import graphql.schema.CoercingParseLiteralException
|
||||
import graphql.schema.CoercingParseValueException
|
||||
import graphql.schema.CoercingSerializeException
|
||||
import graphql.schema.GraphQLScalarType
|
||||
import java.util.Locale
|
||||
import kotlin.time.Duration
|
||||
|
||||
val GraphQLDurationAsString: GraphQLScalarType =
|
||||
GraphQLScalarType
|
||||
.newScalar()
|
||||
.name("Duration")
|
||||
.description("An ISO-8601 encoded duration string")
|
||||
.coercing(GraphqlDurationAsStringCoercing())
|
||||
.build()
|
||||
|
||||
private class GraphqlDurationAsStringCoercing : Coercing<Duration, String> {
|
||||
private fun toStringImpl(input: Any): String =
|
||||
when (input) {
|
||||
is Duration -> input.toIsoString()
|
||||
is String -> Duration.parse(input).toIsoString()
|
||||
else -> throw CoercingSerializeException(
|
||||
"Expected a Duration or String but was ${CoercingUtil.typeName(input)}",
|
||||
)
|
||||
}
|
||||
|
||||
private fun parseValueImpl(
|
||||
input: Any,
|
||||
locale: Locale,
|
||||
): Duration {
|
||||
if (input !is String) {
|
||||
throw CoercingParseValueException(
|
||||
CoercingUtil.i18nMsg(
|
||||
locale,
|
||||
"String.unexpectedRawValueType",
|
||||
CoercingUtil.typeName(input),
|
||||
),
|
||||
)
|
||||
}
|
||||
return try {
|
||||
Duration.parse(input)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
throw CoercingParseValueException(
|
||||
"Invalid duration format: $input. Expected ISO-8601 duration string (e.g., 'PT30M', 'P1D')",
|
||||
e,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseLiteralImpl(
|
||||
input: Any,
|
||||
locale: Locale,
|
||||
): Duration {
|
||||
if (input !is StringValue) {
|
||||
throw CoercingParseLiteralException(
|
||||
CoercingUtil.i18nMsg(
|
||||
locale,
|
||||
"Scalar.unexpectedAstType",
|
||||
"StringValue",
|
||||
CoercingUtil.typeName(input),
|
||||
),
|
||||
)
|
||||
}
|
||||
return try {
|
||||
Duration.parse(input.value)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
throw CoercingParseLiteralException(
|
||||
"Invalid duration format: ${input.value}. Expected ISO-8601 duration string (e.g., 'PT30M', 'P1D')",
|
||||
e,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun valueToLiteralImpl(input: Any): StringValue = StringValue.newStringValue(toStringImpl(input)).build()
|
||||
|
||||
@Deprecated("")
|
||||
override fun serialize(dataFetcherResult: Any): String = toStringImpl(dataFetcherResult)
|
||||
|
||||
@Throws(CoercingSerializeException::class)
|
||||
override fun serialize(
|
||||
dataFetcherResult: Any,
|
||||
graphQLContext: GraphQLContext,
|
||||
locale: Locale,
|
||||
): String = toStringImpl(dataFetcherResult)
|
||||
|
||||
@Deprecated("")
|
||||
override fun parseValue(input: Any): Duration = parseValueImpl(input, Locale.getDefault())
|
||||
|
||||
@Throws(CoercingParseValueException::class)
|
||||
override fun parseValue(
|
||||
input: Any,
|
||||
graphQLContext: GraphQLContext,
|
||||
locale: Locale,
|
||||
): Duration = parseValueImpl(input, locale)
|
||||
|
||||
@Deprecated("")
|
||||
override fun parseLiteral(input: Any): Duration = parseLiteralImpl(input, Locale.getDefault())
|
||||
|
||||
@Throws(CoercingParseLiteralException::class)
|
||||
override fun parseLiteral(
|
||||
input: Value<*>,
|
||||
variables: CoercedVariables,
|
||||
graphQLContext: GraphQLContext,
|
||||
locale: Locale,
|
||||
): Duration = parseLiteralImpl(input, locale)
|
||||
|
||||
@Deprecated("")
|
||||
override fun valueToLiteral(input: Any): Value<*> = valueToLiteralImpl(input)
|
||||
|
||||
override fun valueToLiteral(
|
||||
input: Any,
|
||||
graphQLContext: GraphQLContext,
|
||||
locale: Locale,
|
||||
): Value<*> = valueToLiteralImpl(input)
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import org.jetbrains.exposed.sql.SortOrder
|
||||
import suwayomi.tachidesk.graphql.server.primitives.Node
|
||||
import suwayomi.tachidesk.server.ServerConfig
|
||||
import suwayomi.tachidesk.server.serverConfig
|
||||
import kotlin.time.Duration
|
||||
|
||||
interface Settings : Node {
|
||||
val ip: String?
|
||||
@@ -65,6 +66,9 @@ interface Settings : Node {
|
||||
|
||||
// Authentication
|
||||
val authMode: AuthMode?
|
||||
val jwtAudience: String?
|
||||
val jwtTokenExpiry: Duration?
|
||||
val jwtRefreshExpiry: Duration?
|
||||
val authUsername: String?
|
||||
val authPassword: String?
|
||||
|
||||
@@ -177,6 +181,9 @@ data class PartialSettingsType(
|
||||
override val updateMangas: Boolean?,
|
||||
// Authentication
|
||||
override val authMode: AuthMode?,
|
||||
override val jwtAudience: String?,
|
||||
override val jwtTokenExpiry: Duration?,
|
||||
override val jwtRefreshExpiry: Duration?,
|
||||
override val authUsername: String?,
|
||||
override val authPassword: String?,
|
||||
@GraphQLDeprecated("Removed - prefer authMode")
|
||||
@@ -267,6 +274,9 @@ class SettingsType(
|
||||
override val updateMangas: Boolean,
|
||||
// Authentication
|
||||
override val authMode: AuthMode,
|
||||
override val jwtAudience: String,
|
||||
override val jwtTokenExpiry: Duration,
|
||||
override val jwtRefreshExpiry: Duration,
|
||||
override val authUsername: String,
|
||||
override val authPassword: String,
|
||||
@GraphQLDeprecated("Removed - prefer authMode")
|
||||
@@ -358,6 +368,9 @@ class SettingsType(
|
||||
config.updateMangas.value,
|
||||
// Authentication
|
||||
config.authMode.value,
|
||||
config.jwtAudience.value,
|
||||
config.jwtTokenExpiry.value,
|
||||
config.jwtRefreshExpiry.value,
|
||||
config.authUsername.value,
|
||||
config.authPassword.value,
|
||||
config.basicAuthEnabled.value,
|
||||
|
||||
Reference in New Issue
Block a user