From c5c0ef16709873222a1eeee4e4f49734c9f2df46 Mon Sep 17 00:00:00 2001 From: Mohamad Jaara Date: Tue, 7 Jan 2025 14:18:13 +0100 Subject: [PATCH 1/5] add changes for the crl revocation check --- .../logic/data/e2ei/RevocationListChecker.kt | 71 +++++ .../CertificateRevocationListCheckWorker.kt | 30 +- .../data/e2ei/RevocationListCheckerTest.kt | 288 ++++++++++++++++++ ...ertificateRevocationListCheckWorkerTest.kt | 80 +++-- 4 files changed, 407 insertions(+), 62 deletions(-) create mode 100644 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/e2ei/RevocationListChecker.kt create mode 100644 logic/src/commonTest/kotlin/com/wire/kalium/logic/data/e2ei/RevocationListCheckerTest.kt diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/e2ei/RevocationListChecker.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/e2ei/RevocationListChecker.kt new file mode 100644 index 00000000000..a56b28876d6 --- /dev/null +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/e2ei/RevocationListChecker.kt @@ -0,0 +1,71 @@ +/* + * 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.data.e2ei + +import com.wire.kalium.logic.CoreFailure +import com.wire.kalium.logic.E2EIFailure +import com.wire.kalium.logic.configuration.UserConfigRepository +import com.wire.kalium.logic.data.client.MLSClientProvider +import com.wire.kalium.logic.data.id.CurrentClientIdProvider +import com.wire.kalium.logic.featureFlags.FeatureSupport +import com.wire.kalium.logic.functional.Either +import com.wire.kalium.logic.functional.flatMap +import com.wire.kalium.logic.functional.getOrElse +import com.wire.kalium.logic.functional.map +import com.wire.kalium.logic.kaliumLogger + +/** + * Use case to check if the CRL is expired and if so, register CRL and update conversation statuses if there is a change. + */ +internal interface RevocationListChecker { + suspend fun check(url: String): Either +} + +internal class RevocationListCheckerImpl( + private val certificateRevocationListRepository: CertificateRevocationListRepository, + private val currentClientIdProvider: CurrentClientIdProvider, + private val mlsClientProvider: MLSClientProvider, + private val featureSupport: FeatureSupport, + private val userConfigRepository: UserConfigRepository, +) : RevocationListChecker { + private val logger = kaliumLogger.withTextTag("CheckRevocationListUseCase") + override suspend fun check(url: String): Either { + val isE2EIEnabled = getIsE2EIEnabled() + + return if (isE2EIEnabled) { + logger.i("checking crl url: $url") + certificateRevocationListRepository.getClientDomainCRL(url).flatMap { + currentClientIdProvider().flatMap { clientId -> + mlsClientProvider.getCoreCrypto(clientId).map { coreCrypto -> + logger.i("registering crl..") + coreCrypto.registerCrl(url, it).run { + this.expiration + } + } + } + } + } else Either.Left(E2EIFailure.Disabled) + } + + private fun getIsE2EIEnabled() = userConfigRepository.getE2EISettings().flatMap { settings -> + userConfigRepository.isMLSEnabled() + .map { + it && settings.isRequired && featureSupport.isMLSSupported + } + }.getOrElse(false) +} diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/e2ei/CertificateRevocationListCheckWorker.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/e2ei/CertificateRevocationListCheckWorker.kt index b59c4798697..d5132c3f3a6 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/e2ei/CertificateRevocationListCheckWorker.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/e2ei/CertificateRevocationListCheckWorker.kt @@ -19,46 +19,40 @@ package com.wire.kalium.logic.feature.e2ei import com.wire.kalium.logger.KaliumLogger import com.wire.kalium.logic.data.e2ei.CertificateRevocationListRepository +import com.wire.kalium.logic.data.e2ei.RevocationListChecker import com.wire.kalium.logic.data.sync.IncrementalSyncRepository import com.wire.kalium.logic.data.sync.IncrementalSyncStatus -import com.wire.kalium.logic.feature.e2ei.usecase.CheckRevocationListUseCase import com.wire.kalium.logic.functional.map -import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.first import kotlinx.datetime.Clock /** - * This worker will wait until the sync is done and then check the CRLs if needed. + * This use case will wait until the sync is done and then check the CRLs if needed. * - */ -interface CertificateRevocationListCheckWorker { - suspend fun execute() -} - -/** - * Base implementation of [CertificateRevocationListCheckWorker]. + * Base implementation of [SyncCertificateRevocationListUseCase]. * @param certificateRevocationListRepository The CRL repository. * @param incrementalSyncRepository The incremental sync repository. - * @param checkRevocationList The check revocation list use case. + * @param revocationListChecker The check revocation list use case. * */ -internal class CertificateRevocationListCheckWorkerImpl( +class SyncCertificateRevocationListUseCase internal constructor( private val certificateRevocationListRepository: CertificateRevocationListRepository, private val incrementalSyncRepository: IncrementalSyncRepository, - private val checkRevocationList: CheckRevocationListUseCase, + private val revocationListChecker: RevocationListChecker, kaliumLogger: KaliumLogger -) : CertificateRevocationListCheckWorker { +) { private val logger = kaliumLogger.withTextTag("CertificateRevocationListCheckWorker") - override suspend fun execute() { + suspend operator fun invoke() { logger.d("Starting to monitor") incrementalSyncRepository.incrementalSyncState - .filter { it is IncrementalSyncStatus.Live } - .collect { + .first { it is IncrementalSyncStatus.Live } + .let { logger.i("Checking certificate revocation list (CRL)..") certificateRevocationListRepository.getCRLs()?.cRLWithExpirationList?.forEach { crl -> if (crl.expiration < Clock.System.now().epochSeconds.toULong()) { - checkRevocationList(crl.url).map { newExpirationTime -> + revocationListChecker.check(crl.url).map { newExpirationTime -> newExpirationTime?.let { certificateRevocationListRepository.addOrUpdateCRL(crl.url, it) } diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/e2ei/RevocationListCheckerTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/e2ei/RevocationListCheckerTest.kt new file mode 100644 index 00000000000..b469eb49dbc --- /dev/null +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/e2ei/RevocationListCheckerTest.kt @@ -0,0 +1,288 @@ +/* + * 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.data.e2ei + +import com.wire.kalium.cryptography.CoreCryptoCentral +import com.wire.kalium.cryptography.CrlRegistration +import com.wire.kalium.logic.CoreFailure +import com.wire.kalium.logic.E2EIFailure +import com.wire.kalium.logic.configuration.E2EISettings +import com.wire.kalium.logic.configuration.UserConfigRepository +import com.wire.kalium.logic.data.client.MLSClientProvider +import com.wire.kalium.logic.data.id.CurrentClientIdProvider +import com.wire.kalium.logic.featureFlags.FeatureSupport +import com.wire.kalium.logic.framework.TestClient +import com.wire.kalium.logic.functional.Either +import com.wire.kalium.logic.functional.right +import com.wire.kalium.logic.util.shouldFail +import com.wire.kalium.logic.util.shouldSucceed +import com.wire.kalium.util.DateTimeUtil +import io.ktor.utils.io.core.toByteArray +import io.mockative.Mock +import io.mockative.any +import io.mockative.coEvery +import io.mockative.coVerify +import io.mockative.eq +import io.mockative.every +import io.mockative.mock +import io.mockative.once +import kotlinx.coroutines.test.runTest +import kotlin.test.Test +import kotlin.test.assertEquals + +class RevocationListCheckerTest { + + @Test + fun givenE2EIRepositoryReturnsFailure_whenRunningUseCase_thenDoNotRegisterCrlAndReturnFailure() = + runTest { + val (arrangement, revocationListChecker) = Arrangement() + .withE2EIEnabledAndMLSEnabled(true) + .withE2EIRepositoryFailure() + .arrange() + + val result = revocationListChecker.check(DUMMY_URL) + + result.shouldFail() + coVerify { + arrangement.certificateRevocationListRepository.getClientDomainCRL(any()) + }.wasInvoked(once) + + coVerify { + arrangement.coreCrypto.registerCrl(any(), any()) + }.wasNotInvoked() + } + + @Test + fun givenCurrentClientIdProviderFailure_whenRunningUseCase_thenDoNotRegisterCrlAndReturnFailure() = + runTest { + val (arrangement, revocationListChecker) = Arrangement() + .withE2EIEnabledAndMLSEnabled(true) + .withE2EIRepositorySuccess() + .withCurrentClientIdProviderFailure() + .arrange() + + val result = revocationListChecker.check(DUMMY_URL) + + result.shouldFail() + coVerify { + arrangement.certificateRevocationListRepository.getClientDomainCRL(any()) + }.wasInvoked(once) + + coVerify { + arrangement.currentClientIdProvider.invoke() + }.wasInvoked(once) + + coVerify { + arrangement.coreCrypto.registerCrl(any(), any()) + }.wasNotInvoked() + } + + @Test + fun givenMlsClientProviderFailure_whenRunningUseCase_thenDoNotRegisterCrlAndReturnFailure() = + runTest { + val (arrangement, revocationListChecker) = Arrangement() + .withE2EIEnabledAndMLSEnabled(true) + .withE2EIRepositorySuccess() + .withCurrentClientIdProviderSuccess() + .withMlsClientProviderFailure() + .arrange() + + val result = revocationListChecker.check(DUMMY_URL) + + result.shouldFail() + coVerify { + arrangement.currentClientIdProvider.invoke() + }.wasInvoked(once) + + coVerify { + arrangement.mlsClientProvider.getCoreCrypto(eq(TestClient.CLIENT_ID)) + }.wasInvoked(once) + + coVerify { + arrangement.coreCrypto.registerCrl(any(), any()) + }.wasNotInvoked() + } + + @Test + fun givenMlsClientProviderSuccess_whenRunningUseCase_thenDoNotRegisterCrlAndReturnExpiration() = + runTest { + val (arrangement, revocationListChecker) = Arrangement() + .withE2EIEnabledAndMLSEnabled(true) + .withE2EIRepositorySuccess() + .withCurrentClientIdProviderSuccess() + .withMlsClientProviderSuccess() + .withRegisterCrl() + .arrange() + + val result = revocationListChecker.check(DUMMY_URL) + + result.shouldSucceed { + assertEquals(EXPIRATION, it) + } + coVerify { + arrangement.currentClientIdProvider.invoke() + }.wasInvoked(once) + + coVerify { + arrangement.mlsClientProvider.getCoreCrypto(eq(TestClient.CLIENT_ID)) + }.wasInvoked(once) + + coVerify { + arrangement.coreCrypto.registerCrl(any(), any()) + }.wasInvoked(once) + } + + @Test + fun givenCertificatesRegistrationReturnsFlagIsChanged_whenRunningUseCase_thenUpdateConversationStates() = + runTest { + val (arrangement, revocationListChecker) = Arrangement() + .withE2EIEnabledAndMLSEnabled(true) + .withE2EIRepositorySuccess() + .withCurrentClientIdProviderSuccess() + .withMlsClientProviderSuccess() + .withRegisterCrl() + .withRegisterCrlFlagChanged() + .arrange() + + val result = revocationListChecker.check(DUMMY_URL) + + result.shouldSucceed { + assertEquals(EXPIRATION, it) + } + + coVerify { + arrangement.coreCrypto.registerCrl(any(), any()) + }.wasInvoked(once) + } + + @Test + fun givenE2EIAndMLSAreDisabled_whenRunningUseCase_thenE2EIFailureDisabledIsReturned() = runTest { + // given + val (arrangement, revocationListChecker) = Arrangement() + .withE2EIEnabledAndMLSEnabled(false) + .arrange() + + // when + val result = revocationListChecker.check(DUMMY_URL) + + // then + result.shouldFail { + assertEquals(E2EIFailure.Disabled, it) + } + + coVerify { + arrangement.coreCrypto.registerCrl(any(), any()) + }.wasNotInvoked() + } + + internal class Arrangement { + + @Mock + val certificateRevocationListRepository = mock(CertificateRevocationListRepository::class) + + @Mock + val coreCrypto = mock(CoreCryptoCentral::class) + + @Mock + val currentClientIdProvider = mock(CurrentClientIdProvider::class) + + @Mock + val mlsClientProvider = mock(MLSClientProvider::class) + + @Mock + val featureSupport = mock(FeatureSupport::class) + + @Mock + val userConfigRepository = mock(UserConfigRepository::class) + + fun arrange() = this to RevocationListCheckerImpl( + certificateRevocationListRepository = certificateRevocationListRepository, + currentClientIdProvider = currentClientIdProvider, + mlsClientProvider = mlsClientProvider, + featureSupport = featureSupport, + userConfigRepository = userConfigRepository + ) + + suspend fun withE2EIRepositoryFailure() = apply { + coEvery { + certificateRevocationListRepository.getClientDomainCRL(any()) + }.returns(Either.Left(E2EIFailure.Generic(Exception()))) + } + + suspend fun withE2EIRepositorySuccess() = apply { + coEvery { + certificateRevocationListRepository.getClientDomainCRL(any()) + }.returns(Either.Right("result".toByteArray())) + } + + suspend fun withCurrentClientIdProviderFailure() = apply { + coEvery { + currentClientIdProvider.invoke() + }.returns(Either.Left(CoreFailure.SyncEventOrClientNotFound)) + } + + suspend fun withCurrentClientIdProviderSuccess() = apply { + coEvery { + currentClientIdProvider.invoke() + }.returns(Either.Right(TestClient.CLIENT_ID)) + } + + suspend fun withMlsClientProviderFailure() = apply { + coEvery { + mlsClientProvider.getCoreCrypto(any()) + }.returns(Either.Left(CoreFailure.SyncEventOrClientNotFound)) + } + + suspend fun withMlsClientProviderSuccess() = apply { + coEvery { + mlsClientProvider.getCoreCrypto(any()) + }.returns(Either.Right(coreCrypto)) + } + + suspend fun withRegisterCrl() = apply { + coEvery { + coreCrypto.registerCrl(any(), any()) + }.returns(CrlRegistration(false, EXPIRATION)) + } + + suspend fun withRegisterCrlFlagChanged() = apply { + coEvery { + coreCrypto.registerCrl(any(), any()) + }.returns(CrlRegistration(true, EXPIRATION)) + } + + fun withE2EIEnabledAndMLSEnabled(result: Boolean) = apply { + every { + featureSupport.isMLSSupported + }.returns(result) + + every { + userConfigRepository.isMLSEnabled() + }.returns(result.right()) + + every { + userConfigRepository.getE2EISettings() + }.returns(E2EISettings(true, DUMMY_URL, DateTimeUtil.currentInstant(), false, null).right()) + } + } + + companion object { + private const val DUMMY_URL = "https://dummy.url" + private val EXPIRATION = 10.toULong() + } +} diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/e2ei/CertificateRevocationListCheckWorkerTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/e2ei/CertificateRevocationListCheckWorkerTest.kt index 9a5a42d18d7..4d1e70e4cb2 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/e2ei/CertificateRevocationListCheckWorkerTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/e2ei/CertificateRevocationListCheckWorkerTest.kt @@ -20,19 +20,19 @@ package com.wire.kalium.logic.feature.e2ei import com.wire.kalium.logic.data.e2ei.CertificateRevocationListRepository import com.wire.kalium.logic.data.sync.IncrementalSyncRepository import com.wire.kalium.logic.data.sync.IncrementalSyncStatus -import com.wire.kalium.logic.feature.e2ei.usecase.CheckRevocationListUseCase +import com.wire.kalium.logic.data.e2ei.RevocationListChecker import com.wire.kalium.logic.functional.Either import com.wire.kalium.logic.kaliumLogger import com.wire.kalium.persistence.config.CRLUrlExpirationList import com.wire.kalium.persistence.config.CRLWithExpiration import io.mockative.Mock import io.mockative.any -import io.mockative.classOf +import io.mockative.coEvery +import io.mockative.coVerify import io.mockative.eq -import io.mockative.given +import io.mockative.every import io.mockative.mock import io.mockative.once -import io.mockative.verify import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.runTest @@ -48,71 +48,63 @@ class CertificateRevocationListCheckWorkerTest { .withCheckRevocationListResult() .arrange() - checkCrlWorker.execute() + checkCrlWorker() - verify(arrangement.certificateRevocationListRepository) - .suspendFunction(arrangement.certificateRevocationListRepository::getCRLs) - .wasInvoked(exactly = once) + coVerify { + arrangement.certificateRevocationListRepository.getCRLs() + }.wasInvoked(exactly = once) - verify(arrangement.checkRevocationList) - .suspendFunction(arrangement.checkRevocationList::invoke) - .with(eq(DUMMY_URL)) - .wasInvoked(exactly = once) + coVerify { + arrangement.checkRevocationList.check(eq(DUMMY_URL)) + }.wasInvoked(exactly = once) - verify(arrangement.certificateRevocationListRepository) - .suspendFunction(arrangement.certificateRevocationListRepository::addOrUpdateCRL) - .with(eq(DUMMY_URL), eq(FUTURE_TIMESTAMP)) - .wasInvoked(exactly = once) + coVerify { + arrangement.certificateRevocationListRepository.addOrUpdateCRL(eq(DUMMY_URL), eq(FUTURE_TIMESTAMP)) + }.wasInvoked(exactly = once) } private class Arrangement { @Mock - val certificateRevocationListRepository = mock(classOf()) + val certificateRevocationListRepository = mock(CertificateRevocationListRepository::class) @Mock - val incrementalSyncRepository = mock(classOf()) + val incrementalSyncRepository = mock(IncrementalSyncRepository::class) @Mock - val checkRevocationList = mock(classOf()) + val checkRevocationList = mock(RevocationListChecker::class) - fun arrange() = this to CertificateRevocationListCheckWorkerImpl( + fun arrange() = this to SyncCertificateRevocationListUseCase( certificateRevocationListRepository, incrementalSyncRepository, checkRevocationList, kaliumLogger ) - fun withNoCRL() = apply { - given(certificateRevocationListRepository) - .suspendFunction(certificateRevocationListRepository::getCRLs) - .whenInvoked() - .thenReturn(null) + suspend fun withNoCRL() = apply { + coEvery { + certificateRevocationListRepository.getCRLs() + }.returns(null) } - fun withNonExpiredCRL() = apply { - given(certificateRevocationListRepository) - .suspendFunction(certificateRevocationListRepository::getCRLs) - .whenInvoked() - .thenReturn(CRLUrlExpirationList(listOf(CRLWithExpiration(DUMMY_URL, FUTURE_TIMESTAMP)))) + suspend fun withNonExpiredCRL() = apply { + coEvery { + certificateRevocationListRepository.getCRLs() + }.returns(CRLUrlExpirationList(listOf(CRLWithExpiration(DUMMY_URL, FUTURE_TIMESTAMP)))) } - fun withExpiredCRL() = apply { - given(certificateRevocationListRepository) - .suspendFunction(certificateRevocationListRepository::getCRLs) - .whenInvoked() - .thenReturn(CRLUrlExpirationList(listOf(CRLWithExpiration(DUMMY_URL, TIMESTAMP)))) + suspend fun withExpiredCRL() = apply { + coEvery { + certificateRevocationListRepository.getCRLs() + }.returns(CRLUrlExpirationList(listOf(CRLWithExpiration(DUMMY_URL, TIMESTAMP)))) } - fun withCheckRevocationListResult() = apply { - given(checkRevocationList) - .suspendFunction(checkRevocationList::invoke) - .whenInvokedWith(any()) - .thenReturn(Either.Right(FUTURE_TIMESTAMP)) + suspend fun withCheckRevocationListResult() = apply { + coEvery { + checkRevocationList.check(any()) + }.returns(Either.Right(FUTURE_TIMESTAMP)) } fun withIncrementalSyncState(flow: Flow) = apply { - given(incrementalSyncRepository) - .getter(incrementalSyncRepository::incrementalSyncState) - .whenInvoked() - .thenReturn(flow) + every { incrementalSyncRepository.incrementalSyncState } + .returns(flow) } } From 6e2544631257b1da4740a814e63c2ebe2cacf6ab Mon Sep 17 00:00:00 2001 From: Mohamad Jaara Date: Tue, 7 Jan 2025 14:32:15 +0100 Subject: [PATCH 2/5] detekt --- ...ListCheckWorker.kt => SyncCertificateRevocationListUseCase.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/e2ei/{CertificateRevocationListCheckWorker.kt => SyncCertificateRevocationListUseCase.kt} (100%) diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/e2ei/CertificateRevocationListCheckWorker.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/e2ei/SyncCertificateRevocationListUseCase.kt similarity index 100% rename from logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/e2ei/CertificateRevocationListCheckWorker.kt rename to logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/e2ei/SyncCertificateRevocationListUseCase.kt From 9bc8774a7b6aa63704c9c5d56ca8a73c1acebe76 Mon Sep 17 00:00:00 2001 From: Mohamad Jaara Date: Tue, 7 Jan 2025 15:24:28 +0100 Subject: [PATCH 3/5] fix dependencies --- .../conversation/MLSConversationRepository.kt | 5 ++-- .../kalium/logic/feature/UserSessionScope.kt | 11 +++++--- .../e2ei/CheckCrlRevocationListUseCase.kt | 5 ++-- .../kalium/logic/feature/user/UserScope.kt | 25 ++++++++++--------- .../conversation/MLSWelcomeEventHandler.kt | 5 ++-- 5 files changed, 29 insertions(+), 22 deletions(-) diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/MLSConversationRepository.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/MLSConversationRepository.kt index a36555eef9c..92a8516e5e8 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/MLSConversationRepository.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/MLSConversationRepository.kt @@ -33,6 +33,7 @@ import com.wire.kalium.logic.StorageFailure import com.wire.kalium.logic.data.client.MLSClientProvider import com.wire.kalium.logic.data.conversation.mls.MLSAdditionResult import com.wire.kalium.logic.data.e2ei.CertificateRevocationListRepository +import com.wire.kalium.logic.data.e2ei.RevocationListChecker import com.wire.kalium.logic.data.event.Event import com.wire.kalium.logic.data.event.Event.Conversation.MLSWelcome import com.wire.kalium.logic.data.event.EventDeliveryInfo @@ -213,7 +214,7 @@ internal class MLSConversationDataSource( private val epochsFlow: MutableSharedFlow, private val proposalTimersFlow: MutableSharedFlow, private val keyPackageLimitsProvider: KeyPackageLimitsProvider, - private val checkRevocationList: CheckRevocationListUseCase, + private val revocationListChecker: RevocationListChecker, private val certificateRevocationListRepository: CertificateRevocationListRepository, private val idMapper: IdMapper = MapperProvider.idMapper(), private val conversationMapper: ConversationMapper = MapperProvider.conversationMapper(selfUserId), @@ -904,7 +905,7 @@ internal class MLSConversationDataSource( private suspend fun checkRevocationList(crlNewDistributionPoints: List) { crlNewDistributionPoints.forEach { url -> - checkRevocationList(url).map { newExpiration -> + revocationListChecker.check(url).map { newExpiration -> newExpiration?.let { certificateRevocationListRepository.addOrUpdateCRL(url, it) } 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 08c2a5bb477..3f45055f583 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 @@ -83,6 +83,8 @@ import com.wire.kalium.logic.data.e2ei.CertificateRevocationListRepository import com.wire.kalium.logic.data.e2ei.CertificateRevocationListRepositoryDataSource import com.wire.kalium.logic.data.e2ei.E2EIRepository import com.wire.kalium.logic.data.e2ei.E2EIRepositoryImpl +import com.wire.kalium.logic.data.e2ei.RevocationListChecker +import com.wire.kalium.logic.data.e2ei.RevocationListCheckerImpl import com.wire.kalium.logic.feature.e2ei.usecase.ObserveE2EIConversationsVerificationStatusesUseCase import com.wire.kalium.logic.feature.e2ei.usecase.ObserveE2EIConversationsVerificationStatusesUseCaseImpl import com.wire.kalium.logic.data.event.EventDataSource @@ -649,12 +651,13 @@ class UserSessionScope internal constructor( memberJoinHandler, memberLeaveHandler ) - private val checkRevocationList: CheckRevocationListUseCase - get() = CheckRevocationListUseCaseImpl( + private val checkRevocationList: RevocationListChecker + get() = RevocationListCheckerImpl( certificateRevocationListRepository = certificateRevocationListRepository, currentClientIdProvider = clientIdProvider, mlsClientProvider = mlsClientProvider, - isE2EIEnabledUseCase = isE2EIEnabled + featureSupport = featureSupport, + userConfigRepository = userConfigRepository ) private val mlsConversationRepository: MLSConversationRepository @@ -1359,7 +1362,7 @@ class UserSessionScope internal constructor( conversationRepository = conversationRepository, oneOnOneResolver = oneOnOneResolver, refillKeyPackages = client.refillKeyPackages, - checkRevocationList = checkRevocationList, + revocationListChecker = checkRevocationList, certificateRevocationListRepository = certificateRevocationListRepository ) diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/e2ei/CheckCrlRevocationListUseCase.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/e2ei/CheckCrlRevocationListUseCase.kt index c760a6c45d2..0a5d022ec3e 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/e2ei/CheckCrlRevocationListUseCase.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/e2ei/CheckCrlRevocationListUseCase.kt @@ -19,6 +19,7 @@ package com.wire.kalium.logic.feature.e2ei import com.wire.kalium.logger.KaliumLogger import com.wire.kalium.logic.data.e2ei.CertificateRevocationListRepository +import com.wire.kalium.logic.data.e2ei.RevocationListChecker import com.wire.kalium.logic.feature.e2ei.usecase.CheckRevocationListUseCase import com.wire.kalium.logic.functional.map import kotlinx.datetime.Clock @@ -29,7 +30,7 @@ import kotlinx.datetime.Clock */ class CheckCrlRevocationListUseCase internal constructor( private val certificateRevocationListRepository: CertificateRevocationListRepository, - private val checkRevocationList: CheckRevocationListUseCase, + private val revocationListChecker: RevocationListChecker, kaliumLogger: KaliumLogger ) { @@ -39,7 +40,7 @@ class CheckCrlRevocationListUseCase internal constructor( logger.i("Checking certificate revocation list (CRL). Force update: $forceUpdate") certificateRevocationListRepository.getCRLs()?.cRLWithExpirationList?.forEach { crl -> if (forceUpdate || (crl.expiration < Clock.System.now().epochSeconds.toULong())) { - checkRevocationList(crl.url).map { newExpirationTime -> + revocationListChecker.check(crl.url).map { newExpirationTime -> newExpirationTime?.let { certificateRevocationListRepository.addOrUpdateCRL(crl.url, it) } diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/user/UserScope.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/user/UserScope.kt index ac41b886660..d8e96dee4db 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/user/UserScope.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/user/UserScope.kt @@ -24,11 +24,13 @@ import com.wire.kalium.logic.configuration.UserConfigRepository import com.wire.kalium.logic.configuration.server.ServerConfigRepository import com.wire.kalium.logic.data.asset.AssetRepository import com.wire.kalium.logic.data.client.ClientRepository +import com.wire.kalium.logic.data.client.MLSClientProvider import com.wire.kalium.logic.data.conversation.ConversationRepository import com.wire.kalium.logic.data.conversation.JoinExistingMLSConversationsUseCase import com.wire.kalium.logic.data.conversation.MLSConversationRepository import com.wire.kalium.logic.data.e2ei.CertificateRevocationListRepository import com.wire.kalium.logic.data.e2ei.E2EIRepository +import com.wire.kalium.logic.data.e2ei.RevocationListChecker import com.wire.kalium.logic.data.id.CurrentClientIdProvider import com.wire.kalium.logic.data.properties.UserPropertyRepository import com.wire.kalium.logic.data.session.SessionRepository @@ -49,9 +51,7 @@ import com.wire.kalium.logic.feature.auth.ValidateUserHandleUseCaseImpl import com.wire.kalium.logic.feature.client.FinalizeMLSClientAfterE2EIEnrollment import com.wire.kalium.logic.feature.client.FinalizeMLSClientAfterE2EIEnrollmentImpl import com.wire.kalium.logic.feature.conversation.GetAllContactsNotInConversationUseCase -import com.wire.kalium.logic.feature.e2ei.CertificateRevocationListCheckWorker -import com.wire.kalium.logic.feature.e2ei.CertificateRevocationListCheckWorkerImpl -import com.wire.kalium.logic.feature.e2ei.usecase.CheckRevocationListUseCase +import com.wire.kalium.logic.feature.e2ei.SyncCertificateRevocationListUseCase import com.wire.kalium.logic.feature.e2ei.usecase.EnrollE2EIUseCase import com.wire.kalium.logic.feature.e2ei.usecase.EnrollE2EIUseCaseImpl import com.wire.kalium.logic.feature.e2ei.usecase.GetMLSClientIdentityUseCase @@ -110,10 +110,11 @@ class UserScope internal constructor( private val isE2EIEnabledUseCase: IsE2EIEnabledUseCase, private val certificateRevocationListRepository: CertificateRevocationListRepository, private val incrementalSyncRepository: IncrementalSyncRepository, - private val checkRevocationList: CheckRevocationListUseCase, + private val checkRevocationList: RevocationListChecker, private val syncFeatureConfigs: SyncFeatureConfigsUseCase, private val userScopedLogger: KaliumLogger ) { + private val validateUserHandleUseCase: ValidateUserHandleUseCase get() = ValidateUserHandleUseCaseImpl() val getSelfUser: GetSelfUserUseCase get() = GetSelfUserUseCaseImpl(userRepository) val getSelfUserWithTeam: ObserveSelfUserWithTeamUseCase get() = ObserveSelfUserWithTeamUseCaseImpl(userRepository) @@ -209,14 +210,14 @@ class UserScope internal constructor( kaliumLogger = userScopedLogger, ) - val certificateRevocationListCheckWorker: CertificateRevocationListCheckWorker by lazy { - CertificateRevocationListCheckWorkerImpl( - certificateRevocationListRepository = certificateRevocationListRepository, - incrementalSyncRepository = incrementalSyncRepository, - checkRevocationList = checkRevocationList, - kaliumLogger = userScopedLogger, - ) - } + val syncCertificateRevocationListUseCase: SyncCertificateRevocationListUseCase + get() = + SyncCertificateRevocationListUseCase( + certificateRevocationListRepository = certificateRevocationListRepository, + incrementalSyncRepository = incrementalSyncRepository, + revocationListChecker = checkRevocationList, + kaliumLogger = userScopedLogger, + ) val featureFlagsSyncWorker: FeatureFlagsSyncWorker by lazy { FeatureFlagSyncWorkerImpl( diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/sync/receiver/conversation/MLSWelcomeEventHandler.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/sync/receiver/conversation/MLSWelcomeEventHandler.kt index 5af954af042..8c6f39eb9ed 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/sync/receiver/conversation/MLSWelcomeEventHandler.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/sync/receiver/conversation/MLSWelcomeEventHandler.kt @@ -24,6 +24,7 @@ import com.wire.kalium.logic.data.conversation.Conversation import com.wire.kalium.logic.data.conversation.ConversationDetails import com.wire.kalium.logic.data.conversation.ConversationRepository import com.wire.kalium.logic.data.e2ei.CertificateRevocationListRepository +import com.wire.kalium.logic.data.e2ei.RevocationListChecker import com.wire.kalium.logic.data.event.Event import com.wire.kalium.logic.data.event.EventLoggingStatus import com.wire.kalium.logic.data.event.logEventProcessing @@ -52,7 +53,7 @@ internal class MLSWelcomeEventHandlerImpl( val conversationRepository: ConversationRepository, val oneOnOneResolver: OneOnOneResolver, val refillKeyPackages: RefillKeyPackagesUseCase, - val checkRevocationList: CheckRevocationListUseCase, + private val revocationListChecker: RevocationListChecker, private val certificateRevocationListRepository: CertificateRevocationListRepository ) : MLSWelcomeEventHandler { override suspend fun handle(event: Event.Conversation.MLSWelcome): Either = @@ -105,7 +106,7 @@ internal class MLSWelcomeEventHandlerImpl( private suspend fun checkRevocationList(crlNewDistributionPoints: List) { crlNewDistributionPoints.forEach { url -> - checkRevocationList(url).map { newExpiration -> + revocationListChecker.check(url).map { newExpiration -> newExpiration?.let { certificateRevocationListRepository.addOrUpdateCRL(url, it) } From bf7f4965c896abcde01234f008e6b93c209faa27 Mon Sep 17 00:00:00 2001 From: Mohamad Jaara Date: Tue, 7 Jan 2025 15:32:42 +0100 Subject: [PATCH 4/5] fix dependencies --- .../kalium/logic/data/conversation/MLSConversationRepository.kt | 1 - .../kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt | 2 -- .../kalium/logic/feature/e2ei/CheckCrlRevocationListUseCase.kt | 1 - .../kotlin/com/wire/kalium/logic/feature/user/UserScope.kt | 1 - .../logic/sync/receiver/conversation/MLSWelcomeEventHandler.kt | 1 - 5 files changed, 6 deletions(-) diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/MLSConversationRepository.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/MLSConversationRepository.kt index 92a8516e5e8..e276c2be999 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/MLSConversationRepository.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/MLSConversationRepository.kt @@ -53,7 +53,6 @@ import com.wire.kalium.logic.data.mlspublickeys.MLSPublicKeysRepository import com.wire.kalium.logic.data.mlspublickeys.getRemovalKey import com.wire.kalium.logic.data.user.UserId import com.wire.kalium.logic.di.MapperProvider -import com.wire.kalium.logic.feature.e2ei.usecase.CheckRevocationListUseCase import com.wire.kalium.logic.functional.Either import com.wire.kalium.logic.functional.flatMap import com.wire.kalium.logic.functional.flatMapLeft 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 3f45055f583..c623b186307 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 @@ -216,8 +216,6 @@ import com.wire.kalium.logic.feature.debug.DebugScope import com.wire.kalium.logic.feature.e2ei.ACMECertificatesSyncWorker import com.wire.kalium.logic.feature.e2ei.ACMECertificatesSyncWorkerImpl import com.wire.kalium.logic.feature.e2ei.CheckCrlRevocationListUseCase -import com.wire.kalium.logic.feature.e2ei.usecase.CheckRevocationListUseCase -import com.wire.kalium.logic.feature.e2ei.usecase.CheckRevocationListUseCaseImpl import com.wire.kalium.logic.feature.e2ei.usecase.FetchConversationMLSVerificationStatusUseCase import com.wire.kalium.logic.feature.e2ei.usecase.FetchConversationMLSVerificationStatusUseCaseImpl import com.wire.kalium.logic.feature.e2ei.usecase.FetchMLSVerificationStatusUseCase diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/e2ei/CheckCrlRevocationListUseCase.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/e2ei/CheckCrlRevocationListUseCase.kt index 0a5d022ec3e..d8eea576ab8 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/e2ei/CheckCrlRevocationListUseCase.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/e2ei/CheckCrlRevocationListUseCase.kt @@ -20,7 +20,6 @@ package com.wire.kalium.logic.feature.e2ei import com.wire.kalium.logger.KaliumLogger import com.wire.kalium.logic.data.e2ei.CertificateRevocationListRepository import com.wire.kalium.logic.data.e2ei.RevocationListChecker -import com.wire.kalium.logic.feature.e2ei.usecase.CheckRevocationListUseCase import com.wire.kalium.logic.functional.map import kotlinx.datetime.Clock diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/user/UserScope.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/user/UserScope.kt index d8e96dee4db..c1c9f6cd056 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/user/UserScope.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/user/UserScope.kt @@ -24,7 +24,6 @@ import com.wire.kalium.logic.configuration.UserConfigRepository import com.wire.kalium.logic.configuration.server.ServerConfigRepository import com.wire.kalium.logic.data.asset.AssetRepository import com.wire.kalium.logic.data.client.ClientRepository -import com.wire.kalium.logic.data.client.MLSClientProvider import com.wire.kalium.logic.data.conversation.ConversationRepository import com.wire.kalium.logic.data.conversation.JoinExistingMLSConversationsUseCase import com.wire.kalium.logic.data.conversation.MLSConversationRepository diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/sync/receiver/conversation/MLSWelcomeEventHandler.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/sync/receiver/conversation/MLSWelcomeEventHandler.kt index 8c6f39eb9ed..13092320361 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/sync/receiver/conversation/MLSWelcomeEventHandler.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/sync/receiver/conversation/MLSWelcomeEventHandler.kt @@ -31,7 +31,6 @@ import com.wire.kalium.logic.data.event.logEventProcessing import com.wire.kalium.logic.data.id.ConversationId import com.wire.kalium.logic.data.id.GroupID import com.wire.kalium.logic.feature.conversation.mls.OneOnOneResolver -import com.wire.kalium.logic.feature.e2ei.usecase.CheckRevocationListUseCase import com.wire.kalium.logic.feature.keypackage.RefillKeyPackagesResult import com.wire.kalium.logic.feature.keypackage.RefillKeyPackagesUseCase import com.wire.kalium.logic.functional.Either From df62e267723c403c4ba44ea13cf0648b4269fa9e Mon Sep 17 00:00:00 2001 From: Mohamad Jaara Date: Tue, 7 Jan 2025 17:20:30 +0100 Subject: [PATCH 5/5] fix tests --- .../MLSConversationRepositoryTest.kt | 18 +- .../data/e2ei/RevocationListCheckerTest.kt | 192 ++++++++++-------- ...ertificateRevocationListCheckWorkerTest.kt | 69 ++++--- .../e2ei/CheckCrlRevocationListUseCaseTest.kt | 9 +- .../MLSWelcomeEventHandlerTest.kt | 10 +- 5 files changed, 164 insertions(+), 134 deletions(-) diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/conversation/MLSConversationRepositoryTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/conversation/MLSConversationRepositoryTest.kt index e00d437401a..26819408eb5 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/conversation/MLSConversationRepositoryTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/conversation/MLSConversationRepositoryTest.kt @@ -48,6 +48,7 @@ import com.wire.kalium.logic.data.conversation.MLSConversationRepositoryTest.Arr import com.wire.kalium.logic.data.conversation.MLSConversationRepositoryTest.Arrangement.Companion.WIRE_IDENTITY import com.wire.kalium.logic.data.conversation.mls.KeyPackageClaimResult import com.wire.kalium.logic.data.e2ei.CertificateRevocationListRepository +import com.wire.kalium.logic.data.e2ei.RevocationListChecker import com.wire.kalium.logic.data.event.Event import com.wire.kalium.logic.data.id.GroupID import com.wire.kalium.logic.data.id.QualifiedClientID @@ -58,7 +59,6 @@ import com.wire.kalium.logic.data.mls.CipherSuite import com.wire.kalium.logic.data.mlspublickeys.MLSPublicKeys import com.wire.kalium.logic.data.mlspublickeys.MLSPublicKeysRepository import com.wire.kalium.logic.data.user.UserId -import com.wire.kalium.logic.feature.e2ei.usecase.CheckRevocationListUseCase import com.wire.kalium.logic.framework.TestClient import com.wire.kalium.logic.framework.TestConversation import com.wire.kalium.logic.framework.TestUser @@ -151,7 +151,7 @@ class MLSConversationRepositoryTest { mlsConversationRepository.decryptMessage(Arrangement.COMMIT, Arrangement.GROUP_ID) verify(arrangement.checkRevocationList) - .suspendFunction(arrangement.checkRevocationList::invoke) + .suspendFunction(arrangement.checkRevocationList::check) .with(any()) .wasInvoked(once) @@ -413,7 +413,7 @@ class MLSConversationRepositoryTest { mlsConversationRepository.addMemberToMLSGroup(Arrangement.GROUP_ID, listOf(TestConversation.USER_ID1), CIPHER_SUITE) verify(arrangement.checkRevocationList) - .suspendFunction(arrangement.checkRevocationList::invoke) + .suspendFunction(arrangement.checkRevocationList::check) .with(any()) .wasInvoked(exactly = once) @@ -784,7 +784,7 @@ class MLSConversationRepositoryTest { .wasInvoked(once) verify(arrangement.checkRevocationList) - .suspendFunction(arrangement.checkRevocationList::invoke) + .suspendFunction(arrangement.checkRevocationList::check) .with(any()) .wasNotInvoked() } @@ -805,7 +805,7 @@ class MLSConversationRepositoryTest { mlsConversationRepository.joinGroupByExternalCommit(Arrangement.GROUP_ID, Arrangement.PUBLIC_GROUP_STATE) verify(arrangement.checkRevocationList) - .suspendFunction(arrangement.checkRevocationList::invoke) + .suspendFunction(arrangement.checkRevocationList::check) .with(any()) .wasInvoked(exactly = once) @@ -1382,7 +1382,7 @@ class MLSConversationRepositoryTest { .wasInvoked(once) verify(arrangement.checkRevocationList) - .suspendFunction(arrangement.checkRevocationList::invoke) + .suspendFunction(arrangement.checkRevocationList::check) .with(any()) .wasNotInvoked() } @@ -1405,7 +1405,7 @@ class MLSConversationRepositoryTest { ) verify(arrangement.checkRevocationList) - .suspendFunction(arrangement.checkRevocationList::invoke) + .suspendFunction(arrangement.checkRevocationList::check) .with(any()) .wasInvoked(exactly = once) @@ -1770,7 +1770,7 @@ class MLSConversationRepositoryTest { val keyPackageLimitsProvider = mock(classOf()) @Mock - val checkRevocationList = mock(classOf()) + val checkRevocationList = mock(classOf()) @Mock val certificateRevocationListRepository = mock(classOf()) @@ -1997,7 +1997,7 @@ class MLSConversationRepositoryTest { fun withCheckRevocationListResult() = apply { given(checkRevocationList) - .suspendFunction(checkRevocationList::invoke) + .suspendFunction(checkRevocationList::check) .whenInvokedWith(anything()) .thenReturn(Either.Right(1uL)) } diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/e2ei/RevocationListCheckerTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/e2ei/RevocationListCheckerTest.kt index b469eb49dbc..f9b991d9dc5 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/e2ei/RevocationListCheckerTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/e2ei/RevocationListCheckerTest.kt @@ -35,12 +35,11 @@ import com.wire.kalium.util.DateTimeUtil import io.ktor.utils.io.core.toByteArray import io.mockative.Mock import io.mockative.any -import io.mockative.coEvery -import io.mockative.coVerify import io.mockative.eq -import io.mockative.every +import io.mockative.given import io.mockative.mock import io.mockative.once +import io.mockative.verify import kotlinx.coroutines.test.runTest import kotlin.test.Test import kotlin.test.assertEquals @@ -58,13 +57,15 @@ class RevocationListCheckerTest { val result = revocationListChecker.check(DUMMY_URL) result.shouldFail() - coVerify { - arrangement.certificateRevocationListRepository.getClientDomainCRL(any()) - }.wasInvoked(once) - - coVerify { - arrangement.coreCrypto.registerCrl(any(), any()) - }.wasNotInvoked() + verify(arrangement.certificateRevocationListRepository) + .suspendFunction(arrangement.certificateRevocationListRepository::getClientDomainCRL) + .with(any()) + .wasInvoked(exactly = once) + + verify(arrangement.coreCrypto) + .suspendFunction(arrangement.coreCrypto::registerCrl) + .with(any(), any()) + .wasNotInvoked() } @Test @@ -79,17 +80,20 @@ class RevocationListCheckerTest { val result = revocationListChecker.check(DUMMY_URL) result.shouldFail() - coVerify { - arrangement.certificateRevocationListRepository.getClientDomainCRL(any()) - }.wasInvoked(once) - coVerify { - arrangement.currentClientIdProvider.invoke() - }.wasInvoked(once) + verify(arrangement.certificateRevocationListRepository) + .suspendFunction(arrangement.certificateRevocationListRepository::getClientDomainCRL) + .with(any()) + .wasInvoked(exactly = once) + + verify(arrangement.currentClientIdProvider) + .suspendFunction(arrangement.currentClientIdProvider::invoke) + .wasInvoked(exactly = once) - coVerify { - arrangement.coreCrypto.registerCrl(any(), any()) - }.wasNotInvoked() + verify(arrangement.coreCrypto) + .suspendFunction(arrangement.coreCrypto::registerCrl) + .with(any(), any()) + .wasNotInvoked() } @Test @@ -105,17 +109,20 @@ class RevocationListCheckerTest { val result = revocationListChecker.check(DUMMY_URL) result.shouldFail() - coVerify { - arrangement.currentClientIdProvider.invoke() - }.wasInvoked(once) + verify(arrangement.currentClientIdProvider) + .suspendFunction(arrangement.currentClientIdProvider::invoke) + .wasInvoked(exactly = once) + + verify(arrangement.mlsClientProvider) + .suspendFunction(arrangement.mlsClientProvider::getCoreCrypto) + .with(eq(TestClient.CLIENT_ID)) + .wasInvoked(exactly = once) - coVerify { - arrangement.mlsClientProvider.getCoreCrypto(eq(TestClient.CLIENT_ID)) - }.wasInvoked(once) + verify(arrangement.coreCrypto) + .suspendFunction(arrangement.coreCrypto::registerCrl) + .with(any(), any()) + .wasNotInvoked() - coVerify { - arrangement.coreCrypto.registerCrl(any(), any()) - }.wasNotInvoked() } @Test @@ -134,17 +141,20 @@ class RevocationListCheckerTest { result.shouldSucceed { assertEquals(EXPIRATION, it) } - coVerify { - arrangement.currentClientIdProvider.invoke() - }.wasInvoked(once) - coVerify { - arrangement.mlsClientProvider.getCoreCrypto(eq(TestClient.CLIENT_ID)) - }.wasInvoked(once) + verify(arrangement.currentClientIdProvider) + .suspendFunction(arrangement.currentClientIdProvider::invoke) + .wasInvoked(exactly = once) - coVerify { - arrangement.coreCrypto.registerCrl(any(), any()) - }.wasInvoked(once) + verify(arrangement.mlsClientProvider) + .suspendFunction(arrangement.mlsClientProvider::getCoreCrypto) + .with(eq(TestClient.CLIENT_ID)) + .wasInvoked(exactly = once) + + verify(arrangement.coreCrypto) + .suspendFunction(arrangement.coreCrypto::registerCrl) + .with(any(), any()) + .wasInvoked(exactly = once) } @Test @@ -165,9 +175,10 @@ class RevocationListCheckerTest { assertEquals(EXPIRATION, it) } - coVerify { - arrangement.coreCrypto.registerCrl(any(), any()) - }.wasInvoked(once) + verify(arrangement.coreCrypto) + .suspendFunction(arrangement.coreCrypto::registerCrl) + .with(any(), any()) + .wasInvoked(exactly = once) } @Test @@ -185,9 +196,10 @@ class RevocationListCheckerTest { assertEquals(E2EIFailure.Disabled, it) } - coVerify { - arrangement.coreCrypto.registerCrl(any(), any()) - }.wasNotInvoked() + verify(arrangement.coreCrypto) + .suspendFunction(arrangement.coreCrypto::registerCrl) + .with(any(), any()) + .wasNotInvoked() } internal class Arrangement { @@ -218,66 +230,74 @@ class RevocationListCheckerTest { userConfigRepository = userConfigRepository ) - suspend fun withE2EIRepositoryFailure() = apply { - coEvery { - certificateRevocationListRepository.getClientDomainCRL(any()) - }.returns(Either.Left(E2EIFailure.Generic(Exception()))) + fun withE2EIRepositoryFailure() = apply { + given(certificateRevocationListRepository) + .suspendFunction(certificateRevocationListRepository::getClientDomainCRL) + .whenInvokedWith(any()) + .then { Either.Left(E2EIFailure.Generic(Exception())) } } - suspend fun withE2EIRepositorySuccess() = apply { - coEvery { - certificateRevocationListRepository.getClientDomainCRL(any()) - }.returns(Either.Right("result".toByteArray())) + fun withE2EIRepositorySuccess() = apply { + given(certificateRevocationListRepository) + .suspendFunction(certificateRevocationListRepository::getClientDomainCRL) + .whenInvokedWith(any()) + .then { Either.Right("result".toByteArray()) } } - suspend fun withCurrentClientIdProviderFailure() = apply { - coEvery { - currentClientIdProvider.invoke() - }.returns(Either.Left(CoreFailure.SyncEventOrClientNotFound)) + fun withCurrentClientIdProviderFailure() = apply { + given(currentClientIdProvider) + .suspendFunction(currentClientIdProvider::invoke) + .whenInvoked() + .then { Either.Left(CoreFailure.SyncEventOrClientNotFound) } } - suspend fun withCurrentClientIdProviderSuccess() = apply { - coEvery { - currentClientIdProvider.invoke() - }.returns(Either.Right(TestClient.CLIENT_ID)) + fun withCurrentClientIdProviderSuccess() = apply { + given(currentClientIdProvider) + .suspendFunction(currentClientIdProvider::invoke) + .whenInvoked() + .then { Either.Right(TestClient.CLIENT_ID) } } - suspend fun withMlsClientProviderFailure() = apply { - coEvery { - mlsClientProvider.getCoreCrypto(any()) - }.returns(Either.Left(CoreFailure.SyncEventOrClientNotFound)) + fun withMlsClientProviderFailure() = apply { + given(mlsClientProvider) + .suspendFunction(mlsClientProvider::getCoreCrypto) + .whenInvokedWith(any()) + .then { Either.Left(CoreFailure.SyncEventOrClientNotFound) } } - suspend fun withMlsClientProviderSuccess() = apply { - coEvery { - mlsClientProvider.getCoreCrypto(any()) - }.returns(Either.Right(coreCrypto)) + fun withMlsClientProviderSuccess() = apply { + given(mlsClientProvider) + .suspendFunction(mlsClientProvider::getCoreCrypto) + .whenInvokedWith(any()) + .then { Either.Right(coreCrypto) } } - suspend fun withRegisterCrl() = apply { - coEvery { - coreCrypto.registerCrl(any(), any()) - }.returns(CrlRegistration(false, EXPIRATION)) + fun withRegisterCrl() = apply { + given(coreCrypto) + .suspendFunction(coreCrypto::registerCrl) + .whenInvokedWith(any(), any()) + .thenReturn(CrlRegistration(true, EXPIRATION)) } - suspend fun withRegisterCrlFlagChanged() = apply { - coEvery { - coreCrypto.registerCrl(any(), any()) - }.returns(CrlRegistration(true, EXPIRATION)) + fun withRegisterCrlFlagChanged() = apply { + given(coreCrypto) + .suspendFunction(coreCrypto::registerCrl) + .whenInvokedWith(any(), any()) + .thenReturn(CrlRegistration(false, EXPIRATION)) } fun withE2EIEnabledAndMLSEnabled(result: Boolean) = apply { - every { - featureSupport.isMLSSupported - }.returns(result) - - every { - userConfigRepository.isMLSEnabled() - }.returns(result.right()) - - every { - userConfigRepository.getE2EISettings() - }.returns(E2EISettings(true, DUMMY_URL, DateTimeUtil.currentInstant(), false, null).right()) + given(featureSupport) + .invocation { featureSupport.isMLSSupported } + .thenReturn(result) + given(userConfigRepository) + .function(userConfigRepository::isMLSEnabled) + .whenInvoked() + .thenReturn(result.right()) + given(userConfigRepository) + .function(userConfigRepository::getE2EISettings) + .whenInvoked() + .thenReturn(E2EISettings(result, DUMMY_URL, DateTimeUtil.currentInstant(), false, null).right()) } } diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/e2ei/CertificateRevocationListCheckWorkerTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/e2ei/CertificateRevocationListCheckWorkerTest.kt index 4d1e70e4cb2..4367efcacbe 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/e2ei/CertificateRevocationListCheckWorkerTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/e2ei/CertificateRevocationListCheckWorkerTest.kt @@ -27,12 +27,11 @@ import com.wire.kalium.persistence.config.CRLUrlExpirationList import com.wire.kalium.persistence.config.CRLWithExpiration import io.mockative.Mock import io.mockative.any -import io.mockative.coEvery -import io.mockative.coVerify import io.mockative.eq -import io.mockative.every +import io.mockative.given import io.mockative.mock import io.mockative.once +import io.mockative.verify import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.runTest @@ -50,18 +49,19 @@ class CertificateRevocationListCheckWorkerTest { checkCrlWorker() - coVerify { - arrangement.certificateRevocationListRepository.getCRLs() - }.wasInvoked(exactly = once) + verify(arrangement.certificateRevocationListRepository) + .suspendFunction(arrangement.certificateRevocationListRepository::getCRLs) + .wasInvoked(exactly = once) - coVerify { - arrangement.checkRevocationList.check(eq(DUMMY_URL)) - }.wasInvoked(exactly = once) - - coVerify { - arrangement.certificateRevocationListRepository.addOrUpdateCRL(eq(DUMMY_URL), eq(FUTURE_TIMESTAMP)) - }.wasInvoked(exactly = once) + verify(arrangement.checkRevocationList) + .suspendFunction(arrangement.checkRevocationList::check) + .with(eq(DUMMY_URL)) + .wasInvoked(exactly = once) + verify(arrangement.certificateRevocationListRepository) + .suspendFunction(arrangement.certificateRevocationListRepository::addOrUpdateCRL) + .with(eq(DUMMY_URL), eq(FUTURE_TIMESTAMP)) + .wasInvoked(exactly = once) } private class Arrangement { @@ -79,32 +79,39 @@ class CertificateRevocationListCheckWorkerTest { certificateRevocationListRepository, incrementalSyncRepository, checkRevocationList, kaliumLogger ) - suspend fun withNoCRL() = apply { - coEvery { - certificateRevocationListRepository.getCRLs() - }.returns(null) + fun withNoCRL() = apply { + given(certificateRevocationListRepository) + .suspendFunction(certificateRevocationListRepository::getCRLs) + .whenInvoked() + .then { null } } - suspend fun withNonExpiredCRL() = apply { - coEvery { - certificateRevocationListRepository.getCRLs() - }.returns(CRLUrlExpirationList(listOf(CRLWithExpiration(DUMMY_URL, FUTURE_TIMESTAMP)))) + fun withNonExpiredCRL() = apply { + given(certificateRevocationListRepository) + .suspendFunction(certificateRevocationListRepository::getCRLs) + .whenInvoked() + .then { CRLUrlExpirationList(listOf(CRLWithExpiration(DUMMY_URL, TIMESTAMP))) } } - suspend fun withExpiredCRL() = apply { - coEvery { - certificateRevocationListRepository.getCRLs() - }.returns(CRLUrlExpirationList(listOf(CRLWithExpiration(DUMMY_URL, TIMESTAMP)))) + fun withExpiredCRL() = apply { + given(certificateRevocationListRepository) + .suspendFunction(certificateRevocationListRepository::getCRLs) + .whenInvoked() + .then { CRLUrlExpirationList(listOf(CRLWithExpiration(DUMMY_URL, TIMESTAMP))) } } - suspend fun withCheckRevocationListResult() = apply { - coEvery { - checkRevocationList.check(any()) - }.returns(Either.Right(FUTURE_TIMESTAMP)) + + fun withCheckRevocationListResult() = apply { + given(checkRevocationList) + .suspendFunction(checkRevocationList::check) + .whenInvokedWith(any()) + .then { Either.Right(FUTURE_TIMESTAMP) } } fun withIncrementalSyncState(flow: Flow) = apply { - every { incrementalSyncRepository.incrementalSyncState } - .returns(flow) + given(incrementalSyncRepository) + .invocation { + incrementalSyncRepository.incrementalSyncState + }.then { flow } } } diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/e2ei/CheckCrlRevocationListUseCaseTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/e2ei/CheckCrlRevocationListUseCaseTest.kt index 9f3859f1ab8..d38a8b0dec3 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/e2ei/CheckCrlRevocationListUseCaseTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/e2ei/CheckCrlRevocationListUseCaseTest.kt @@ -18,6 +18,7 @@ package com.wire.kalium.logic.feature.e2ei import com.wire.kalium.logic.data.e2ei.CertificateRevocationListRepository +import com.wire.kalium.logic.data.e2ei.RevocationListChecker import com.wire.kalium.logic.data.sync.IncrementalSyncRepository import com.wire.kalium.logic.data.sync.IncrementalSyncStatus import com.wire.kalium.logic.feature.e2ei.usecase.CheckRevocationListUseCase @@ -54,7 +55,7 @@ class CheckCrlRevocationListUseCaseTest { .wasInvoked(exactly = once) verify(arrangement.checkRevocationList) - .suspendFunction(arrangement.checkRevocationList::invoke) + .suspendFunction(arrangement.checkRevocationList::check) .with(eq(DUMMY_URL)) .wasInvoked(exactly = once) @@ -79,7 +80,7 @@ class CheckCrlRevocationListUseCaseTest { .wasInvoked(exactly = once) verify(arrangement.checkRevocationList) - .suspendFunction(arrangement.checkRevocationList::invoke) + .suspendFunction(arrangement.checkRevocationList::check) .with(eq(DUMMY_URL)) .wasInvoked(exactly = once) @@ -95,7 +96,7 @@ class CheckCrlRevocationListUseCaseTest { val certificateRevocationListRepository = mock(classOf()) @Mock - val checkRevocationList = mock(classOf()) + val checkRevocationList = mock(classOf()) fun arrange() = this to CheckCrlRevocationListUseCase( certificateRevocationListRepository, checkRevocationList, kaliumLogger @@ -123,7 +124,7 @@ class CheckCrlRevocationListUseCaseTest { } fun withCheckRevocationListResult() = apply { given(checkRevocationList) - .suspendFunction(checkRevocationList::invoke) + .suspendFunction(checkRevocationList::check) .whenInvokedWith(any()) .thenReturn(Either.Right(FUTURE_TIMESTAMP)) } diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/sync/receiver/conversation/MLSWelcomeEventHandlerTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/sync/receiver/conversation/MLSWelcomeEventHandlerTest.kt index 18f8ddf4640..986df466336 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/sync/receiver/conversation/MLSWelcomeEventHandlerTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/sync/receiver/conversation/MLSWelcomeEventHandlerTest.kt @@ -26,6 +26,8 @@ import com.wire.kalium.logic.StorageFailure import com.wire.kalium.logic.data.client.MLSClientProvider import com.wire.kalium.logic.data.conversation.Conversation import com.wire.kalium.logic.data.e2ei.CertificateRevocationListRepository +import com.wire.kalium.logic.data.e2ei.RevocationListChecker +import com.wire.kalium.logic.data.e2ei.RevocationListCheckerImpl import com.wire.kalium.logic.data.event.Event import com.wire.kalium.logic.data.id.GroupID import com.wire.kalium.logic.feature.e2ei.usecase.CheckRevocationListUseCase @@ -250,7 +252,7 @@ class MLSWelcomeEventHandlerTest { .wasInvoked(exactly = once) verify(arrangement.checkRevocationList) - .suspendFunction(arrangement.checkRevocationList::invoke) + .suspendFunction(arrangement.checkRevocationList::check) .with(any()) .wasInvoked(exactly = once) @@ -273,7 +275,7 @@ class MLSWelcomeEventHandlerTest { val refillKeyPackagesUseCase: RefillKeyPackagesUseCase = mock(classOf()) @Mock - val checkRevocationList: CheckRevocationListUseCase = mock(classOf()) + val checkRevocationList: RevocationListChecker = mock(classOf()) @Mock val certificateRevocationListRepository: CertificateRevocationListRepository = mock(classOf()) @@ -305,7 +307,7 @@ class MLSWelcomeEventHandlerTest { fun withCheckRevocationListResult() { given(checkRevocationList) - .suspendFunction(checkRevocationList::invoke) + .suspendFunction(checkRevocationList::check) .whenInvokedWith(anything()) .thenReturn(Either.Right(1uL)) } @@ -324,7 +326,7 @@ class MLSWelcomeEventHandlerTest { conversationRepository = conversationRepository, oneOnOneResolver = oneOnOneResolver, refillKeyPackages = refillKeyPackagesUseCase, - checkRevocationList = checkRevocationList, + revocationListChecker = checkRevocationList, certificateRevocationListRepository = certificateRevocationListRepository ) }