From 795b5a42eacfb4da2032b7aeb9d46d83b2ca0295 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Fri, 1 Sep 2023 11:52:05 +0200 Subject: [PATCH 1/2] Add servercertificate module and move code from setup there --- .../servercertificate/build.gradle.kts | 18 ++++++++++ .../AccountServerCertificateModule.kt | 29 +++++++++++++++ ...nMemoryServerCertificateErrorRepository.kt | 21 +++++++++++ .../AccountServerCertificateDomainContract.kt | 21 +++++++++++ .../domain/entity/ServerCertificateError.kt} | 4 +-- .../usecase/AddServerCertificateException.kt | 6 ++-- .../AccountServerCertificateErrorContract.kt} | 4 +-- .../AccountServerCertificateErrorScreen.kt} | 22 ++++++------ ...AccountServerCertificateErrorViewModel.kt} | 32 ++++++++--------- .../AccountServerCertificateModuleKtTest.kt | 35 +++++++++++++++++++ feature/account/setup/build.gradle.kts | 3 ++ .../account/setup/AccountSetupModule.kt | 20 ++--------- .../InMemoryCertificateErrorRepository.kt | 21 ----------- .../account/setup/domain/DomainContract.kt | 9 ----- .../validation/AccountValidationMainScreen.kt | 10 +++--- .../ui/validation/AccountValidationScreen.kt | 2 +- .../validation/AccountValidationViewModel.kt | 7 ++-- .../account/setup/AccountSetupModuleKtTest.kt | 4 +-- .../AccountValidationViewModelTest.kt | 6 ++-- settings.gradle.kts | 1 + 20 files changed, 179 insertions(+), 96 deletions(-) create mode 100644 feature/account/servercertificate/build.gradle.kts create mode 100644 feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/AccountServerCertificateModule.kt create mode 100644 feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/data/InMemoryServerCertificateErrorRepository.kt create mode 100644 feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/AccountServerCertificateDomainContract.kt rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/CertificateError.kt => servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/entity/ServerCertificateError.kt} (57%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate}/domain/usecase/AddServerCertificateException.kt (73%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/servercertificate/CertificateErrorContract.kt => servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorContract.kt} (81%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/servercertificate/CertificateErrorScreen.kt => servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorScreen.kt} (87%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/servercertificate/CertificateErrorViewModel.kt => servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorViewModel.kt} (67%) create mode 100644 feature/account/servercertificate/src/test/kotlin/app/k9mail/feature/account/servercertificate/AccountServerCertificateModuleKtTest.kt delete mode 100644 feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/data/InMemoryCertificateErrorRepository.kt diff --git a/feature/account/servercertificate/build.gradle.kts b/feature/account/servercertificate/build.gradle.kts new file mode 100644 index 000000000..ac04d5f40 --- /dev/null +++ b/feature/account/servercertificate/build.gradle.kts @@ -0,0 +1,18 @@ +plugins { + id(ThunderbirdPlugins.Library.androidCompose) +} + +android { + namespace = "app.k9mail.feature.account.servercertificate" + resourcePrefix = "account_servercertificate_" +} + +dependencies { + implementation(projects.core.ui.compose.designsystem) + implementation(projects.core.common) + implementation(projects.feature.account.common) + + implementation(projects.mail.common) + + testImplementation(projects.core.ui.compose.testing) +} diff --git a/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/AccountServerCertificateModule.kt b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/AccountServerCertificateModule.kt new file mode 100644 index 000000000..94de6d5e3 --- /dev/null +++ b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/AccountServerCertificateModule.kt @@ -0,0 +1,29 @@ +package app.k9mail.feature.account.servercertificate + +import app.k9mail.feature.account.servercertificate.data.InMemoryServerCertificateErrorRepository +import app.k9mail.feature.account.servercertificate.domain.AccountServerCertificateDomainContract +import app.k9mail.feature.account.servercertificate.domain.usecase.AddServerCertificateException +import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorViewModel +import org.koin.androidx.viewmodel.dsl.viewModel +import org.koin.core.module.Module +import org.koin.dsl.module + +val featureAccountServerCertificateModule: Module = module { + + single { + InMemoryServerCertificateErrorRepository() + } + + factory { + AddServerCertificateException( + localKeyStore = get(), + ) + } + + viewModel { + AccountServerCertificateErrorViewModel( + certificateErrorRepository = get(), + addServerCertificateException = get(), + ) + } +} diff --git a/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/data/InMemoryServerCertificateErrorRepository.kt b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/data/InMemoryServerCertificateErrorRepository.kt new file mode 100644 index 000000000..61a2786ee --- /dev/null +++ b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/data/InMemoryServerCertificateErrorRepository.kt @@ -0,0 +1,21 @@ +package app.k9mail.feature.account.servercertificate.data + +import app.k9mail.feature.account.servercertificate.domain.AccountServerCertificateDomainContract +import app.k9mail.feature.account.servercertificate.domain.entity.ServerCertificateError + +class InMemoryServerCertificateErrorRepository( + private var serverCertificateError: ServerCertificateError? = null, +) : AccountServerCertificateDomainContract.ServerCertificateErrorRepository { + + override fun getCertificateError(): ServerCertificateError? { + return serverCertificateError + } + + override fun setCertificateError(serverCertificateError: ServerCertificateError) { + this.serverCertificateError = serverCertificateError + } + + override fun clearCertificateError() { + serverCertificateError = null + } +} diff --git a/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/AccountServerCertificateDomainContract.kt b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/AccountServerCertificateDomainContract.kt new file mode 100644 index 000000000..dd5d8e8ee --- /dev/null +++ b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/AccountServerCertificateDomainContract.kt @@ -0,0 +1,21 @@ +package app.k9mail.feature.account.servercertificate.domain + +import app.k9mail.feature.account.servercertificate.domain.entity.ServerCertificateError +import java.security.cert.X509Certificate + +interface AccountServerCertificateDomainContract { + + interface ServerCertificateErrorRepository { + fun getCertificateError(): ServerCertificateError? + + fun setCertificateError(serverCertificateError: ServerCertificateError) + + fun clearCertificateError() + } + + interface UseCase { + fun interface AddServerCertificateException { + suspend fun addCertificate(hostname: String, port: Int, certificate: X509Certificate?) + } + } +} diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/CertificateError.kt b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/entity/ServerCertificateError.kt similarity index 57% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/CertificateError.kt rename to feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/entity/ServerCertificateError.kt index d85b7a005..796b6d41a 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/CertificateError.kt +++ b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/entity/ServerCertificateError.kt @@ -1,8 +1,8 @@ -package app.k9mail.feature.account.setup.domain.entity +package app.k9mail.feature.account.servercertificate.domain.entity import java.security.cert.X509Certificate -data class CertificateError( +data class ServerCertificateError( val hostname: String, val port: Int, val certificateChain: List, diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/AddServerCertificateException.kt b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/usecase/AddServerCertificateException.kt similarity index 73% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/AddServerCertificateException.kt rename to feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/usecase/AddServerCertificateException.kt index a1cfb8cf2..baf3c3d4f 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/AddServerCertificateException.kt +++ b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/usecase/AddServerCertificateException.kt @@ -1,6 +1,6 @@ -package app.k9mail.feature.account.setup.domain.usecase +package app.k9mail.feature.account.servercertificate.domain.usecase -import app.k9mail.feature.account.setup.domain.DomainContract +import app.k9mail.feature.account.servercertificate.domain.AccountServerCertificateDomainContract.UseCase import com.fsck.k9.mail.ssl.LocalKeyStore import java.security.cert.X509Certificate import kotlinx.coroutines.CoroutineDispatcher @@ -10,7 +10,7 @@ import kotlinx.coroutines.withContext internal class AddServerCertificateException( private val localKeyStore: LocalKeyStore, private val coroutineDispatcher: CoroutineDispatcher = Dispatchers.IO, -) : DomainContract.UseCase.AddServerCertificateException { +) : UseCase.AddServerCertificateException { override suspend fun addCertificate(hostname: String, port: Int, certificate: X509Certificate?) { withContext(coroutineDispatcher) { localKeyStore.addCertificate(hostname, port, certificate) diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/servercertificate/CertificateErrorContract.kt b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorContract.kt similarity index 81% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/servercertificate/CertificateErrorContract.kt rename to feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorContract.kt index 18ffe42a7..e5f21ab86 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/servercertificate/CertificateErrorContract.kt +++ b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorContract.kt @@ -1,8 +1,8 @@ -package app.k9mail.feature.account.setup.ui.servercertificate +package app.k9mail.feature.account.servercertificate.ui import app.k9mail.core.ui.compose.common.mvi.UnidirectionalViewModel -interface CertificateErrorContract { +interface AccountServerCertificateErrorContract { interface ViewModel : UnidirectionalViewModel diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/servercertificate/CertificateErrorScreen.kt b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorScreen.kt similarity index 87% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/servercertificate/CertificateErrorScreen.kt rename to feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorScreen.kt index f02b471a3..7c0a4343a 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/servercertificate/CertificateErrorScreen.kt +++ b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorScreen.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.ui.servercertificate +package app.k9mail.feature.account.servercertificate.ui import androidx.activity.compose.BackHandler import androidx.compose.foundation.layout.Column @@ -21,11 +21,11 @@ import app.k9mail.core.ui.compose.designsystem.template.ResponsiveWidthContainer import app.k9mail.core.ui.compose.designsystem.template.Scaffold import app.k9mail.core.ui.compose.theme.K9Theme import app.k9mail.core.ui.compose.theme.MainTheme -import app.k9mail.feature.account.setup.data.InMemoryCertificateErrorRepository -import app.k9mail.feature.account.setup.domain.entity.CertificateError -import app.k9mail.feature.account.setup.ui.servercertificate.CertificateErrorContract.Effect -import app.k9mail.feature.account.setup.ui.servercertificate.CertificateErrorContract.Event -import app.k9mail.feature.account.setup.ui.servercertificate.CertificateErrorContract.ViewModel +import app.k9mail.feature.account.servercertificate.data.InMemoryServerCertificateErrorRepository +import app.k9mail.feature.account.servercertificate.domain.entity.ServerCertificateError +import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract.Effect +import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract.Event +import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract.ViewModel import java.security.cert.CertificateFactory import java.security.cert.X509Certificate import org.koin.androidx.compose.koinViewModel @@ -33,11 +33,11 @@ import org.koin.androidx.compose.koinViewModel // Note: This is a placeholder with mostly hardcoded text. // TODO: Replace with final design. @Composable -internal fun CertificateErrorScreen( +fun CertificateErrorScreen( onCertificateAccepted: () -> Unit, onBack: () -> Unit, modifier: Modifier = Modifier, - viewModel: ViewModel = koinViewModel(), + viewModel: ViewModel = koinViewModel(), ) { val (state, dispatch) = viewModel.observe { effect -> when (effect) { @@ -138,7 +138,7 @@ internal fun CertificateErrorScreenK9Preview() { val certificateFactory = CertificateFactory.getInstance("X.509") val certificate = certificateFactory.generateCertificate(inputStream) as X509Certificate - val certificateError = CertificateError( + val serverCertificateError = ServerCertificateError( hostname = "mail.domain.example", port = 143, certificateChain = listOf(certificate), @@ -148,9 +148,9 @@ internal fun CertificateErrorScreenK9Preview() { CertificateErrorScreen( onCertificateAccepted = {}, onBack = {}, - viewModel = CertificateErrorViewModel( + viewModel = AccountServerCertificateErrorViewModel( addServerCertificateException = { _, _, _ -> }, - certificateErrorRepository = InMemoryCertificateErrorRepository(certificateError), + certificateErrorRepository = InMemoryServerCertificateErrorRepository(serverCertificateError), ), ) } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/servercertificate/CertificateErrorViewModel.kt b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorViewModel.kt similarity index 67% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/servercertificate/CertificateErrorViewModel.kt rename to feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorViewModel.kt index 1edcde332..58641a40b 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/servercertificate/CertificateErrorViewModel.kt +++ b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorViewModel.kt @@ -1,13 +1,13 @@ -package app.k9mail.feature.account.setup.ui.servercertificate +package app.k9mail.feature.account.servercertificate.ui import androidx.lifecycle.viewModelScope import app.k9mail.core.ui.compose.common.mvi.BaseViewModel -import app.k9mail.feature.account.setup.domain.DomainContract.CertificateErrorRepository -import app.k9mail.feature.account.setup.domain.DomainContract.UseCase.AddServerCertificateException -import app.k9mail.feature.account.setup.domain.entity.CertificateError -import app.k9mail.feature.account.setup.ui.servercertificate.CertificateErrorContract.Effect -import app.k9mail.feature.account.setup.ui.servercertificate.CertificateErrorContract.Event -import app.k9mail.feature.account.setup.ui.servercertificate.CertificateErrorContract.State +import app.k9mail.feature.account.servercertificate.domain.AccountServerCertificateDomainContract +import app.k9mail.feature.account.servercertificate.domain.AccountServerCertificateDomainContract.UseCase +import app.k9mail.feature.account.servercertificate.domain.entity.ServerCertificateError +import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract.Effect +import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract.Event +import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract.State import com.fsck.k9.logging.Timber import com.fsck.k9.mail.filter.Hex import java.security.MessageDigest @@ -15,15 +15,15 @@ import java.security.NoSuchAlgorithmException import java.security.cert.CertificateEncodingException import kotlinx.coroutines.launch -class CertificateErrorViewModel( - private val certificateErrorRepository: CertificateErrorRepository, - private val addServerCertificateException: AddServerCertificateException, +class AccountServerCertificateErrorViewModel( + private val certificateErrorRepository: AccountServerCertificateDomainContract.ServerCertificateErrorRepository, + private val addServerCertificateException: UseCase.AddServerCertificateException, initialState: State = State(), -) : BaseViewModel(initialState), CertificateErrorContract.ViewModel { - private val certificateError: CertificateError? = certificateErrorRepository.getCertificateError() +) : BaseViewModel(initialState), AccountServerCertificateErrorContract.ViewModel { + private val serverCertificateError: ServerCertificateError? = certificateErrorRepository.getCertificateError() init { - setErrorMessage(buildErrorMessage(certificateError)) + setErrorMessage(buildErrorMessage(serverCertificateError)) } override fun event(event: Event) { @@ -34,7 +34,7 @@ class CertificateErrorViewModel( } private fun acceptCertificate() { - val certificateError = requireNotNull(certificateError) + val certificateError = requireNotNull(serverCertificateError) viewModelScope.launch { addServerCertificateException.addCertificate( @@ -56,8 +56,8 @@ class CertificateErrorViewModel( emitEffect(Effect.NavigateCertificateAccepted) } - private fun buildErrorMessage(certificateError: CertificateError?): String { - val certificate = certificateError?.certificateChain?.firstOrNull() ?: return "" + private fun buildErrorMessage(serverCertificateError: ServerCertificateError?): String { + val certificate = serverCertificateError?.certificateChain?.firstOrNull() ?: return "" return buildString { certificate.subjectAlternativeNames?.let { subjectAlternativeNames -> diff --git a/feature/account/servercertificate/src/test/kotlin/app/k9mail/feature/account/servercertificate/AccountServerCertificateModuleKtTest.kt b/feature/account/servercertificate/src/test/kotlin/app/k9mail/feature/account/servercertificate/AccountServerCertificateModuleKtTest.kt new file mode 100644 index 000000000..2009862fb --- /dev/null +++ b/feature/account/servercertificate/src/test/kotlin/app/k9mail/feature/account/servercertificate/AccountServerCertificateModuleKtTest.kt @@ -0,0 +1,35 @@ +package app.k9mail.feature.account.servercertificate + +import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract +import com.fsck.k9.mail.ssl.LocalKeyStore +import org.junit.Test +import org.koin.core.annotation.KoinExperimentalAPI +import org.koin.core.module.Module +import org.koin.dsl.koinApplication +import org.koin.dsl.module +import org.koin.test.KoinTest +import org.koin.test.check.checkModules +import org.koin.test.verify.verify +import org.mockito.Mockito + +class AccountServerCertificateModuleKtTest : KoinTest { + + private val externalModule: Module = module { + single { Mockito.mock() } + } + + @OptIn(KoinExperimentalAPI::class) + @Test + fun `should have a valid di module`() { + featureAccountServerCertificateModule.verify( + extraTypes = listOf( + AccountServerCertificateErrorContract.State::class, + ), + ) + + koinApplication { + modules(externalModule, featureAccountServerCertificateModule) + checkModules() + } + } +} diff --git a/feature/account/setup/build.gradle.kts b/feature/account/setup/build.gradle.kts index 550959528..a5a9c3dc7 100644 --- a/feature/account/setup/build.gradle.kts +++ b/feature/account/setup/build.gradle.kts @@ -19,14 +19,17 @@ android { dependencies { implementation(projects.core.ui.compose.designsystem) implementation(projects.core.common) + implementation(projects.mail.common) implementation(projects.mail.protocols.imap) implementation(projects.mail.protocols.pop3) implementation(projects.mail.protocols.smtp) implementation(projects.feature.autodiscovery.service) + api(projects.feature.account.common) implementation(projects.feature.account.oauth) + implementation(projects.feature.account.servercertificate) testImplementation(projects.core.ui.compose.testing) } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt index e823a4471..d65b3e03d 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt @@ -4,9 +4,8 @@ import app.k9mail.autodiscovery.api.AutoDiscoveryService import app.k9mail.autodiscovery.service.RealAutoDiscoveryService import app.k9mail.feature.account.common.featureAccountCommonModule import app.k9mail.feature.account.oauth.featureAccountOAuthModule -import app.k9mail.feature.account.setup.data.InMemoryCertificateErrorRepository +import app.k9mail.feature.account.servercertificate.featureAccountServerCertificateModule import app.k9mail.feature.account.setup.domain.DomainContract -import app.k9mail.feature.account.setup.domain.usecase.AddServerCertificateException import app.k9mail.feature.account.setup.domain.usecase.CreateAccount import app.k9mail.feature.account.setup.domain.usecase.GetAutoDiscovery import app.k9mail.feature.account.setup.domain.usecase.ValidateServerSettings @@ -23,7 +22,6 @@ import app.k9mail.feature.account.setup.ui.options.AccountOptionsViewModel import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigValidator import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigViewModel -import app.k9mail.feature.account.setup.ui.servercertificate.CertificateErrorViewModel import app.k9mail.feature.account.setup.ui.validation.AccountValidationViewModel import com.fsck.k9.mail.store.imap.ImapServerSettingsValidator import com.fsck.k9.mail.store.pop3.Pop3ServerSettingsValidator @@ -35,7 +33,7 @@ import org.koin.core.qualifier.named import org.koin.dsl.module val featureAccountSetupModule: Module = module { - includes(featureAccountCommonModule, featureAccountOAuthModule) + includes(featureAccountCommonModule, featureAccountOAuthModule, featureAccountServerCertificateModule) single { OkHttpClient() @@ -54,8 +52,6 @@ val featureAccountSetupModule: Module = module { ) } - single { InMemoryCertificateErrorRepository() } - factory { ValidateServerSettings( authStateStorage = get(), @@ -74,12 +70,6 @@ val featureAccountSetupModule: Module = module { ) } - factory { - AddServerCertificateException( - localKeyStore = get(), - ) - } - factory { CreateAccount( accountCreator = get(), @@ -143,12 +133,6 @@ val featureAccountSetupModule: Module = module { accountStateRepository = get(), ) } - viewModel { - CertificateErrorViewModel( - certificateErrorRepository = get(), - addServerCertificateException = get(), - ) - } } internal const val NAME_INCOMING_VALIDATION = "incoming_validation" diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/data/InMemoryCertificateErrorRepository.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/data/InMemoryCertificateErrorRepository.kt deleted file mode 100644 index 834ec8007..000000000 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/data/InMemoryCertificateErrorRepository.kt +++ /dev/null @@ -1,21 +0,0 @@ -package app.k9mail.feature.account.setup.data - -import app.k9mail.feature.account.setup.domain.DomainContract -import app.k9mail.feature.account.setup.domain.entity.CertificateError - -class InMemoryCertificateErrorRepository( - private var certificateError: CertificateError? = null, -) : DomainContract.CertificateErrorRepository { - - override fun getCertificateError(): CertificateError? { - return certificateError - } - - override fun setCertificateError(certificateError: CertificateError) { - this.certificateError = certificateError - } - - override fun clearCertificateError() { - certificateError = null - } -} diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/DomainContract.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/DomainContract.kt index 0a77856e3..e22b349d3 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/DomainContract.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/DomainContract.kt @@ -3,21 +3,12 @@ package app.k9mail.feature.account.setup.domain import app.k9mail.autodiscovery.api.AutoDiscoveryResult import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.feature.account.common.domain.entity.AccountOptions -import app.k9mail.feature.account.setup.domain.entity.CertificateError import com.fsck.k9.mail.ServerSettings import com.fsck.k9.mail.server.ServerSettingsValidationResult import java.security.cert.X509Certificate interface DomainContract { - interface CertificateErrorRepository { - fun getCertificateError(): CertificateError? - - fun setCertificateError(certificateError: CertificateError) - - fun clearCertificateError() - } - interface UseCase { fun interface GetAutoDiscovery { suspend fun execute(emailAddress: String): AutoDiscoveryResult diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationMainScreen.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationMainScreen.kt index b49717408..f51f997ba 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationMainScreen.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationMainScreen.kt @@ -13,8 +13,8 @@ import app.k9mail.feature.account.common.ui.WizardNavigationBar import app.k9mail.feature.account.common.ui.WizardNavigationBarState import app.k9mail.feature.account.common.ui.preview.PreviewAccountStateRepository import app.k9mail.feature.account.oauth.ui.preview.PreviewAccountOAuthViewModel +import app.k9mail.feature.account.servercertificate.data.InMemoryServerCertificateErrorRepository import app.k9mail.feature.account.setup.R -import app.k9mail.feature.account.setup.data.InMemoryCertificateErrorRepository import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Event import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.ViewModel import com.fsck.k9.mail.server.ServerSettingsValidationResult @@ -65,7 +65,7 @@ internal fun AccountIncomingValidationScreenK9Preview() { }, accountStateRepository = PreviewAccountStateRepository(), authorizationStateRepository = { true }, - certificateErrorRepository = InMemoryCertificateErrorRepository(), + certificateErrorRepository = InMemoryServerCertificateErrorRepository(), oAuthViewModel = PreviewAccountOAuthViewModel(), isIncomingValidation = true, ), @@ -84,7 +84,7 @@ internal fun AccountIncomingValidationScreenThunderbirdPreview() { }, accountStateRepository = PreviewAccountStateRepository(), authorizationStateRepository = { true }, - certificateErrorRepository = InMemoryCertificateErrorRepository(), + certificateErrorRepository = InMemoryServerCertificateErrorRepository(), oAuthViewModel = PreviewAccountOAuthViewModel(), isIncomingValidation = true, ), @@ -103,7 +103,7 @@ internal fun AccountOutgoingValidationScreenK9Preview() { }, accountStateRepository = PreviewAccountStateRepository(), authorizationStateRepository = { true }, - certificateErrorRepository = InMemoryCertificateErrorRepository(), + certificateErrorRepository = InMemoryServerCertificateErrorRepository(), oAuthViewModel = PreviewAccountOAuthViewModel(), isIncomingValidation = false, ), @@ -122,7 +122,7 @@ internal fun AccountOutgoingValidationScreenThunderbirdPreview() { }, accountStateRepository = PreviewAccountStateRepository(), authorizationStateRepository = { true }, - certificateErrorRepository = InMemoryCertificateErrorRepository(), + certificateErrorRepository = InMemoryServerCertificateErrorRepository(), oAuthViewModel = PreviewAccountOAuthViewModel(), isIncomingValidation = false, ), diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationScreen.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationScreen.kt index 5cdd6d5d4..634513bbb 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationScreen.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationScreen.kt @@ -5,7 +5,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Modifier import app.k9mail.core.ui.compose.common.mvi.observe -import app.k9mail.feature.account.setup.ui.servercertificate.CertificateErrorScreen +import app.k9mail.feature.account.servercertificate.ui.CertificateErrorScreen import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Effect import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Event import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.ViewModel diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt index c7003ac4b..dbf83ee22 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt @@ -6,8 +6,9 @@ import app.k9mail.feature.account.common.domain.AccountDomainContract import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract import app.k9mail.feature.account.oauth.domain.entity.OAuthResult import app.k9mail.feature.account.oauth.ui.AccountOAuthContract +import app.k9mail.feature.account.servercertificate.domain.AccountServerCertificateDomainContract +import app.k9mail.feature.account.servercertificate.domain.entity.ServerCertificateError import app.k9mail.feature.account.setup.domain.DomainContract -import app.k9mail.feature.account.setup.domain.entity.CertificateError import app.k9mail.feature.account.setup.domain.entity.isOAuth import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Effect import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Error @@ -25,7 +26,7 @@ internal class AccountValidationViewModel( private val validateServerSettings: DomainContract.UseCase.ValidateServerSettings, private val accountStateRepository: AccountDomainContract.AccountStateRepository, private val authorizationStateRepository: AccountOAuthDomainContract.AuthorizationStateRepository, - private val certificateErrorRepository: DomainContract.CertificateErrorRepository, + private val certificateErrorRepository: AccountServerCertificateDomainContract.ServerCertificateErrorRepository, override val oAuthViewModel: AccountOAuthContract.ViewModel, override val isIncomingValidation: Boolean = true, initialState: State? = null, @@ -169,7 +170,7 @@ internal class AccountValidationViewModel( val serverSettings = checkNotNull(state.value.serverSettings) certificateErrorRepository.setCertificateError( - CertificateError( + ServerCertificateError( hostname = serverSettings.host!!, port = serverSettings.port, certificateChain = error.certificateChain, diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt index 05d3546bd..4d7f20acd 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt @@ -4,6 +4,7 @@ import android.content.Context import app.k9mail.core.common.oauth.OAuthConfigurationFactory import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.oauth.ui.AccountOAuthContract +import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator.AccountCreatorResult import app.k9mail.feature.account.setup.ui.AccountSetupContract @@ -11,7 +12,6 @@ import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryCon import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract -import app.k9mail.feature.account.setup.ui.servercertificate.CertificateErrorContract import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract import com.fsck.k9.mail.oauth.AuthStateStorage import com.fsck.k9.mail.oauth.OAuth2TokenProvider @@ -69,7 +69,7 @@ class AccountSetupModuleKtTest : KoinTest { AccountOutgoingConfigContract.State::class, AccountOptionsContract.State::class, AccountState::class, - CertificateErrorContract.State::class, + AccountServerCertificateErrorContract.State::class, AuthStateStorage::class, Context::class, Boolean::class, diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModelTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModelTest.kt index 10ae44864..91fdfe08a 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModelTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModelTest.kt @@ -5,7 +5,7 @@ import app.k9mail.core.ui.compose.testing.mvi.assertThatAndMviTurbinesConsumed import app.k9mail.core.ui.compose.testing.mvi.turbinesWithInitialStateCheck import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository import app.k9mail.feature.account.common.domain.entity.AccountState -import app.k9mail.feature.account.setup.data.InMemoryCertificateErrorRepository +import app.k9mail.feature.account.servercertificate.data.InMemoryServerCertificateErrorRepository import app.k9mail.feature.account.setup.ui.FakeAccountOAuthViewModel import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Effect import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Error @@ -199,7 +199,7 @@ class AccountValidationViewModelTest { }, accountStateRepository = InMemoryAccountStateRepository(), authorizationStateRepository = { true }, - certificateErrorRepository = InMemoryCertificateErrorRepository(), + certificateErrorRepository = InMemoryServerCertificateErrorRepository(), oAuthViewModel = FakeAccountOAuthViewModel(), initialState = initialState, ) @@ -238,7 +238,7 @@ class AccountValidationViewModelTest { }, accountStateRepository = InMemoryAccountStateRepository(accountState), authorizationStateRepository = { true }, - certificateErrorRepository = InMemoryCertificateErrorRepository(), + certificateErrorRepository = InMemoryServerCertificateErrorRepository(), oAuthViewModel = FakeAccountOAuthViewModel(), initialState = initialState, ) diff --git a/settings.gradle.kts b/settings.gradle.kts index 3fdff2363..6e63d4662 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -46,6 +46,7 @@ include( include( ":feature:account:common", ":feature:account:oauth", + ":feature:account:servercertificate", ":feature:account:setup", ) From 51fb16500332747aad3a6e2a70a4b95d8f5f56f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Fri, 1 Sep 2023 12:37:23 +0200 Subject: [PATCH 2/2] Remove ServerSettingsExtension as it's already part of the OAuth module --- .../account/setup/domain/entity/ServerSettingsExtension.kt | 6 ------ .../setup/ui/validation/AccountValidationViewModel.kt | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) delete mode 100644 feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/ServerSettingsExtension.kt diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/ServerSettingsExtension.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/ServerSettingsExtension.kt deleted file mode 100644 index cc4425d19..000000000 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/ServerSettingsExtension.kt +++ /dev/null @@ -1,6 +0,0 @@ -package app.k9mail.feature.account.setup.domain.entity - -import com.fsck.k9.mail.AuthType -import com.fsck.k9.mail.ServerSettings - -fun ServerSettings?.isOAuth() = this?.authenticationType == AuthType.XOAUTH2 diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt index dbf83ee22..b42acf678 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt @@ -5,11 +5,11 @@ import app.k9mail.core.ui.compose.common.mvi.BaseViewModel import app.k9mail.feature.account.common.domain.AccountDomainContract import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract import app.k9mail.feature.account.oauth.domain.entity.OAuthResult +import app.k9mail.feature.account.oauth.domain.entity.isOAuth import app.k9mail.feature.account.oauth.ui.AccountOAuthContract import app.k9mail.feature.account.servercertificate.domain.AccountServerCertificateDomainContract import app.k9mail.feature.account.servercertificate.domain.entity.ServerCertificateError import app.k9mail.feature.account.setup.domain.DomainContract -import app.k9mail.feature.account.setup.domain.entity.isOAuth import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Effect import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Error import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Event