Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit b5bb1665 authored by Wolf-Martell Montwé's avatar Wolf-Martell Montwé Committed by GitHub
Browse files

Merge pull request #7166 from thundernest/add_account_loader

Add account loader
parents cc399240 496a64c0
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
package app.k9mail.feature.preview

import app.k9mail.core.common.oauth.OAuthConfigurationFactory
import app.k9mail.feature.account.common.AccountCommonExternalContract
import app.k9mail.feature.account.edit.AccountEditExternalContract
import app.k9mail.feature.account.setup.AccountSetupExternalContract
import app.k9mail.feature.account.setup.featureAccountSetupModule
@@ -23,6 +24,7 @@ val accountModule: Module = module {
    single { InMemoryAccountStore() }
        .binds(
            arrayOf(
                AccountCommonExternalContract.AccountStateLoader::class,
                AccountSetupExternalContract.AccountCreator::class,
                AccountEditExternalContract.AccountUpdater::class,
            ),
+23 −1
Original line number Diff line number Diff line
package app.k9mail.feature.preview.account

import app.k9mail.feature.account.common.AccountCommonExternalContract.AccountStateLoader
import app.k9mail.feature.account.common.domain.entity.Account
import app.k9mail.feature.account.common.domain.entity.AccountState
import app.k9mail.feature.account.common.domain.entity.AuthorizationState
import app.k9mail.feature.account.edit.AccountEditExternalContract.AccountUpdater
import app.k9mail.feature.account.edit.AccountEditExternalContract.AccountUpdater.AccountUpdaterResult
import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator
@@ -8,7 +11,15 @@ import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCrea

class InMemoryAccountStore(
    private val accountMap: MutableMap<String, Account> = mutableMapOf(),
) : AccountCreator, AccountUpdater {
) : AccountCreator, AccountUpdater, AccountStateLoader {

    suspend fun load(accountUuid: String): Account? {
        return accountMap[accountUuid]
    }

    override suspend fun loadAccountState(accountUuid: String): AccountState? {
        return accountMap[accountUuid]?.let { mapToAccountState(it) }
    }

    override suspend fun createAccount(account: Account): AccountCreatorResult {
        accountMap[account.uuid] = account
@@ -25,4 +36,15 @@ class InMemoryAccountStore(
            AccountUpdaterResult.Success(account.uuid)
        }
    }

    private fun mapToAccountState(account: Account): AccountState {
        return AccountState(
            uuid = account.uuid,
            emailAddress = account.emailAddress,
            incomingServerSettings = account.incomingServerSettings,
            outgoingServerSettings = account.outgoingServerSettings,
            authorizationState = account.authorizationState?.let { AuthorizationState(it) },
            options = account.options,
        )
    }
}
+7 −0
Original line number Diff line number Diff line
package com.fsck.k9.account

import app.k9mail.feature.account.common.AccountCommonExternalContract
import app.k9mail.feature.account.edit.AccountEditExternalContract
import app.k9mail.feature.account.setup.AccountSetupExternalContract
import org.koin.android.ext.koin.androidApplication
@@ -21,6 +22,12 @@ val newAccountModule = module {
        )
    }

    factory<AccountCommonExternalContract.AccountStateLoader> {
        AccountStateLoader(
            accountManager = get(),
        )
    }

    factory<AccountEditExternalContract.AccountUpdater> {
        AccountUpdater(
            preferences = get(),
+44 −0
Original line number Diff line number Diff line
package com.fsck.k9.account

import app.k9mail.feature.account.common.AccountCommonExternalContract
import app.k9mail.feature.account.common.domain.entity.AccountState
import app.k9mail.feature.account.common.domain.entity.AuthorizationState
import com.fsck.k9.logging.Timber
import com.fsck.k9.preferences.AccountManager
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import com.fsck.k9.Account as K9Account

class AccountStateLoader(
    private val accountManager: AccountManager,
    private val coroutineDispatcher: CoroutineDispatcher = Dispatchers.IO,
) : AccountCommonExternalContract.AccountStateLoader {

    @Suppress("TooGenericExceptionCaught")
    override suspend fun loadAccountState(accountUuid: String): AccountState? {
        return try {
            withContext(coroutineDispatcher) {
                load(accountUuid)
            }
        } catch (e: Exception) {
            Timber.e(e, "Error while loading account")

            null
        }
    }

    private fun load(accountUuid: String): AccountState? {
        return accountManager.getAccount(accountUuid)?.let { mapToAccountState(it) }
    }

    private fun mapToAccountState(account: K9Account): AccountState {
        return AccountState(
            uuid = account.uuid,
            emailAddress = account.email,
            incomingServerSettings = account.incomingServerSettings,
            outgoingServerSettings = account.outgoingServerSettings,
            authorizationState = AuthorizationState(account.oAuthState),
        )
    }
}
+80 −0
Original line number Diff line number Diff line
package com.fsck.k9.account

import app.k9mail.feature.account.common.domain.entity.AccountState
import app.k9mail.feature.account.common.domain.entity.AuthorizationState
import assertk.assertThat
import assertk.assertions.isEqualTo
import assertk.assertions.isNull
import com.fsck.k9.Account
import com.fsck.k9.Identity
import com.fsck.k9.mail.AuthType
import com.fsck.k9.mail.ConnectionSecurity
import com.fsck.k9.mail.ServerSettings
import kotlinx.coroutines.test.runTest
import org.junit.Test

class AccountStateLoaderTest {

    @Test
    fun `loadAccountState() should return null when accountManager returns null`() = runTest {
        val accountManager = FakeAccountManager()
        val accountLoader = AccountStateLoader(accountManager)

        val result = accountLoader.loadAccountState("accountUuid")

        assertThat(result).isNull()
    }

    @Test
    fun `loadAccountState() should return account when present in accountManager`() = runTest {
        val accounts = mapOf(
            "accountUuid" to Account(uuid = "accountUuid").apply {
                identities = mutableListOf(Identity())
                email = "emailAddress"
                incomingServerSettings = INCOMING_SERVER_SETTINGS
                outgoingServerSettings = OUTGOING_SERVER_SETTINGS
                oAuthState = "oAuthState"
            },
        )
        val accountManager = FakeAccountManager(accounts = accounts)
        val accountLoader = AccountStateLoader(accountManager)

        val result = accountLoader.loadAccountState("accountUuid")

        assertThat(result).isEqualTo(
            AccountState(
                uuid = "accountUuid",
                emailAddress = "emailAddress",
                incomingServerSettings = INCOMING_SERVER_SETTINGS,
                outgoingServerSettings = OUTGOING_SERVER_SETTINGS,
                authorizationState = AuthorizationState("oAuthState"),
            ),
        )
    }

    private companion object {
        val INCOMING_SERVER_SETTINGS = ServerSettings(
            type = "imap",
            host = "imap.example.org",
            port = 143,
            connectionSecurity = ConnectionSecurity.SSL_TLS_REQUIRED,
            authenticationType = AuthType.PLAIN,
            username = "username",
            password = "password",
            clientCertificateAlias = null,
            extra = emptyMap(),
        )

        val OUTGOING_SERVER_SETTINGS = ServerSettings(
            type = "smtp",
            host = "smtp.example.org",
            port = 587,
            connectionSecurity = ConnectionSecurity.SSL_TLS_REQUIRED,
            authenticationType = AuthType.PLAIN,
            username = "username",
            password = "password",
            clientCertificateAlias = null,
            extra = emptyMap(),
        )
    }
}
Loading