diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/FeatureFlagManagerImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/FeatureFlagManagerImpl.kt index d27c95781..947dabb1d 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/FeatureFlagManagerImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/FeatureFlagManagerImpl.kt @@ -3,10 +3,12 @@ package com.x8bit.bitwarden.data.platform.manager import com.x8bit.bitwarden.data.platform.datasource.disk.model.ServerConfig import com.x8bit.bitwarden.data.platform.manager.model.FlagKey import com.x8bit.bitwarden.data.platform.repository.ServerConfigRepository +import com.x8bit.bitwarden.data.platform.util.isServerVersionAtLeast import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map private const val CIPHER_KEY_ENCRYPTION_KEY = "enableCipherKeyEncryption" +private const val CIPHER_KEY_ENC_MIN_SERVER_VERSION = "2024.2.0" /** * Primary implementation of [FeatureFlagManager]. @@ -16,7 +18,13 @@ class FeatureFlagManagerImpl( ) : FeatureFlagManager { override val sdkFeatureFlags: Map - get() = mapOf(CIPHER_KEY_ENCRYPTION_KEY to true) + get() = mapOf( + CIPHER_KEY_ENCRYPTION_KEY to + isServerVersionAtLeast( + serverConfigRepository.serverConfigStateFlow.value, + CIPHER_KEY_ENC_MIN_SERVER_VERSION, + ), + ) override fun getFeatureFlagFlow(key: FlagKey): Flow = serverConfigRepository diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/util/ServerVersionUtils.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/util/ServerVersionUtils.kt new file mode 100644 index 000000000..6d5ed31e2 --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/util/ServerVersionUtils.kt @@ -0,0 +1,51 @@ +package com.x8bit.bitwarden.data.platform.util + +import com.x8bit.bitwarden.data.platform.datasource.disk.model.ServerConfig +import kotlin.text.split +import kotlin.text.toIntOrNull + +private const val VERSION_SEPARATOR = "." +private const val SUFFIX_SEPARATOR = "-" + +/** + * Checks if the server version is greater than another provided version, returns true if it is. + */ +fun isServerVersionAtLeast(serverConfig: ServerConfig?, version: String): Boolean { + val serverVersion = serverConfig + ?.serverData + ?.version + + if (serverVersion.isNullOrEmpty() || version.isEmpty()) { + return false + } + + val serverVersionParts = getVersionComponents(serverVersion) + val otherVersionParts = getVersionComponents(version) + + if (serverVersionParts.isNullOrEmpty() || otherVersionParts.isNullOrEmpty()) { + return false + } + + // Must iterate through all indices to establish if versions are equal + for (i in serverVersionParts.indices) { + val serverPart = serverVersionParts.getOrNull(i)?.toIntOrNull() ?: 0 + val otherPart = otherVersionParts.getOrNull(i)?.toIntOrNull() ?: 0 + + if (serverPart > otherPart) { + return true + } else if (serverPart < otherPart) { + return false + } + } + + // Versions are equal + return true +} + +/** + * Extracts the version components from a version string, disregarding any suffixes. + */ +private fun getVersionComponents(version: String?): List? { + val versionComponents = version?.split(SUFFIX_SEPARATOR)?.first() + return versionComponents?.split(VERSION_SEPARATOR) +} diff --git a/app/src/test/java/com/x8bit/bitwarden/data/platform/manager/FeatureFlagManagerTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/platform/manager/FeatureFlagManagerTest.kt index 8f5466c8b..1c7a6f70d 100644 --- a/app/src/test/java/com/x8bit/bitwarden/data/platform/manager/FeatureFlagManagerTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/data/platform/manager/FeatureFlagManagerTest.kt @@ -7,6 +7,7 @@ import com.x8bit.bitwarden.data.platform.datasource.network.model.ConfigResponse import com.x8bit.bitwarden.data.platform.datasource.network.model.ConfigResponseJson.ServerJson import com.x8bit.bitwarden.data.platform.manager.model.FlagKey import com.x8bit.bitwarden.data.platform.repository.util.FakeServerConfigRepository +import com.x8bit.bitwarden.data.platform.util.isServerVersionAtLeast import kotlinx.coroutines.test.runTest import kotlinx.serialization.json.JsonPrimitive import org.junit.Test @@ -33,6 +34,53 @@ class FeatureFlagManagerTest { assertEquals(expected, actual) } + @Test + fun `server version is at least supplied version`() { + val result = + isServerVersionAtLeast( + fakeServerConfigRepository.serverConfigStateFlow.value, + "2024.2.0", + ) + + // This relies on the fake server version being "2024.7.0" + assertTrue(result) + } + + @Test + fun `server version is not at least supplied version`() { + val result = + isServerVersionAtLeast( + fakeServerConfigRepository.serverConfigStateFlow.value, + "2024.12.0-suffix", + ) + + // This relies on the fake server version being "2024.7.0" + assertFalse(result) + } + + @Test + fun `server version is the same as supplied version`() { + val result = + isServerVersionAtLeast( + fakeServerConfigRepository.serverConfigStateFlow.value, + "2024.7.0", + ) + + // This relies on the fake server version being "2024.7.0" + assertTrue(result) + } + + @Test + fun `server version is not the same as blank supplied version`() { + val result = + isServerVersionAtLeast( + fakeServerConfigRepository.serverConfigStateFlow.value, + "", + ) + + assertFalse(result) + } + @Test fun `ServerConfigRepository flow with value should trigger new flags`() = runTest { fakeServerConfigRepository.serverConfigValue = null