diff --git a/CHANGELOG.md b/CHANGELOG.md index 09ccc12..c365ed7 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Security +## [2.0.4] - 2023-08-07 +### Changed +- [2023-08-07] Updated dependencies [@carbotaniuman]. +- [2023-04-06] Fixed DB contention issues [@carbotaniuman]. +- [2023-04-06] Make errors more useful [@carbotaniuman]. + ## [2.0.3] - 2022-02-17 ### Changed - [2022-02-17] Updated dependencies [@carbotaniuman]. @@ -411,7 +417,8 @@ This release contains many breaking changes! Of note are the changes to the cach ### Fixed - [2020-06-11] Tweaked logging configuration to reduce log file sizes by [@carbotaniuman]. -[Unreleased]: https://gitlab.com/mangadex/mangadex_at_home/-/compare/2.0.3...HEAD +[Unreleased]: https://gitlab.com/mangadex/mangadex_at_home/-/compare/2.0.4...HEAD +[2.0.4]: https://gitlab.com/mangadex/mangadex_at_home/-/compare/2.0.3...2.0.4 [2.0.3]: https://gitlab.com/mangadex/mangadex_at_home/-/compare/2.0.2...2.0.3 [2.0.2]: https://gitlab.com/mangadex/mangadex_at_home/-/compare/2.0.1...2.0.2 [2.0.1]: https://gitlab.com/mangadex/mangadex_at_home/-/compare/2.0.0...2.0.1 diff --git a/build.gradle b/build.gradle index 57ab508..5733c71 100644 --- a/build.gradle +++ b/build.gradle @@ -1,12 +1,14 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + plugins { id "jacoco" id "java" - id "org.jetbrains.kotlin.jvm" version "1.6.0" - id "org.jetbrains.kotlin.kapt" version "1.6.0" + id "org.jetbrains.kotlin.jvm" version "1.8.0" + id "org.jetbrains.kotlin.kapt" version "1.8.0" id "application" id "com.github.johnrengelman.shadow" version "7.0.0" id "com.diffplug.spotless" version "5.8.2" - id "net.afanasev.sekret" version "0.1.1" + id "net.afanasev.sekret" version "0.1.1-RC3" id "com.palantir.git-version" version "0.12.3" } @@ -28,18 +30,16 @@ configurations { dependencies { implementation "org.jetbrains.kotlin:kotlin-reflect" - compileOnly group: "net.afanasev", name: "sekret-annotation", version: "0.1.1" - implementation group: "commons-io", name: "commons-io", version: "2.11.0" - implementation group: "org.apache.commons", name: "commons-compress", version: "1.21" - implementation group: "ch.qos.logback", name: "logback-classic", version: "1.3.0-alpha4" + implementation group: "org.apache.commons", name: "commons-compress", version: "1.22" + implementation group: "ch.qos.logback", name: "logback-classic", version: "1.3.6" implementation group: "io.micrometer", name: "micrometer-registry-prometheus", version: "1.8.3" - implementation group: "com.maxmind.geoip2", name: "geoip2", version: "2.15.0" + implementation group: "com.maxmind.geoip2", name: "geoip2", version: "2.16.1" - implementation platform(group: "org.http4k", name: "http4k-bom", version: "4.19.3.0") - implementation platform(group: "com.fasterxml.jackson", name: "jackson-bom", version: "2.13.1") - implementation platform(group: "io.netty", name: "netty-bom", version: "4.1.74.Final") + implementation platform(group: "org.http4k", name: "http4k-bom", version: "4.41.3.0") + implementation platform(group: "com.fasterxml.jackson", name: "jackson-bom", version: "2.14.2") + implementation platform(group: "io.netty", name: "netty-bom", version: "4.1.91.Final") implementation group: "org.http4k", name: "http4k-core" implementation group: "org.http4k", name: "http4k-resilience4j" @@ -52,12 +52,12 @@ dependencies { implementation group: "org.http4k", name: "http4k-server-netty" implementation group: "io.netty", name: "netty-codec-haproxy" implementation group: "io.netty", name: "netty-transport-native-epoll", classifier: "linux-x86_64" - implementation group: "io.netty.incubator", name: "netty-incubator-transport-native-io_uring", version: "0.0.11.Final", classifier: "linux-x86_64" + implementation group: "io.netty.incubator", name: "netty-incubator-transport-native-io_uring", version: "0.0.19.Final", classifier: "linux-x86_64" testImplementation group: "org.http4k", name: "http4k-testing-kotest" - runtimeOnly group: "io.netty", name: "netty-tcnative-boringssl-static", version: "2.0.48.Final" + runtimeOnly group: "io.netty", name: "netty-tcnative-boringssl-static", version: "2.0.59.Final" implementation group: "com.zaxxer", name: "HikariCP", version: "4.0.3" - implementation group: "org.xerial", name: "sqlite-jdbc", version: "3.34.0" + implementation group: "org.xerial", name: "sqlite-jdbc", version: "3.41.2.1" implementation "org.ktorm:ktorm-core:$ktorm_version" implementation "org.ktorm:ktorm-jackson:$ktorm_version" @@ -66,10 +66,10 @@ dependencies { testImplementation "io.kotest:kotest-runner-junit5:$kotest_version" testImplementation "io.kotest:kotest-assertions-core:$kotest_version" - testImplementation "io.mockk:mockk:1.12.3" + testImplementation "io.mockk:mockk:1.13.4" } -tasks.withType(Test) { +tasks.withType(Test).configureEach { useJUnitPlatform() javaLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(8) @@ -91,14 +91,14 @@ kapt { } java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + toolchain { + languageVersion.set(JavaLanguageVersion.of(8)) + } } -tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { - kotlinOptions { +tasks.withType(KotlinCompile).configureEach { + compilerOptions { freeCompilerArgs = ["-Xjsr305=strict"] - jvmTarget = "1.8" } } diff --git a/gradle.properties b/gradle.properties index 643e533..df19bc2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ -kotest_version=5.1.0 -ktorm_version=3.4.1 -picocli_version=4.6.3 \ No newline at end of file +kotest_version=5.5.5 +ktorm_version=3.6.0 +picocli_version=4.7.1 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 62d4c05..7454180 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 00e33ed..e1bef7e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index fbd7c51..744e882 100755 --- a/gradlew +++ b/gradlew @@ -72,7 +72,7 @@ case "`uname`" in Darwin* ) darwin=true ;; - MINGW* ) + MSYS* | MINGW* ) msys=true ;; NONSTOP* ) @@ -130,7 +130,7 @@ fi if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath diff --git a/gradlew.bat b/gradlew.bat index 5093609..107acd3 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -54,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -64,21 +64,6 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line @@ -86,7 +71,7 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/src/main/kotlin/mdnet/cache/ImageStorage.kt b/src/main/kotlin/mdnet/cache/ImageStorage.kt index 3abab0c..51823aa 100644 --- a/src/main/kotlin/mdnet/cache/ImageStorage.kt +++ b/src/main/kotlin/mdnet/cache/ImageStorage.kt @@ -95,9 +95,14 @@ class ImageStorage( try { val toUpdate = HashSet() queue.drainTo(toUpdate) - val now = Instant.now() - LOGGER.info { "Updating LRU times for ${toUpdate.size} entries" } + if (toUpdate.isEmpty()) { + LOGGER.info { "Updating LRU times for ${toUpdate.size} entries" } + } else { + LOGGER.info { "Skipping empty LRU update" } + } + + val now = Instant.now() if (databaseLock.tryLock(500, TimeUnit.MILLISECONDS)) { try { diff --git a/src/main/kotlin/mdnet/settings/ClientSettings.kt b/src/main/kotlin/mdnet/settings/ClientSettings.kt index 34d162e..7d13860 100644 --- a/src/main/kotlin/mdnet/settings/ClientSettings.kt +++ b/src/main/kotlin/mdnet/settings/ClientSettings.kt @@ -20,7 +20,6 @@ package mdnet.settings import com.fasterxml.jackson.databind.PropertyNamingStrategies import com.fasterxml.jackson.databind.annotation.JsonNaming -import net.afanasev.sekret.Secret @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy::class) data class ClientSettings( @@ -33,7 +32,7 @@ data class ClientSettings( @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy::class) data class ServerSettings( - @field:Secret val secret: String, + val secret: String, val externalPort: Int = 0, val gracefulShutdownWaitSeconds: Int = 60, val hostname: String = "0.0.0.0", @@ -44,7 +43,11 @@ data class ServerSettings( val port: Int = 443, val threads: Int = 0, val enableProxyProtocol: Boolean = false, -) +) { + override fun toString(): String { + return "ServerSettings(secret=, externalPort=$externalPort, gracefulShutdownWaitSeconds=$gracefulShutdownWaitSeconds, hostname='$hostname', maxKilobitsPerSecond=$maxKilobitsPerSecond, externalMaxKilobitsPerSecond=$externalMaxKilobitsPerSecond, maxMebibytesPerHour=$maxMebibytesPerHour, externalIp=$externalIp, port=$port, threads=$threads, enableProxyProtocol=$enableProxyProtocol)" + } +} @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy::class) data class DevSettings( @@ -57,5 +60,9 @@ data class DevSettings( @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy::class) data class MetricsSettings( val enableGeoip: Boolean = false, - @field:Secret val geoipLicenseKey: String = "none" -) + val geoipLicenseKey: String = "none" +) { + override fun toString(): String { + return "MetricsSettings(enableGeoip=$enableGeoip, geoipLicenseKey=)" + } +} diff --git a/src/main/kotlin/mdnet/settings/PingResult.kt b/src/main/kotlin/mdnet/settings/PingResult.kt index 1ccd86f..eb5409d 100644 --- a/src/main/kotlin/mdnet/settings/PingResult.kt +++ b/src/main/kotlin/mdnet/settings/PingResult.kt @@ -20,7 +20,6 @@ package mdnet.settings import com.fasterxml.jackson.databind.PropertyNamingStrategies import com.fasterxml.jackson.databind.annotation.JsonNaming -import net.afanasev.sekret.Secret import org.http4k.core.Uri sealed class PingResult @@ -37,12 +36,13 @@ data class RemoteSettings( val latestBuild: Int, val url: Uri, val clientId: String, - @field:Secret val tokenKey: ByteArray, + val tokenKey: ByteArray, val compromised: Boolean, val paused: Boolean, val disableTokens: Boolean = false, val tls: TlsCert? ) : PingResult() { + override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false @@ -74,11 +74,19 @@ data class RemoteSettings( result = 31 * result + (tls?.hashCode() ?: 0) return result } + + override fun toString(): String { + return "RemoteSettings(imageServer=$imageServer, latestBuild=$latestBuild, url=$url, clientId='$clientId', tokenKey=, compromised=$compromised, paused=$paused, disableTokens=$disableTokens, tls=$tls)" + } } @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy::class) data class TlsCert( val createdAt: String, - @field:Secret val privateKey: String, - @field:Secret val certificate: String -) + val privateKey: String, + val certificate: String +) { + override fun toString(): String { + return "TlsCert(createdAt='$createdAt', privateKey=, certificate=)" + } +} diff --git a/src/main/kotlin/mdnet/settings/SettingsRequest.kt b/src/main/kotlin/mdnet/settings/SettingsRequest.kt index 974ec28..22a09e2 100644 --- a/src/main/kotlin/mdnet/settings/SettingsRequest.kt +++ b/src/main/kotlin/mdnet/settings/SettingsRequest.kt @@ -20,20 +20,27 @@ package mdnet.settings import com.fasterxml.jackson.databind.PropertyNamingStrategies import com.fasterxml.jackson.databind.annotation.JsonNaming -import net.afanasev.sekret.Secret @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy::class) data class SettingsRequest( - @field:Secret val secret: String, + val secret: String, val ipAddress: String?, val port: Int, val diskSpace: Long, val networkSpeed: Long, val buildVersion: Int, val tlsCreatedAt: String?, -) +) { + override fun toString(): String { + return "SettingsRequest(secret=, ipAddress=$ipAddress, port=$port, diskSpace=$diskSpace, networkSpeed=$networkSpeed, buildVersion=$buildVersion, tlsCreatedAt=$tlsCreatedAt)" + } +} @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy::class) data class LogoutRequest( - @field:Secret val secret: String, -) + val secret: String, +) { + override fun toString(): String { + return "LogoutRequest(secret=)" + } +} diff --git a/src/test/kotlin/mdnet/cache/ImageStorageTest.kt b/src/test/kotlin/mdnet/cache/ImageStorageTest.kt index 80bf8d8..465c2fb 100644 --- a/src/test/kotlin/mdnet/cache/ImageStorageTest.kt +++ b/src/test/kotlin/mdnet/cache/ImageStorageTest.kt @@ -32,7 +32,7 @@ import io.kotest.matchers.nulls.shouldNotBeNull import io.kotest.matchers.shouldBe import org.apache.commons.io.IOUtils import org.ktorm.database.Database -import kotlin.time.Duration +import kotlin.time.Duration.Companion.minutes import kotlin.time.ExperimentalTime class ImageStorageTest : FreeSpec() { @@ -177,7 +177,7 @@ class ImageStorageSlowTest : FreeSpec() { writer.stream.write(ByteArray(4096)) writer.commit(4096).shouldBeTrue() - eventually(Duration.minutes(5)) { + eventually(5.minutes) { imageStorage.size.shouldBeGreaterThan(0) } } @@ -193,7 +193,7 @@ class ImageStorageSlowTest : FreeSpec() { writer.commit(8192).shouldBeTrue() imageStorage.calculateSize() - eventually(Duration.minutes(5)) { + eventually(5.minutes) { imageStorage.size.shouldBeZero() } }