diff --git a/buildSrc/src/main/kotlin/Config.kt b/buildSrc/src/main/kotlin/Config.kt index e8d47ea9..b8c1bb04 100644 --- a/buildSrc/src/main/kotlin/Config.kt +++ b/buildSrc/src/main/kotlin/Config.kt @@ -22,7 +22,7 @@ object Config { const val minSdk = 23 const val targetSdk = 33 const val testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - const val versionName = "1.0.3" + const val versionName = "1.0.4" const val archivesBaseName = "ProtonDrive-$versionName" val resourceConfigurations = listOf("en") } diff --git a/drive/base/domain/src/main/kotlin/me/proton/core/drive/base/domain/exception/InvalidFieldException.kt b/drive/base/domain/src/main/kotlin/me/proton/core/drive/base/domain/exception/InvalidFieldException.kt index ac78b4ae..772dda93 100644 --- a/drive/base/domain/src/main/kotlin/me/proton/core/drive/base/domain/exception/InvalidFieldException.kt +++ b/drive/base/domain/src/main/kotlin/me/proton/core/drive/base/domain/exception/InvalidFieldException.kt @@ -24,4 +24,4 @@ fun requireField(value: Boolean, lazyMessage: () -> Any) { val message = lazyMessage() throw InvalidFieldException(message.toString()) } -} \ No newline at end of file +} diff --git a/drive/drivelink-crypto/domain/src/main/kotlin/me/proton/core/drive/drivelink/crypto/domain/usecase/DecryptDriveLinks.kt b/drive/drivelink-crypto/domain/src/main/kotlin/me/proton/core/drive/drivelink/crypto/domain/usecase/DecryptDriveLinks.kt index 7508b0ee..660f26aa 100644 --- a/drive/drivelink-crypto/domain/src/main/kotlin/me/proton/core/drive/drivelink/crypto/domain/usecase/DecryptDriveLinks.kt +++ b/drive/drivelink-crypto/domain/src/main/kotlin/me/proton/core/drive/drivelink/crypto/domain/usecase/DecryptDriveLinks.kt @@ -21,12 +21,15 @@ package me.proton.core.drive.drivelink.crypto.domain.usecase import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.supervisorScope +import me.proton.core.drive.base.domain.log.LogTag +import me.proton.core.drive.base.domain.log.logId import me.proton.core.drive.base.domain.provider.ConfigurationProvider import me.proton.core.drive.cryptobase.domain.usecase.UnlockKey import me.proton.core.drive.drivelink.domain.entity.DriveLink import me.proton.core.drive.key.domain.extension.keyHolder import me.proton.core.drive.key.domain.usecase.GetLinkParentKey import me.proton.core.drive.link.domain.entity.LinkId +import me.proton.core.util.kotlin.CoreLogger import java.util.concurrent.ConcurrentHashMap import javax.inject.Inject @@ -46,7 +49,14 @@ class DecryptDriveLinks @Inject constructor( val deferred = links.chunkedInto(configurationProvider.decryptionInParallel).map { driveLinks -> async { driveLinks.forEach { link -> - decryptedLinks[link.id] = decryptDriveLink(unlockedKey, link).getOrNull() + decryptedLinks[link.id] = decryptDriveLink(unlockedKey, link) + .onFailure { error -> + CoreLogger.e( + LogTag.ENCRYPTION, + error, + "There was an error decrypting drive link: ${link.id.id.logId()}" + ) + }.getOrNull() } } } diff --git a/drive/drivelink/domain/src/main/kotlin/me/proton/core/drive/drivelink/domain/usecase/GetLastModified.kt b/drive/drivelink/domain/src/main/kotlin/me/proton/core/drive/drivelink/domain/usecase/GetLastModified.kt index d5bf576a..a6eb593a 100644 --- a/drive/drivelink/domain/src/main/kotlin/me/proton/core/drive/drivelink/domain/usecase/GetLastModified.kt +++ b/drive/drivelink/domain/src/main/kotlin/me/proton/core/drive/drivelink/domain/usecase/GetLastModified.kt @@ -20,8 +20,11 @@ package me.proton.core.drive.drivelink.domain.usecase import me.proton.core.drive.base.domain.entity.CryptoProperty import me.proton.core.drive.base.domain.entity.TimestampS import me.proton.core.drive.base.domain.formatter.DateTimeFormatter +import me.proton.core.drive.base.domain.log.LogTag +import me.proton.core.drive.base.domain.log.logId import me.proton.core.drive.drivelink.domain.entity.DriveLink import me.proton.core.drive.file.base.domain.extension.toXAttr +import me.proton.core.util.kotlin.CoreLogger import javax.inject.Inject class GetLastModified @Inject constructor( @@ -30,7 +33,18 @@ class GetLastModified @Inject constructor( operator fun invoke(driveLink: DriveLink): TimestampS { if (driveLink.cryptoXAttr !is CryptoProperty.Decrypted) return driveLink.lastModified val xAttrString = driveLink.cryptoXAttr.value ?: return driveLink.lastModified - return dateTimeFormatter.parseFromIso8601String(iso8601 = xAttrString.toXAttr().common.modificationTime) - .getOrNull() ?: driveLink.lastModified + xAttrString.toXAttr().onSuccess { xAttr -> + return dateTimeFormatter.parseFromIso8601String(iso8601 = xAttr.common.modificationTime) + .getOrNull() ?: driveLink.lastModified + }.onFailure { error -> + CoreLogger.d( + LogTag.ENCRYPTION, + error, + "There was an error parsing xAttr of drive link: ${driveLink.id.id.logId()}" + ) + } + return driveLink.lastModified + + } } diff --git a/drive/file/base/domain/src/main/kotlin/me/proton/core/drive/file/base/domain/extension/String.kt b/drive/file/base/domain/src/main/kotlin/me/proton/core/drive/file/base/domain/extension/String.kt deleted file mode 100644 index b0b43020..00000000 --- a/drive/file/base/domain/src/main/kotlin/me/proton/core/drive/file/base/domain/extension/String.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2022-2023 Proton AG. - * This file is part of Proton Core. - * - * Proton Core is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Proton Core is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Proton Core. If not, see . - */ -package me.proton.core.drive.file.base.domain.extension - -import kotlinx.serialization.decodeFromString -import kotlinx.serialization.json.Json -import me.proton.core.drive.file.base.domain.entity.XAttr - -fun String.toXAttr() = Json.decodeFromString(this) diff --git a/drive/file/base/domain/src/main/kotlin/me/proton/core/drive/file/base/domain/extension/XAttr.kt b/drive/file/base/domain/src/main/kotlin/me/proton/core/drive/file/base/domain/extension/XAttr.kt index 946d5b01..a447e6ae 100644 --- a/drive/file/base/domain/src/main/kotlin/me/proton/core/drive/file/base/domain/extension/XAttr.kt +++ b/drive/file/base/domain/src/main/kotlin/me/proton/core/drive/file/base/domain/extension/XAttr.kt @@ -17,7 +17,19 @@ */ package me.proton.core.drive.file.base.domain.extension +import kotlinx.serialization.SerializationException +import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json import me.proton.core.drive.file.base.domain.entity.XAttr -fun XAttr.asJson(): String = Json.encodeToString(XAttr.serializer(), this) +private val json = Json { + ignoreUnknownKeys = true +} + +fun String.toXAttr(): Result = try { + Result.success(json.decodeFromString(this)) +} catch (e: SerializationException) { + Result.failure(e) +} + +fun XAttr.asJson(): String = json.encodeToString(XAttr.serializer(), this) diff --git a/drive/file/base/domain/src/test/kotlin/me/proton/core/drive/file/base/domain/extension/XAttrKtTest.kt b/drive/file/base/domain/src/test/kotlin/me/proton/core/drive/file/base/domain/extension/XAttrKtTest.kt new file mode 100644 index 00000000..1e002571 --- /dev/null +++ b/drive/file/base/domain/src/test/kotlin/me/proton/core/drive/file/base/domain/extension/XAttrKtTest.kt @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2023 Proton AG. + * This file is part of Proton Core. + * + * Proton Core is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Proton Core is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Proton Core. If not, see . + */ + +package me.proton.core.drive.file.base.domain.extension + +import me.proton.core.drive.file.base.domain.entity.XAttr +import org.intellij.lang.annotations.Language +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Test + +class XAttrKtTest { + + @Language("json") + val json = + """{"Common": {"ModificationTime": "ModificationTime", "unknown_key": null}}""" + + @Test + fun deserialization() { + assertEquals( + Result.success( + XAttr( + common = XAttr.Common( + modificationTime = "ModificationTime" + ) + ) + ), json.toXAttr() + ) + } + + @Test + fun serialization() { + val xAttr = XAttr(common = XAttr.Common(modificationTime = "modificationTime")) + assertEquals(xAttr, xAttr.asJson().toXAttr().getOrNull()) + } + + @Test + fun `fails with bad input`() { + assertTrue("bad input".toXAttr().isFailure) + } +} \ No newline at end of file diff --git a/drive/preview/src/main/kotlin/me/proton/core/drive/files/preview/presentation/component/PreviewEmpty.kt b/drive/preview/src/main/kotlin/me/proton/core/drive/files/preview/presentation/component/PreviewEmpty.kt index dc8c57e0..3ed32ef4 100644 --- a/drive/preview/src/main/kotlin/me/proton/core/drive/files/preview/presentation/component/PreviewEmpty.kt +++ b/drive/preview/src/main/kotlin/me/proton/core/drive/files/preview/presentation/component/PreviewEmpty.kt @@ -65,4 +65,4 @@ fun PreviewEmpty( ) } } -} \ No newline at end of file +} diff --git a/drive/preview/src/test/kotlin/me/proton/core/drive/files/preview/presentation/component/TextPreviewTest.kt b/drive/preview/src/test/kotlin/me/proton/core/drive/files/preview/presentation/component/TextPreviewTest.kt index f76bde25..3a7a4c71 100644 --- a/drive/preview/src/test/kotlin/me/proton/core/drive/files/preview/presentation/component/TextPreviewTest.kt +++ b/drive/preview/src/test/kotlin/me/proton/core/drive/files/preview/presentation/component/TextPreviewTest.kt @@ -15,7 +15,6 @@ * You should have received a copy of the GNU General Public License * along with Proton Core. If not, see . */ - package me.proton.core.drive.files.preview.presentation.component import org.junit.Test @@ -56,4 +55,4 @@ class TextPreviewTest { assertEquals(listOf("first line", "", "second line"), content) } -} \ No newline at end of file +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8f79040c..1f044bfe 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -29,7 +29,7 @@ androidx-work = "2.7.1" # Coil coil = "1.4.0" # Core -core = "9.9.1" +core = "9.9.3" # Dagger dagger = "2.44.2" # Gradle