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

Commit 0e2a4daa authored by Mohammed Althaf T's avatar Mohammed Althaf T 😊
Browse files

mail: Sync mail with account manager

parent 26add5ab
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ android {
}

dependencies {
    implementation(projects.legacy.account)
    implementation(projects.core.common)
    implementation(projects.mail.common)
    implementation(projects.feature.autodiscovery.api)
+1 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ object AccountManagerConstants {
    const val ACCOUNT_EMAIL_ADDRESS_KEY = "email_address"
    const val MAIL_CONTENT_AUTHORITY = "foundation.e.mail.provider.AppContentProvider"
    const val KEY_AUTH_STATE = "auth_state"
    const val AUTH_TOKEN_TYPE = "oauth2-access-token"

    val ACCOUNT_TYPES = listOf(EELO_ACCOUNT_TYPE, GOOGLE_ACCOUNT_TYPE, YAHOO_ACCOUNT_TYPE)

+151 −0
Original line number Diff line number Diff line
package app.k9mail.feature.account.accountmanager

import android.accounts.Account
import android.accounts.AccountManager
import android.content.Context
import com.fsck.k9.logging.Timber
import com.fsck.k9.mail.AuthType
import com.fsck.k9.mail.oauth.AuthStateStorage
import app.k9mail.legacy.account.Account as kAccount
import app.k9mail.legacy.account.AccountManager as kAccountManager

object AccountManagerHelper {
    /**
     * Update oAuthState for google accounts which is logged in using accountManager
     * @return is the update operation successful or not
     */
    fun updateOAuthState(context: Context, accountManager: kAccountManager, account: kAccount?): Boolean {
        // check params
        if (account == null) {
            Timber.w("updating OAuthState failed, account is null")
            return false
        }

        // validation
        if (account.incomingServerSettings.authenticationType != AuthType.XOAUTH2) {
            Timber.w("updating oAuthState failed, not oauth2 authType")
            return false
        }

        val osAccountManager = AccountManager.get(context)

        var result = false
        AccountManagerConstants.ACCOUNT_TYPES.forEach {
            val openIdAccount = retrieveOpenIdAccountFromAccountManager(osAccountManager, it, account.email)
            if (openIdAccount != null) {
                updateOAuthState(account, osAccountManager, openIdAccount, accountManager)
                result = true
                return@forEach
            }
        }

        return result
    }

    fun updateOAuthState(context: Context, authStateStorage: AuthStateStorage): Boolean {
        // check params
        if (authStateStorage.getEmail().isNullOrBlank()) {
            Timber.w("updating OAuthState failed, email is null")
            return false
        }

        val osAccountManager = AccountManager.get(context)

        var result = false
        AccountManagerConstants.ACCOUNT_TYPES.forEach {
            val openIdAccount =
                retrieveOpenIdAccountFromAccountManager(osAccountManager, it, authStateStorage.getEmail())
            if (openIdAccount != null) {
                updateOAuthState(authStateStorage, openIdAccount, osAccountManager)
                result = true
                return@forEach
            }
        }

        return result
    }

    private fun updateOAuthState(
        account: kAccount,
        osAccountManager: AccountManager,
        openIdAccount: Account?,
        accountManager: kAccountManager,
    ) {
        account.oAuthState = osAccountManager.getUserData(openIdAccount, AccountManagerConstants.KEY_AUTH_STATE)
        accountManager.saveAccount(account)
    }

    private fun updateOAuthState(
        authStateStorage: AuthStateStorage,
        openIdAccount: Account?,
        osAccountManager: AccountManager,
    ) {
        val authState = osAccountManager.getUserData(openIdAccount, AccountManagerConstants.KEY_AUTH_STATE)
        authStateStorage.updateAuthorizationState(authorizationState = authState)
    }

    // If token is updated by mail, also update the accountManager
    fun updateAccountInAccountManager(
        context: Context?,
        account: Account?,
        authState: String?,
        accessToken: String?,
    ) {
        if (context == null || account == null || authState == null || accessToken == null) {
            Timber.w("updating account for accountManager failed, invalid param.")
            return
        }

        val accountManager = AccountManager.get(context)
        accountManager.setAuthToken(account, AccountManagerConstants.AUTH_TOKEN_TYPE, accessToken)
        accountManager.setUserData(account, AccountManagerConstants.KEY_AUTH_STATE, authState)
    }

    fun retrieveOpenIdAccountFromAccountManager(context: Context?, email: String?): Account? {
        if (context == null) {
            Timber.w("retrieve google accounts from accountManager failed, null context.")
            return null
        }

        val accountManager = AccountManager.get(context)

        var resultAccount: Account? = null

        AccountManagerConstants.ACCOUNT_TYPES.forEach {
            resultAccount = retrieveOpenIdAccountFromAccountManager(accountManager, it, email)
            if (resultAccount != null) {
                return@forEach
            }
        }

        return resultAccount
    }

    private fun retrieveOpenIdAccountFromAccountManager(
        accountManager: AccountManager?,
        accountType: String,
        email: String?,
    ): Account? {
        if (accountManager == null || email.isNullOrEmpty()) {
            Timber.w("retrieve $accountType account from accountManager failed, invalid param")
            return null
        }

        val openIdAccounts = accountManager.getAccountsByType(accountType)
        for (openIdAccount in openIdAccounts) {
            val emailId = accountManager.getUserData(openIdAccount, AccountManagerConstants.ACCOUNT_EMAIL_ADDRESS_KEY)
            if (!email.equals(emailId, ignoreCase = true)) {
                continue
            }

            val authState = accountManager.getUserData(openIdAccount, AccountManagerConstants.KEY_AUTH_STATE)
            if (authState.isNullOrEmpty()) {
                return null
            }

            return openIdAccount
        }

        return null
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -18,6 +18,10 @@ class InMemoryAccountStateRepository(
        return state
    }

    override fun getEmail(): String? {
        return state.emailAddress
    }

    override fun setState(accountState: AccountState) {
        state = accountState
    }
+4 −0
Original line number Diff line number Diff line
@@ -10,4 +10,8 @@ class FakeAuthStateStorage(
    override fun updateAuthorizationState(authorizationState: String?) {
        this.authorizationState = authorizationState
    }

    override fun getEmail(): String? {
        return null
    }
}
Loading