Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/invalid server settings gql mutation request #1092

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ private fun createRollingFileAppender(
context = logContext
setParent(appender)
fileNamePattern = "$logDirPath/${logFilename}_%d{yyyy-MM-dd}_%i.log.gz"
maxHistory = maxFiles
maxHistory = maxFiles.coerceAtLeast(0)
setMaxFileSize(fileSizeValueOfOrDefault(maxFileSize, "10mb"))
setTotalSizeCap(fileSizeValueOfOrDefault(maxTotalSize, "100mb"))
start()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,47 @@ import kotlinx.coroutines.flow.MutableStateFlow
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.SERVER_CONFIG_MODULE_NAME
import suwayomi.tachidesk.server.ServerConfig
import suwayomi.tachidesk.server.serverConfig
import xyz.nulldev.ts.config.GlobalConfigManager
import java.io.File

private fun validateString(
value: String?,
pattern: Regex,
name: String,
private fun validateValue(
exception: Exception,
validate: () -> Boolean,
) {
validateString(value, pattern, Exception("Invalid format for \"$name\" [$value]"))
if (!validate()) {
throw exception
}
}

private fun validateString(
value: String?,
pattern: Regex,
private fun <T> validateValue(
value: T?,
exception: Exception,
validate: (value: T) -> Boolean,
) {
if (value != null && !value.matches(pattern)) {
throw exception
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,
Expand All @@ -39,10 +57,43 @@ class SettingsMutation {
)

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
val logbackSizePattern = "^[0-9]+(|kb|KB|mb|MB|gb|GB)\$".toRegex()
validateString(settings.maxLogFileSize, logbackSizePattern, "maxLogFileSize")
validateString(settings.maxLogFolderSize, logbackSizePattern, "maxLogFolderSize")
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")
}

private fun <SettingType : Any> updateSetting(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ object Chapter {
if (serverConfig.autoDownloadNewChaptersLimit.value == 0) {
chaptersToConsiderForDownloadLimit.size
} else {
serverConfig.autoDownloadNewChaptersLimit.value.coerceAtMost(chaptersToConsiderForDownloadLimit.size)
serverConfig.autoDownloadNewChaptersLimit.value.coerceIn(0, chaptersToConsiderForDownloadLimit.size)
}
val limitedChaptersToDownload = chaptersToConsiderForDownloadLimit.subList(0, latestChapterToDownloadIndex)
val limitedChaptersToDownloadWithDuplicates =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,14 +204,14 @@ object DownloadManager {
"Failed: ${downloadQueue.size - availableDownloads.size}"
}

if (runningDownloaders.size < serverConfig.maxSourcesInParallel.value) {
if (runningDownloaders.size < serverConfig.maxSourcesInParallel.value.coerceAtLeast(1)) {
availableDownloads
.asSequence()
.map { it.manga.sourceId }
.distinct()
.minus(
runningDownloaders.map { it.sourceId }.toSet(),
).take(serverConfig.maxSourcesInParallel.value - runningDownloaders.size)
).take((serverConfig.maxSourcesInParallel.value - runningDownloaders.size).coerceAtLeast(0))
.map { getDownloader(it) }
.forEach {
it.start()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ object ExtensionsList {
this
}

private val repoMatchRegex =
val repoMatchRegex =
(
"https:\\/\\/(?>www\\.|raw\\.)?(github|githubusercontent)\\.com" +
"\\/([^\\/]+)\\/([^\\/]+)(?>(?>\\/tree|\\/blob)?\\/([^\\/\\n]*))?(?>\\/([^\\/\\n]*\\.json)?)?"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ object WebInterfaceManager {
private fun getServedWebUIFlavor(): WebUIFlavor =
WebUIFlavor.from(preferences.getString(SERVED_WEBUI_FLAVOR_KEY, WebUIFlavor.default.uiName)!!)

private fun isAutoUpdateEnabled(): Boolean = serverConfig.webUIUpdateCheckInterval.value.toInt() != 0
private fun isAutoUpdateEnabled(): Boolean = serverConfig.webUIUpdateCheckInterval.value.toInt() > 0

@OptIn(DelicateCoroutinesApi::class)
private fun scheduleWebUIUpdateCheck() {
Expand Down
Loading