diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt index 6d693de786a..859269f102c 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt @@ -591,7 +591,6 @@ class UserSessionScope internal constructor( kaliumLogger = userScopedLogger ) private val featureSupport: FeatureSupport = FeatureSupportImpl( - kaliumConfigs, sessionManager.serverConfig().metaData.commonApiVersion.version ) @@ -1225,7 +1224,6 @@ class UserSessionScope internal constructor( private val pendingProposalScheduler: PendingProposalScheduler = PendingProposalSchedulerImpl( - kaliumConfigs, incrementalSyncRepository, lazy { mlsConversationRepository }, lazy { subconversationRepository } @@ -1979,7 +1977,11 @@ class UserSessionScope internal constructor( @OptIn(DelicateKaliumApi::class) private val isAllowedToRegisterMLSClient: IsAllowedToRegisterMLSClientUseCase - get() = IsAllowedToRegisterMLSClientUseCaseImpl(featureSupport, mlsPublicKeysRepository) + get() = IsAllowedToRegisterMLSClientUseCaseImpl( + featureSupport, + mlsPublicKeysRepository, + userConfigRepository + ) private val syncFeatureConfigsUseCase: SyncFeatureConfigsUseCase get() = SyncFeatureConfigsUseCaseImpl( diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/client/IsAllowedToRegisterMLSClientUseCase.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/client/IsAllowedToRegisterMLSClientUseCase.kt index 838619af9cb..3feb0cd3b8e 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/client/IsAllowedToRegisterMLSClientUseCase.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/client/IsAllowedToRegisterMLSClientUseCase.kt @@ -18,8 +18,10 @@ package com.wire.kalium.logic.feature.client +import com.wire.kalium.logic.configuration.UserConfigRepository import com.wire.kalium.logic.data.mlspublickeys.MLSPublicKeysRepository import com.wire.kalium.logic.featureFlags.FeatureSupport +import com.wire.kalium.logic.functional.fold import com.wire.kalium.logic.functional.isRight import com.wire.kalium.util.DelicateKaliumApi @@ -39,8 +41,12 @@ interface IsAllowedToRegisterMLSClientUseCase { internal class IsAllowedToRegisterMLSClientUseCaseImpl( private val featureSupport: FeatureSupport, private val mlsPublicKeysRepository: MLSPublicKeysRepository, + private val userConfigRepository: UserConfigRepository ) : IsAllowedToRegisterMLSClientUseCase { - override suspend operator fun invoke(): Boolean = - featureSupport.isMLSSupported && mlsPublicKeysRepository.getKeys().isRight() + override suspend operator fun invoke(): Boolean { + return featureSupport.isMLSSupported && + mlsPublicKeysRepository.getKeys().isRight() && + userConfigRepository.isMLSEnabled().fold({ false }, { isEnabled -> isEnabled }) + } } diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/message/PendingProposalScheduler.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/message/PendingProposalScheduler.kt index e7e000e3bdf..4993b062031 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/message/PendingProposalScheduler.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/message/PendingProposalScheduler.kt @@ -24,7 +24,6 @@ import com.wire.kalium.logic.data.conversation.SubconversationRepository import com.wire.kalium.logic.data.id.GroupID import com.wire.kalium.logic.data.sync.IncrementalSyncRepository import com.wire.kalium.logic.data.sync.IncrementalSyncStatus -import com.wire.kalium.logic.featureFlags.KaliumConfigs import com.wire.kalium.logic.functional.distinct import com.wire.kalium.logic.functional.onFailure import com.wire.kalium.logic.kaliumLogger @@ -63,7 +62,6 @@ interface PendingProposalScheduler { } internal class PendingProposalSchedulerImpl( - private val kaliumConfigs: KaliumConfigs, private val incrementalSyncRepository: IncrementalSyncRepository, private val mlsConversationRepository: Lazy, private val subconversationRepository: Lazy, @@ -82,7 +80,7 @@ internal class PendingProposalSchedulerImpl( commitPendingProposalsScope.launch() { incrementalSyncRepository.incrementalSyncState.collectLatest { syncState -> ensureActive() - if (syncState == IncrementalSyncStatus.Live && kaliumConfigs.isMLSSupportEnabled) { + if (syncState == IncrementalSyncStatus.Live) { startCommittingPendingProposals() } } diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/featureFlags/FeatureSupportImpl.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/featureFlags/FeatureSupportImpl.kt index cb11a6b34e1..fd37ac693ae 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/featureFlags/FeatureSupportImpl.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/featureFlags/FeatureSupportImpl.kt @@ -24,9 +24,8 @@ interface FeatureSupport { @Suppress("MagicNumber") class FeatureSupportImpl( - kaliumConfigs: KaliumConfigs, apiVersion: Int ) : FeatureSupport { - override val isMLSSupported: Boolean = kaliumConfigs.isMLSSupportEnabled && apiVersion >= 5 + override val isMLSSupported: Boolean = apiVersion >= 6 } diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/featureFlags/KaliumConfigs.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/featureFlags/KaliumConfigs.kt index dc90b3b111f..1ca24af381a 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/featureFlags/KaliumConfigs.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/featureFlags/KaliumConfigs.kt @@ -26,7 +26,6 @@ import kotlin.time.Duration.Companion.hours data class KaliumConfigs( val forceConstantBitrateCalls: Boolean = false, val fileRestrictionState: BuildFileRestrictionState = BuildFileRestrictionState.NoRestriction, - var isMLSSupportEnabled: Boolean = true, // Disabling db-encryption will crash on android-api level below 30 val shouldEncryptData: Boolean = true, val encryptProteusStorage: Boolean = false, diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/client/IsAllowedToRegisterMLSClientUseCaseTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/client/IsAllowedToRegisterMLSClientUseCaseTest.kt new file mode 100644 index 00000000000..dfa49376049 --- /dev/null +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/client/IsAllowedToRegisterMLSClientUseCaseTest.kt @@ -0,0 +1,172 @@ +/* + * Wire + * Copyright (C) 2024 Wire Swiss GmbH + * + * This program 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. + * + * This program 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 this program. If not, see http://www.gnu.org/licenses/. + */ +package com.wire.kalium.logic.feature.client + +import com.wire.kalium.logic.CoreFailure +import com.wire.kalium.logic.StorageFailure +import com.wire.kalium.logic.configuration.UserConfigRepository +import com.wire.kalium.logic.data.mls.MLSPublicKeys +import com.wire.kalium.logic.data.mlspublickeys.MLSPublicKeysRepository +import com.wire.kalium.logic.featureFlags.FeatureSupport +import com.wire.kalium.logic.functional.Either +import io.mockative.Mock +import io.mockative.coEvery +import io.mockative.every +import io.mockative.mock +import kotlinx.coroutines.test.runTest +import kotlin.test.Test +import kotlin.test.assertEquals + +class IsAllowedToRegisterMLSClientUseCaseTest { + + @Test + fun givenAllMlsConditionsAreMet_whenUseCaseInvoked_returnsTrue() = runTest { + // given + val (_, isAllowedToRegisterMLSClientUseCase) = Arrangement() + .withMlsFeatureFlag(true) + .withUserConfigMlsEnabled(true) + .withGetPublicKeysSuccessful() + .arrange() + + // when + val result = isAllowedToRegisterMLSClientUseCase() + + // then + assertEquals(true, result) + } + + @Test + fun givenMlsFeatureFlagDisabled_whenUseCaseInvoked_returnsFalse() = runTest { + // given + val (_, isAllowedToRegisterMLSClientUseCase) = Arrangement() + .withMlsFeatureFlag(false) + .withUserConfigMlsEnabled(true) + .withGetPublicKeysSuccessful() + .arrange() + + // when + val result = isAllowedToRegisterMLSClientUseCase() + + // then + assertEquals(false, result) + } + + @Test + fun givenUserConfigMlsDisabled_whenUseCaseInvoked_returnsFalse() = runTest { + // given + val (_, isAllowedToRegisterMLSClientUseCase) = Arrangement() + .withMlsFeatureFlag(true) + .withUserConfigMlsEnabled(false) + .withGetPublicKeysSuccessful() + .arrange() + + // when + val result = isAllowedToRegisterMLSClientUseCase() + + // then + assertEquals(false, result) + } + + @Test + fun givenPublicKeysFailure_whenUseCaseInvoked_returnsFalse() = runTest { + // given + val (_, isAllowedToRegisterMLSClientUseCase) = Arrangement() + .withMlsFeatureFlag(true) + .withUserConfigMlsEnabled(true) + .withGetPublicKeysFailed() + .arrange() + + // when + val result = isAllowedToRegisterMLSClientUseCase() + + // then + assertEquals(false, result) + } + + @Test + fun givenUserConfigDataNotFound_whenUseCaseInvoked_returnsFalse() = runTest { + // given + val (_, isAllowedToRegisterMLSClientUseCase) = Arrangement() + .withMlsFeatureFlag(true) + .withUserConfigDataNotFound() + .withGetPublicKeysFailed() + .arrange() + + // when + val result = isAllowedToRegisterMLSClientUseCase() + + // then + assertEquals(false, result) + } + + + private class Arrangement { + @Mock + val featureSupport = mock(FeatureSupport::class) + + @Mock + val mlsPublicKeysRepository = mock(MLSPublicKeysRepository::class) + + @Mock + val userConfigRepository = mock(UserConfigRepository::class) + + fun withMlsFeatureFlag(enabled: Boolean) = apply { + every { + featureSupport.isMLSSupported + }.returns(enabled) + } + + fun withUserConfigMlsEnabled(enabled: Boolean) = apply { + every { + userConfigRepository.isMLSEnabled() + }.returns(Either.Right(enabled)) + } + + fun withUserConfigDataNotFound() = apply { + every { + userConfigRepository.isMLSEnabled() + }.returns(Either.Left(StorageFailure.DataNotFound)) + } + + suspend fun withGetPublicKeysSuccessful() = apply { + coEvery { + mlsPublicKeysRepository.getKeys() + }.returns(Either.Right(MLS_PUBLIC_KEY)) + } + + suspend fun withGetPublicKeysFailed() = apply { + coEvery { + mlsPublicKeysRepository.getKeys() + }.returns(Either.Left(CoreFailure.Unknown(Throwable("an error")))) + } + + fun arrange() = this to IsAllowedToRegisterMLSClientUseCaseImpl( + featureSupport = featureSupport, + mlsPublicKeysRepository = mlsPublicKeysRepository, + userConfigRepository = userConfigRepository + ) + + companion object { + val MLS_PUBLIC_KEY = MLSPublicKeys( + removal = mapOf( + "ed25519" to "gRNvFYReriXbzsGu7zXiPtS8kaTvhU1gUJEV9rdFHVw=" + ) + ) + } + } +} diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/message/PendingProposalSchedulerTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/message/PendingProposalSchedulerTest.kt index b8607eaee40..05215c911db 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/message/PendingProposalSchedulerTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/message/PendingProposalSchedulerTest.kt @@ -95,22 +95,6 @@ class PendingProposalSchedulerTest { }.wasInvoked(once) } - @Test - fun givenMLSSupportIsDisabled_whenSyncIsLive_thenPendingProposalIsNotCommitted() = runTest(TestKaliumDispatcher.default) { - val (arrangement, _) = Arrangement() - .withScheduledProposalTimers(listOf(ProposalTimer(TestConversation.GROUP_ID, Arrangement.INSTANT_PAST))) - .withCommitPendingProposalsSuccessful() - .arrange() - - arrangement.kaliumConfigs.isMLSSupportEnabled = false - arrangement.incrementalSyncRepository.updateIncrementalSyncState(IncrementalSyncStatus.Live) - yield() - - coVerify { - arrangement.mlsConversationRepository.commitPendingProposals(eq(TestConversation.GROUP_ID)) - }.wasNotInvoked() - } - @Test fun givenNonExpiredProposalTimer_whenSyncFinishes_thenPendingProposalIsNotCommitted() = runTest(TestKaliumDispatcher.default) { val (arrangement, _) = Arrangement() @@ -182,8 +166,6 @@ class PendingProposalSchedulerTest { private class Arrangement { - val kaliumConfigs = KaliumConfigs() - val incrementalSyncRepository = InMemoryIncrementalSyncRepository() @Mock @@ -193,7 +175,6 @@ class PendingProposalSchedulerTest { val subconversationRepository = mock(SubconversationRepository::class) val pendingProposalScheduler = PendingProposalSchedulerImpl( - kaliumConfigs, incrementalSyncRepository, lazy { mlsConversationRepository }, lazy { subconversationRepository }, diff --git a/monkeys/src/main/kotlin/com/wire/kalium/monkeys/homeDirectory.kt b/monkeys/src/main/kotlin/com/wire/kalium/monkeys/homeDirectory.kt index 86b973a04c3..5ad0ef16e75 100644 --- a/monkeys/src/main/kotlin/com/wire/kalium/monkeys/homeDirectory.kt +++ b/monkeys/src/main/kotlin/com/wire/kalium/monkeys/homeDirectory.kt @@ -29,12 +29,14 @@ fun coreLogic( rootPath: String, ): CoreLogic { val coreLogic = CoreLogic( - rootPath, kaliumConfigs = KaliumConfigs( + rootPath = rootPath, + kaliumConfigs = KaliumConfigs( developmentApiEnabled = true, encryptProteusStorage = true, - isMLSSupportEnabled = true, wipeOnDeviceRemoval = true, - ), userAgent = "Wire Infinite Monkeys", useInMemoryStorage = true + ), + userAgent = "Wire Infinite Monkeys", + useInMemoryStorage = true ) coreLogic.updateApiVersionsScheduler.scheduleImmediateApiVersionUpdate() return coreLogic diff --git a/tango-tests/src/integrationTest/kotlin/PocIntegrationTest.kt b/tango-tests/src/integrationTest/kotlin/PocIntegrationTest.kt index ffcc205ca7a..270ea80e43e 100644 --- a/tango-tests/src/integrationTest/kotlin/PocIntegrationTest.kt +++ b/tango-tests/src/integrationTest/kotlin/PocIntegrationTest.kt @@ -231,7 +231,6 @@ class PocIntegrationTest { kaliumConfigs = KaliumConfigs( developmentApiEnabled = true, encryptProteusStorage = true, - isMLSSupportEnabled = true, wipeOnDeviceRemoval = true, mockedRequests = mockedRequests, mockNetworkStateObserver = TestNetworkStateObserver.DEFAULT_TEST_NETWORK_STATE_OBSERVER,