diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/e2ei/CertificateRevocationListRepository.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/e2ei/CertificateRevocationListRepository.kt new file mode 100644 index 00000000000..10588351510 --- /dev/null +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/data/e2ei/CertificateRevocationListRepository.kt @@ -0,0 +1,98 @@ +/* + * 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.configuration.UserConfigRepository +import com.wire.kalium.logic.functional.Either +import com.wire.kalium.logic.functional.map +import com.wire.kalium.logic.wrapApiRequest +import com.wire.kalium.network.api.base.unbound.acme.ACMEApi +import com.wire.kalium.persistence.config.CRLUrlExpirationList +import com.wire.kalium.persistence.config.CRLWithExpiration +import com.wire.kalium.persistence.dao.MetadataDAO +import io.ktor.http.Url +import io.ktor.http.protocolWithAuthority + +interface CertificateRevocationListRepository { + + /** + * Returns CRLs with expiration time. + * + * @return the [CRLUrlExpirationList] representing a list of CRLs with expiration time. + */ + suspend fun getCRLs(): CRLUrlExpirationList? + suspend fun addOrUpdateCRL(url: String, timestamp: ULong) + suspend fun getCurrentClientCrlUrl(): Either + suspend fun getClientDomainCRL(url: String): Either +} + +internal class CertificateRevocationListRepositoryDataSource( + private val acmeApi: ACMEApi, + private val metadataDAO: MetadataDAO, + private val userConfigRepository: UserConfigRepository +) : CertificateRevocationListRepository { + override suspend fun getCRLs(): CRLUrlExpirationList? = + metadataDAO.getSerializable(CRL_LIST_KEY, CRLUrlExpirationList.serializer()) + + override suspend fun addOrUpdateCRL(url: String, timestamp: ULong) { + val newCRLUrls = metadataDAO.getSerializable(CRL_LIST_KEY, CRLUrlExpirationList.serializer()) + ?.let { crlExpirationList -> + val crlWithExpiration = crlExpirationList.cRLWithExpirationList.find { + it.url == url + } + crlWithExpiration?.let { item -> + crlExpirationList.cRLWithExpirationList.map { current -> + if (current.url == url) { + return@map item.copy(expiration = timestamp) + } else { + return@map current + } + } + } ?: run { + // add new CRL + crlExpirationList.cRLWithExpirationList.plus( + CRLWithExpiration(url, timestamp) + ) + } + + } ?: run { + // add new CRL + listOf(CRLWithExpiration(url, timestamp)) + } + metadataDAO.putSerializable( + CRL_LIST_KEY, + CRLUrlExpirationList(newCRLUrls), + CRLUrlExpirationList.serializer() + ) + } + + override suspend fun getCurrentClientCrlUrl(): Either = + userConfigRepository.getE2EISettings().map { + (Url(it.discoverUrl).protocolWithAuthority) + } + + override suspend fun getClientDomainCRL(url: String): Either = + wrapApiRequest { + acmeApi.getClientDomainCRL(url) + } + + companion object { + const val CRL_LIST_KEY = "crl_list_key" + } +} 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 7b9d66f4547..bcf4ae7e67a 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 @@ -77,6 +77,8 @@ import com.wire.kalium.logic.data.conversation.ProposalTimer import com.wire.kalium.logic.data.conversation.SubconversationRepositoryImpl import com.wire.kalium.logic.data.conversation.UpdateKeyingMaterialThresholdProvider import com.wire.kalium.logic.data.conversation.UpdateKeyingMaterialThresholdProviderImpl +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.event.EventDataSource @@ -205,6 +207,8 @@ import com.wire.kalium.logic.feature.conversation.mls.OneOnOneResolverImpl 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.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.usecase.CheckRevocationListUseCaseImpl import com.wire.kalium.logic.feature.e2ei.usecase.EnrollE2EIUseCase @@ -1509,6 +1513,12 @@ class UserSessionScope internal constructor( userStorage.database.clientDAO, userStorage.database.metadataDAO, ) + private val certificateRevocationListRepository: CertificateRevocationListRepository + get() = CertificateRevocationListRepositoryDataSource( + acmeApi = globalScope.unboundNetworkContainer.acmeApi, + metadataDAO = userStorage.database.metadataDAO, + userConfigRepository = userConfigRepository + ) private val proteusPreKeyRefiller: ProteusPreKeyRefiller get() = ProteusPreKeyRefillerImpl(preKeyRepository) @@ -1521,6 +1531,14 @@ class UserSessionScope internal constructor( ) } + private val certificateRevocationListCheckWorker: CertificateRevocationListCheckWorker by lazy { + CertificateRevocationListCheckWorkerImpl( + certificateRevocationListRepository = certificateRevocationListRepository, + incrementalSyncRepository = incrementalSyncRepository, + checkRevocationList = checkRevocationList, + ) + } + private val featureFlagsSyncWorker: FeatureFlagsSyncWorker by lazy { FeatureFlagSyncWorkerImpl( incrementalSyncRepository = incrementalSyncRepository, @@ -1882,7 +1900,7 @@ class UserSessionScope internal constructor( private val checkRevocationList: CheckRevocationListUseCase get() = CheckRevocationListUseCaseImpl( - e2EIRepository = e2eiRepository, + certificateRevocationListRepository = certificateRevocationListRepository, currentClientIdProvider = clientIdProvider, mlsClientProvider = mlsClientProvider, mLSConversationsVerificationStatusesHandler = mlsConversationsVerificationStatusesHandler @@ -1920,6 +1938,10 @@ class UserSessionScope internal constructor( proteusSyncWorker.execute() } + launch { + certificateRevocationListCheckWorker.execute() + } + launch { avsSyncStateReporter.execute() } 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 new file mode 100644 index 00000000000..1f312f6755f --- /dev/null +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/e2ei/CertificateRevocationListCheckWorker.kt @@ -0,0 +1,66 @@ +/* + * 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.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.functional.map +import com.wire.kalium.logic.kaliumLogger +import kotlinx.coroutines.flow.filter +import kotlinx.datetime.Clock + +/** + * This worker will wait until the sync is done and then check the CRLs if needed. + * + */ +internal interface CertificateRevocationListCheckWorker { + suspend fun execute() +} + +/** + * Base implementation of [CertificateRevocationListCheckWorker]. + * @param certificateRevocationListRepository The CRL repository. + * @param incrementalSyncRepository The incremental sync repository. + * @param checkRevocationList The check revocation list use case. + * + */ +internal class CertificateRevocationListCheckWorkerImpl( + private val certificateRevocationListRepository: CertificateRevocationListRepository, + private val incrementalSyncRepository: IncrementalSyncRepository, + private val checkRevocationList: CheckRevocationListUseCase +) : CertificateRevocationListCheckWorker { + + override suspend fun execute() { + incrementalSyncRepository.incrementalSyncState + .filter { it is IncrementalSyncStatus.Live } + .collect { + kaliumLogger.i("Checking certificate revocation list (CRL)..") + certificateRevocationListRepository.getCRLs()?.cRLWithExpirationList?.forEach { crl -> + if (crl.expiration < Clock.System.now().epochSeconds.toULong()) { + checkRevocationList(crl.url).map { newExpirationTime -> + newExpirationTime?.let { + certificateRevocationListRepository.addOrUpdateCRL(crl.url, it) + } + } + } + } + } + } +} diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/e2ei/usecase/CheckRevocationListUseCase.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/e2ei/usecase/CheckRevocationListUseCase.kt index 825b38d6735..b2821f034e7 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/e2ei/usecase/CheckRevocationListUseCase.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/e2ei/usecase/CheckRevocationListUseCase.kt @@ -19,7 +19,7 @@ package com.wire.kalium.logic.feature.e2ei.usecase import com.wire.kalium.logic.CoreFailure import com.wire.kalium.logic.data.client.MLSClientProvider -import com.wire.kalium.logic.data.e2ei.E2EIRepository +import com.wire.kalium.logic.data.e2ei.CertificateRevocationListRepository import com.wire.kalium.logic.data.id.CurrentClientIdProvider import com.wire.kalium.logic.feature.conversation.MLSConversationsVerificationStatusesHandler import com.wire.kalium.logic.functional.Either @@ -34,13 +34,13 @@ interface CheckRevocationListUseCase { } internal class CheckRevocationListUseCaseImpl( - private val e2EIRepository: E2EIRepository, + private val certificateRevocationListRepository: CertificateRevocationListRepository, private val currentClientIdProvider: CurrentClientIdProvider, private val mlsClientProvider: MLSClientProvider, private val mLSConversationsVerificationStatusesHandler: MLSConversationsVerificationStatusesHandler ) : CheckRevocationListUseCase { override suspend fun invoke(url: String): Either { - return e2EIRepository.getClientDomainCRL(url).flatMap { + return certificateRevocationListRepository.getClientDomainCRL(url).flatMap { currentClientIdProvider().flatMap { clientId -> mlsClientProvider.getMLSClient(clientId).map { mlsClient -> mlsClient.registerCrl(url, it).run { diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/e2ei/CertificateRevocationListRepositoryTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/e2ei/CertificateRevocationListRepositoryTest.kt new file mode 100644 index 00000000000..701e98c83e4 --- /dev/null +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/data/e2ei/CertificateRevocationListRepositoryTest.kt @@ -0,0 +1,155 @@ +/* + * 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.configuration.UserConfigRepository +import com.wire.kalium.logic.data.e2ei.CertificateRevocationListRepositoryDataSource.Companion.CRL_LIST_KEY +import com.wire.kalium.network.api.base.unbound.acme.ACMEApi +import com.wire.kalium.persistence.config.CRLWithExpiration +import com.wire.kalium.persistence.config.CRLUrlExpirationList +import com.wire.kalium.persistence.dao.MetadataDAO +import io.mockative.Mock +import io.mockative.classOf +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 + +class CertificateRevocationListRepositoryTest { + + @Test + fun givenAnEmptyStoredList_whenUpdatingCRLs_thenAddNewCRL() = runTest { + val (arrangement, crlRepository) = Arrangement() + .withEmptyList() + .arrange() + + crlRepository.addOrUpdateCRL(DUMMY_URL, TIMESTAMP) + + verify(arrangement.metadataDAO).coroutine { + putSerializable( + CRL_LIST_KEY, + CRLUrlExpirationList(listOf(CRLWithExpiration(DUMMY_URL, TIMESTAMP))), + CRLUrlExpirationList.serializer() + ) + }.wasInvoked(once) + } + @Test + fun givenNoStoredList_whenUpdatingCRLs_thenAddNewCRL() = runTest { + val (arrangement, crlRepository) = Arrangement() + .withNullCRLResult() + .arrange() + + crlRepository.addOrUpdateCRL(DUMMY_URL, TIMESTAMP) + + verify(arrangement.metadataDAO).coroutine { + putSerializable( + CRL_LIST_KEY, + CRLUrlExpirationList(listOf(CRLWithExpiration(DUMMY_URL, TIMESTAMP))), + CRLUrlExpirationList.serializer() + ) + }.wasInvoked(once) + } + + @Test + fun givenPassedCRLExistsInStoredList_whenUpdatingCRLs_thenUpdateCurrentCRL() = runTest { + val (arrangement, crlRepository) = Arrangement() + .withCRLs() + .arrange() + + crlRepository.addOrUpdateCRL(DUMMY_URL, TIMESTAMP2) + + verify(arrangement.metadataDAO).coroutine { + putSerializable( + CRL_LIST_KEY, + CRLUrlExpirationList(listOf(CRLWithExpiration(DUMMY_URL, TIMESTAMP2))), + CRLUrlExpirationList.serializer() + ) + }.wasInvoked(once) + } + + @Test + fun givenNewCRLUrl_whenUpdatingCRLs_thenAddNewCRL() = runTest { + val (arrangement, crlRepository) = Arrangement() + .withCRLs() + .arrange() + + crlRepository.addOrUpdateCRL(DUMMY_URL2, TIMESTAMP) + + verify(arrangement.metadataDAO).coroutine { + putSerializable( + CRL_LIST_KEY, + CRLUrlExpirationList( + listOf( + CRLWithExpiration(DUMMY_URL, TIMESTAMP), + CRLWithExpiration(DUMMY_URL2, TIMESTAMP) + ) + ), + CRLUrlExpirationList.serializer() + ) + }.wasInvoked(once) + } + + private class Arrangement { + + @Mock + val acmeApi = mock(classOf()) + + @Mock + val metadataDAO = mock(classOf()) + + @Mock + val userConfigRepository = mock(classOf()) + + fun arrange() = this to CertificateRevocationListRepositoryDataSource(acmeApi, metadataDAO, userConfigRepository) + + suspend fun withEmptyList() = apply { + given(metadataDAO).coroutine { + metadataDAO.getSerializable( + CRL_LIST_KEY, + CRLUrlExpirationList.serializer() + ) + }.thenReturn(CRLUrlExpirationList(listOf())) + } + suspend fun withNullCRLResult() = apply { + given(metadataDAO).coroutine { + metadataDAO.getSerializable( + CRL_LIST_KEY, + CRLUrlExpirationList.serializer() + ) + }.thenReturn(null) + } + + suspend fun withCRLs() = apply { + given(metadataDAO).coroutine { + metadataDAO.getSerializable( + CRL_LIST_KEY, + CRLUrlExpirationList.serializer() + ) + }.thenReturn(CRLUrlExpirationList(listOf(CRLWithExpiration(DUMMY_URL, TIMESTAMP)))) + } + } + + companion object { + private const val DUMMY_URL = "https://dummy.url" + private const val DUMMY_URL2 = "https://dummy-2.url" + private val TIMESTAMP = 1234567890.toULong() + private val TIMESTAMP2 = 5453222.toULong() + } +} diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/e2ei/CertificateRevocationListCheckTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/e2ei/CertificateRevocationListCheckTest.kt new file mode 100644 index 00000000000..5d2e16dde4b --- /dev/null +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/e2ei/CertificateRevocationListCheckTest.kt @@ -0,0 +1,124 @@ +/* + * 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.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.functional.Either +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.eq +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 +import kotlin.test.Test + +class CertificateRevocationListCheckTest { + + @Test + fun givenExpiredCRL_whenTimeElapses_thenCheckRevocationList() = runTest { + val (arrangement, checkCrlWorker) = Arrangement() + .withIncrementalSyncState(flowOf(IncrementalSyncStatus.Live)) + .withExpiredCRL() + .withCheckRevocationListResult() + .arrange() + + checkCrlWorker.execute() + + verify(arrangement.certificateRevocationListRepository) + .suspendFunction(arrangement.certificateRevocationListRepository::getCRLs) + .wasInvoked(exactly = once) + + verify(arrangement.checkRevocationList) + .suspendFunction(arrangement.checkRevocationList::invoke) + .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 { + + @Mock + val certificateRevocationListRepository = mock(classOf()) + + @Mock + val incrementalSyncRepository = mock(classOf()) + + @Mock + val checkRevocationList = mock(classOf()) + + fun arrange() = this to CertificateRevocationListCheckWorkerImpl( + certificateRevocationListRepository, incrementalSyncRepository, checkRevocationList + ) + + fun withNoCRL() = apply { + given(certificateRevocationListRepository) + .suspendFunction(certificateRevocationListRepository::getCRLs) + .whenInvoked() + .thenReturn(null) + } + + fun withNonExpiredCRL() = apply { + given(certificateRevocationListRepository) + .suspendFunction(certificateRevocationListRepository::getCRLs) + .whenInvoked() + .thenReturn(CRLUrlExpirationList(listOf(CRLWithExpiration(DUMMY_URL, FUTURE_TIMESTAMP)))) + } + + fun withExpiredCRL() = apply { + given(certificateRevocationListRepository) + .suspendFunction(certificateRevocationListRepository::getCRLs) + .whenInvoked() + .thenReturn(CRLUrlExpirationList(listOf(CRLWithExpiration(DUMMY_URL, TIMESTAMP)))) + } + fun withCheckRevocationListResult() = apply { + given(checkRevocationList) + .suspendFunction(checkRevocationList::invoke) + .whenInvokedWith(any()) + .thenReturn(Either.Right(FUTURE_TIMESTAMP)) + } + + fun withIncrementalSyncState(flow: Flow) = apply { + given(incrementalSyncRepository) + .getter(incrementalSyncRepository::incrementalSyncState) + .whenInvoked() + .thenReturn(flow) + } + + } + + companion object { + const val DUMMY_URL = "https://dummy.url" + val TIMESTAMP = 633218892.toULong() // Wednesday, 24 January 1990 22:08:12 + val FUTURE_TIMESTAMP = 4104511692.toULong() // Sunday, 24 January 2100 22:08:12 + } +} diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/e2ei/usecase/CheckRevocationListUseCaseTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/e2ei/usecase/CheckRevocationListUseCaseTest.kt index 2a9c46b58ac..51d3a7511c7 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/e2ei/usecase/CheckRevocationListUseCaseTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/e2ei/usecase/CheckRevocationListUseCaseTest.kt @@ -22,7 +22,7 @@ import com.wire.kalium.cryptography.MLSClient import com.wire.kalium.logic.CoreFailure import com.wire.kalium.logic.E2EIFailure import com.wire.kalium.logic.data.client.MLSClientProvider -import com.wire.kalium.logic.data.e2ei.E2EIRepository +import com.wire.kalium.logic.data.e2ei.CertificateRevocationListRepository import com.wire.kalium.logic.data.id.CurrentClientIdProvider import com.wire.kalium.logic.feature.conversation.MLSConversationsVerificationStatusesHandler import com.wire.kalium.logic.framework.TestClient @@ -54,8 +54,8 @@ class CheckRevocationListUseCaseTest { val result = checkRevocationList.invoke(DUMMY_URL) result.shouldFail() - verify(arrangement.e2EIRepository) - .suspendFunction(arrangement.e2EIRepository::getClientDomainCRL) + verify(arrangement.certificateRevocationListRepository) + .suspendFunction(arrangement.certificateRevocationListRepository::getClientDomainCRL) .with(any()) .wasInvoked(once) @@ -76,8 +76,8 @@ class CheckRevocationListUseCaseTest { val result = checkRevocationList.invoke(DUMMY_URL) result.shouldFail() - verify(arrangement.e2EIRepository) - .suspendFunction(arrangement.e2EIRepository::getClientDomainCRL) + verify(arrangement.certificateRevocationListRepository) + .suspendFunction(arrangement.certificateRevocationListRepository::getClientDomainCRL) .with(any()) .wasInvoked(once) @@ -178,7 +178,7 @@ class CheckRevocationListUseCaseTest { internal class Arrangement { @Mock - val e2EIRepository = mock(classOf()) + val certificateRevocationListRepository = mock(classOf()) @Mock val mlsClient = mock(classOf()) @@ -196,22 +196,22 @@ class CheckRevocationListUseCaseTest { mock(classOf()) fun arrange() = this to CheckRevocationListUseCaseImpl( - e2EIRepository = e2EIRepository, + certificateRevocationListRepository = certificateRevocationListRepository, currentClientIdProvider = currentClientIdProvider, mlsClientProvider = mlsClientProvider, mLSConversationsVerificationStatusesHandler = mLSConversationsVerificationStatusesHandler ) fun withE2EIRepositoryFailure() = apply { - given(e2EIRepository) - .suspendFunction(e2EIRepository::getClientDomainCRL) + given(certificateRevocationListRepository) + .suspendFunction(certificateRevocationListRepository::getClientDomainCRL) .whenInvokedWith(any()) .thenReturn(Either.Left(E2EIFailure.Generic(Exception()))) } fun withE2EIRepositorySuccess() = apply { - given(e2EIRepository) - .suspendFunction(e2EIRepository::getClientDomainCRL) + given(certificateRevocationListRepository) + .suspendFunction(certificateRevocationListRepository::getClientDomainCRL) .whenInvokedWith(any()) .thenReturn(Either.Right("result".toByteArray())) } @@ -260,7 +260,7 @@ class CheckRevocationListUseCaseTest { } companion object { - const val DUMMY_URL = "https://dummy.url" - val EXPIRATION = 10.toULong() + private const val DUMMY_URL = "https://dummy.url" + private val EXPIRATION = 10.toULong() } } diff --git a/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/config/UserConfigStorage.kt b/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/config/UserConfigStorage.kt index e046b1c2c6d..8f9c9d756bc 100644 --- a/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/config/UserConfigStorage.kt +++ b/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/config/UserConfigStorage.kt @@ -225,6 +225,17 @@ data class LastPreKey( @SerialName("key") val key: String, ) +@Serializable +data class CRLUrlExpirationList( + @SerialName("crl_with_expiration_list") val cRLWithExpirationList: List +) + +@Serializable +data class CRLWithExpiration( + @SerialName("url") val url: String, + @SerialName("expiration") val expiration: ULong +) + @Serializable sealed class SelfDeletionTimerEntity {