mirror of
https://github.com/Suwayomi/Suwayomi-Server.git
synced 2026-07-04 03:14:40 -05:00
* Add jwt settings to grapqhl SettingsType * Sort proto BackupServerSettings by ProtNumber
280 lines
12 KiB
Kotlin
280 lines
12 KiB
Kotlin
package suwayomi.tachidesk.graphql.mutations
|
|
|
|
import com.expediagroup.graphql.generator.annotations.GraphQLIgnore
|
|
import graphql.schema.DataFetchingEnvironment
|
|
import kotlinx.coroutines.flow.MutableStateFlow
|
|
import suwayomi.tachidesk.graphql.server.getAttribute
|
|
import suwayomi.tachidesk.graphql.types.PartialSettingsType
|
|
import suwayomi.tachidesk.graphql.types.Settings
|
|
import suwayomi.tachidesk.graphql.types.SettingsType
|
|
import suwayomi.tachidesk.manga.impl.extension.ExtensionsList.repoMatchRegex
|
|
import suwayomi.tachidesk.server.JavalinSetup.Attribute
|
|
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
|
|
import suwayomi.tachidesk.server.SERVER_CONFIG_MODULE_NAME
|
|
import suwayomi.tachidesk.server.ServerConfig
|
|
import suwayomi.tachidesk.server.serverConfig
|
|
import suwayomi.tachidesk.server.user.requireUser
|
|
import xyz.nulldev.ts.config.GlobalConfigManager
|
|
import java.io.File
|
|
|
|
private fun validateValue(
|
|
exception: Exception,
|
|
validate: () -> Boolean,
|
|
) {
|
|
if (!validate()) {
|
|
throw exception
|
|
}
|
|
}
|
|
|
|
private fun <T> validateValue(
|
|
value: T?,
|
|
exception: Exception,
|
|
validate: (value: T) -> Boolean,
|
|
) {
|
|
if (value != null) {
|
|
validateValue(exception) { validate(value) }
|
|
}
|
|
}
|
|
|
|
private fun <T> validateValue(
|
|
value: T?,
|
|
name: String,
|
|
validate: (value: T) -> Boolean,
|
|
) {
|
|
validateValue(value, Exception("Invalid value for \"$name\" [$value]"), validate)
|
|
}
|
|
|
|
private fun validateFilePath(
|
|
value: String?,
|
|
name: String,
|
|
) {
|
|
validateValue(value, name) { File(it).exists() }
|
|
}
|
|
|
|
class SettingsMutation {
|
|
data class SetSettingsInput(
|
|
val clientMutationId: String? = null,
|
|
val settings: PartialSettingsType,
|
|
)
|
|
|
|
data class SetSettingsPayload(
|
|
val clientMutationId: String?,
|
|
val settings: SettingsType,
|
|
)
|
|
|
|
private fun validateSettings(settings: Settings) {
|
|
validateValue(settings.ip, "ip") { it.matches("^((25[0-5]|(2[0-4]|1\\d|[1-9]|)\\d)\\.?\\b){4}$".toRegex()) }
|
|
|
|
// proxy
|
|
validateValue(settings.socksProxyVersion, "socksProxyVersion") { it == 4 || it == 5 }
|
|
|
|
// webUI
|
|
validateFilePath(settings.electronPath, "electronPath")
|
|
validateValue(settings.webUIUpdateCheckInterval, "webUIUpdateCheckInterval") { it == 0.0 || it in 1.0..23.0 }
|
|
|
|
// downloader
|
|
validateFilePath(settings.downloadsPath, "downloadsPath")
|
|
validateValue(settings.autoDownloadNewChaptersLimit, "autoDownloadNewChaptersLimit") { it >= 0 }
|
|
|
|
// extensions
|
|
validateValue(settings.extensionRepos, "extensionRepos") { it.all { repoUrl -> repoUrl.matches(repoMatchRegex) } }
|
|
|
|
// requests
|
|
validateValue(settings.maxSourcesInParallel, "maxSourcesInParallel") { it in 1..20 }
|
|
|
|
// updater
|
|
validateValue(settings.globalUpdateInterval, "globalUpdateInterval") { it == 0.0 || it >= 6 }
|
|
|
|
// misc
|
|
validateValue(settings.maxLogFiles, "maxLogFiles") { it >= 0 }
|
|
|
|
val logbackSizePattern = "^[0-9]+(|kb|KB|mb|MB|gb|GB)$".toRegex()
|
|
validateValue(settings.maxLogFileSize, "maxLogFolderSize") { it.matches(logbackSizePattern) }
|
|
validateValue(settings.maxLogFolderSize, "maxLogFolderSize") { it.matches(logbackSizePattern) }
|
|
|
|
// backup
|
|
validateFilePath(settings.backupPath, "backupPath")
|
|
validateValue(settings.backupTime, "backupTime") { it.matches("^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$".toRegex()) }
|
|
validateValue(settings.backupInterval, "backupInterval") { it == 0 || it >= 1 }
|
|
validateValue(settings.backupTTL, "backupTTL") { it == 0 || it >= 1 }
|
|
|
|
// local source
|
|
validateFilePath(settings.localSourcePath, "localSourcePath")
|
|
|
|
// opds
|
|
validateValue(settings.opdsItemsPerPage, "opdsItemsPerPage") { it in 10..5000 }
|
|
}
|
|
|
|
private fun <SettingType : Any> updateSetting(
|
|
newSetting: SettingType?,
|
|
configSetting: MutableStateFlow<SettingType>,
|
|
) {
|
|
if (newSetting == null) {
|
|
return
|
|
}
|
|
|
|
configSetting.value = newSetting
|
|
}
|
|
|
|
private fun <SettingType : Any, RealSettingType : Any> updateSetting(
|
|
newSetting: RealSettingType?,
|
|
configSetting: MutableStateFlow<SettingType>,
|
|
mapper: (RealSettingType) -> SettingType,
|
|
) {
|
|
if (newSetting == null) {
|
|
return
|
|
}
|
|
|
|
configSetting.value = mapper(newSetting)
|
|
}
|
|
|
|
@GraphQLIgnore
|
|
fun updateSettings(settings: Settings) {
|
|
updateSetting(settings.ip, serverConfig.ip)
|
|
updateSetting(settings.port, serverConfig.port)
|
|
|
|
// proxy
|
|
updateSetting(settings.socksProxyEnabled, serverConfig.socksProxyEnabled)
|
|
updateSetting(settings.socksProxyVersion, serverConfig.socksProxyVersion)
|
|
updateSetting(settings.socksProxyHost, serverConfig.socksProxyHost)
|
|
updateSetting(settings.socksProxyPort, serverConfig.socksProxyPort)
|
|
updateSetting(settings.socksProxyUsername, serverConfig.socksProxyUsername)
|
|
updateSetting(settings.socksProxyPassword, serverConfig.socksProxyPassword)
|
|
|
|
// webUI
|
|
updateSetting(settings.webUIFlavor, serverConfig.webUIFlavor)
|
|
updateSetting(settings.initialOpenInBrowserEnabled, serverConfig.initialOpenInBrowserEnabled)
|
|
updateSetting(settings.webUIInterface, serverConfig.webUIInterface)
|
|
updateSetting(settings.electronPath, serverConfig.electronPath)
|
|
updateSetting(settings.webUIChannel, serverConfig.webUIChannel)
|
|
updateSetting(settings.webUIUpdateCheckInterval, serverConfig.webUIUpdateCheckInterval)
|
|
|
|
// downloader
|
|
updateSetting(settings.downloadAsCbz, serverConfig.downloadAsCbz)
|
|
updateSetting(settings.downloadsPath, serverConfig.downloadsPath)
|
|
updateSetting(settings.autoDownloadNewChapters, serverConfig.autoDownloadNewChapters)
|
|
updateSetting(settings.excludeEntryWithUnreadChapters, serverConfig.excludeEntryWithUnreadChapters)
|
|
updateSetting(settings.autoDownloadAheadLimit, serverConfig.autoDownloadNewChaptersLimit) // deprecated
|
|
updateSetting(settings.autoDownloadNewChaptersLimit, serverConfig.autoDownloadNewChaptersLimit)
|
|
updateSetting(settings.autoDownloadIgnoreReUploads, serverConfig.autoDownloadIgnoreReUploads)
|
|
updateSetting(settings.downloadConversions, serverConfig.downloadConversions) { list ->
|
|
list.associate {
|
|
it.mimeType to
|
|
ServerConfig.DownloadConversion(
|
|
target = it.target,
|
|
compressionLevel = it.compressionLevel,
|
|
)
|
|
}
|
|
}
|
|
|
|
// extension
|
|
updateSetting(settings.extensionRepos, serverConfig.extensionRepos)
|
|
|
|
// requests
|
|
updateSetting(settings.maxSourcesInParallel, serverConfig.maxSourcesInParallel)
|
|
|
|
// updater
|
|
updateSetting(settings.excludeUnreadChapters, serverConfig.excludeUnreadChapters)
|
|
updateSetting(settings.excludeNotStarted, serverConfig.excludeNotStarted)
|
|
updateSetting(settings.excludeCompleted, serverConfig.excludeCompleted)
|
|
updateSetting(settings.globalUpdateInterval, serverConfig.globalUpdateInterval)
|
|
updateSetting(settings.updateMangas, serverConfig.updateMangas)
|
|
|
|
// 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)
|
|
updateSetting(settings.basicAuthUsername, serverConfig.basicAuthUsername)
|
|
updateSetting(settings.basicAuthPassword, serverConfig.basicAuthPassword)
|
|
|
|
// misc
|
|
updateSetting(settings.debugLogsEnabled, serverConfig.debugLogsEnabled)
|
|
updateSetting(settings.systemTrayEnabled, serverConfig.systemTrayEnabled)
|
|
updateSetting(settings.maxLogFiles, serverConfig.maxLogFiles)
|
|
updateSetting(settings.maxLogFileSize, serverConfig.maxLogFileSize)
|
|
updateSetting(settings.maxLogFolderSize, serverConfig.maxLogFolderSize)
|
|
|
|
// backup
|
|
updateSetting(settings.backupPath, serverConfig.backupPath)
|
|
updateSetting(settings.backupTime, serverConfig.backupTime)
|
|
updateSetting(settings.backupInterval, serverConfig.backupInterval)
|
|
updateSetting(settings.backupTTL, serverConfig.backupTTL)
|
|
|
|
// local source
|
|
updateSetting(settings.localSourcePath, serverConfig.localSourcePath)
|
|
|
|
// cloudflare bypass
|
|
updateSetting(settings.flareSolverrEnabled, serverConfig.flareSolverrEnabled)
|
|
updateSetting(settings.flareSolverrUrl, serverConfig.flareSolverrUrl)
|
|
updateSetting(settings.flareSolverrTimeout, serverConfig.flareSolverrTimeout)
|
|
updateSetting(settings.flareSolverrSessionName, serverConfig.flareSolverrSessionName)
|
|
updateSetting(settings.flareSolverrSessionTtl, serverConfig.flareSolverrSessionTtl)
|
|
updateSetting(settings.flareSolverrAsResponseFallback, serverConfig.flareSolverrAsResponseFallback)
|
|
|
|
// opds
|
|
updateSetting(settings.opdsUseBinaryFileSizes, serverConfig.opdsUseBinaryFileSizes)
|
|
updateSetting(settings.opdsItemsPerPage, serverConfig.opdsItemsPerPage)
|
|
updateSetting(settings.opdsEnablePageReadProgress, serverConfig.opdsEnablePageReadProgress)
|
|
updateSetting(settings.opdsMarkAsReadOnDownload, serverConfig.opdsMarkAsReadOnDownload)
|
|
updateSetting(settings.opdsShowOnlyUnreadChapters, serverConfig.opdsShowOnlyUnreadChapters)
|
|
updateSetting(settings.opdsShowOnlyDownloadedChapters, serverConfig.opdsShowOnlyDownloadedChapters)
|
|
updateSetting(settings.opdsChapterSortOrder, serverConfig.opdsChapterSortOrder)
|
|
|
|
// koreader sync
|
|
updateSetting(settings.koreaderSyncServerUrl, serverConfig.koreaderSyncServerUrl)
|
|
updateSetting(settings.koreaderSyncUsername, serverConfig.koreaderSyncUsername)
|
|
updateSetting(settings.koreaderSyncUserkey, serverConfig.koreaderSyncUserkey)
|
|
updateSetting(settings.koreaderSyncDeviceId, serverConfig.koreaderSyncDeviceId)
|
|
updateSetting(settings.koreaderSyncChecksumMethod, serverConfig.koreaderSyncChecksumMethod)
|
|
updateSetting(settings.koreaderSyncStrategy, serverConfig.koreaderSyncStrategy)
|
|
updateSetting(settings.koreaderSyncPercentageTolerance, serverConfig.koreaderSyncPercentageTolerance)
|
|
}
|
|
|
|
fun setSettings(
|
|
dataFetchingEnvironment: DataFetchingEnvironment,
|
|
input: SetSettingsInput,
|
|
): SetSettingsPayload {
|
|
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
|
|
val (clientMutationId, settings) = input
|
|
|
|
validateSettings(settings)
|
|
updateSettings(settings)
|
|
|
|
return SetSettingsPayload(clientMutationId, SettingsType())
|
|
}
|
|
|
|
data class ResetSettingsInput(
|
|
val clientMutationId: String? = null,
|
|
)
|
|
|
|
data class ResetSettingsPayload(
|
|
val clientMutationId: String?,
|
|
val settings: SettingsType,
|
|
)
|
|
|
|
fun resetSettings(
|
|
dataFetchingEnvironment: DataFetchingEnvironment,
|
|
input: ResetSettingsInput,
|
|
): ResetSettingsPayload {
|
|
dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser()
|
|
val (clientMutationId) = input
|
|
|
|
GlobalConfigManager.resetUserConfig()
|
|
val defaultServerConfig =
|
|
ServerConfig {
|
|
GlobalConfigManager.config.getConfig(
|
|
SERVER_CONFIG_MODULE_NAME,
|
|
)
|
|
}
|
|
|
|
val settings = SettingsType(defaultServerConfig)
|
|
updateSettings(settings)
|
|
|
|
return ResetSettingsPayload(clientMutationId, settings)
|
|
}
|
|
}
|