Merge pull request #6097 from k9mail/oauth_config_provider
Add proper way to retrieve OAuth credentials
This commit is contained in:
commit
402259a834
11 changed files with 78 additions and 40 deletions
|
@ -4,5 +4,5 @@ import org.koin.dsl.module
|
|||
|
||||
val autodiscoveryProvidersXmlModule = module {
|
||||
factory { ProvidersXmlProvider(context = get()) }
|
||||
factory { ProvidersXmlDiscovery(xmlProvider = get()) }
|
||||
factory { ProvidersXmlDiscovery(xmlProvider = get(), oAuthConfigurationProvider = get()) }
|
||||
}
|
||||
|
|
|
@ -9,12 +9,14 @@ import com.fsck.k9.autodiscovery.api.DiscoveryTarget
|
|||
import com.fsck.k9.helper.EmailHelper
|
||||
import com.fsck.k9.mail.AuthType
|
||||
import com.fsck.k9.mail.ConnectionSecurity
|
||||
import com.fsck.k9.oauth.OAuthConfigurationProvider
|
||||
import com.fsck.k9.preferences.Protocols
|
||||
import org.xmlpull.v1.XmlPullParser
|
||||
import timber.log.Timber
|
||||
|
||||
class ProvidersXmlDiscovery(
|
||||
private val xmlProvider: ProvidersXmlProvider
|
||||
private val xmlProvider: ProvidersXmlProvider,
|
||||
private val oAuthConfigurationProvider: OAuthConfigurationProvider
|
||||
) : ConnectionSettingsDiscovery {
|
||||
|
||||
override fun discover(email: String, target: DiscoveryTarget): DiscoveryResults? {
|
||||
|
@ -104,8 +106,7 @@ class ProvidersXmlDiscovery(
|
|||
uri.port
|
||||
}
|
||||
|
||||
// TODO: Remove this hack
|
||||
val authType = if (host == "imap.gmail.com" || host == "imap.googlemail.com") {
|
||||
val authType = if (oAuthConfigurationProvider.getConfiguration(host) != null) {
|
||||
AuthType.XOAUTH2
|
||||
} else {
|
||||
AuthType.PLAIN
|
||||
|
@ -134,8 +135,7 @@ class ProvidersXmlDiscovery(
|
|||
uri.port
|
||||
}
|
||||
|
||||
// TODO: Remove this hack
|
||||
val authType = if (host == "smtp.gmail.com" || host == "smtp.googlemail.com") {
|
||||
val authType = if (oAuthConfigurationProvider.getConfiguration(host) != null) {
|
||||
AuthType.XOAUTH2
|
||||
} else {
|
||||
AuthType.PLAIN
|
||||
|
|
|
@ -5,12 +5,15 @@ import com.fsck.k9.RobolectricTest
|
|||
import com.fsck.k9.autodiscovery.api.DiscoveryTarget
|
||||
import com.fsck.k9.mail.AuthType
|
||||
import com.fsck.k9.mail.ConnectionSecurity
|
||||
import com.fsck.k9.oauth.OAuthConfiguration
|
||||
import com.fsck.k9.oauth.OAuthConfigurationProvider
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Test
|
||||
|
||||
class ProvidersXmlDiscoveryTest : RobolectricTest() {
|
||||
private val xmlProvider = ProvidersXmlProvider(ApplicationProvider.getApplicationContext())
|
||||
private val providersXmlDiscovery = ProvidersXmlDiscovery(xmlProvider)
|
||||
private val oAuthConfigurationProvider = createOAuthConfigurationProvider()
|
||||
private val providersXmlDiscovery = ProvidersXmlDiscovery(xmlProvider, oAuthConfigurationProvider)
|
||||
|
||||
@Test
|
||||
fun discover_withGmailDomain_shouldReturnCorrectSettings() {
|
||||
|
@ -39,4 +42,20 @@ class ProvidersXmlDiscoveryTest : RobolectricTest() {
|
|||
|
||||
assertThat(connectionSettings).isNull()
|
||||
}
|
||||
|
||||
private fun createOAuthConfigurationProvider(): OAuthConfigurationProvider {
|
||||
val googleConfig = OAuthConfiguration(
|
||||
clientId = "irrelevant",
|
||||
scopes = listOf("irrelevant"),
|
||||
authorizationEndpoint = "irrelevant",
|
||||
tokenEndpoint = "irrelevant"
|
||||
)
|
||||
|
||||
return OAuthConfigurationProvider(
|
||||
configurations = mapOf(
|
||||
listOf("imap.gmail.com", "smtp.gmail.com") to googleConfig,
|
||||
),
|
||||
googleConfiguration = googleConfig
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package com.fsck.k9.activity.setup
|
||||
package com.fsck.k9.oauth
|
||||
|
||||
data class OAuthConfiguration(
|
||||
val clientId: String,
|
|
@ -0,0 +1,22 @@
|
|||
package com.fsck.k9.oauth
|
||||
|
||||
class OAuthConfigurationProvider(
|
||||
private val configurations: Map<List<String>, OAuthConfiguration>,
|
||||
private val googleConfiguration: OAuthConfiguration
|
||||
) {
|
||||
private val hostnameMapping: Map<String, OAuthConfiguration> = buildMap {
|
||||
for ((hostnames, configuration) in configurations) {
|
||||
for (hostname in hostnames) {
|
||||
put(hostname.lowercase(), configuration)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getConfiguration(hostname: String): OAuthConfiguration? {
|
||||
return hostnameMapping[hostname.lowercase()]
|
||||
}
|
||||
|
||||
fun isGoogle(hostname: String): Boolean {
|
||||
return getConfiguration(hostname) == googleConfiguration
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
package com.fsck.k9
|
||||
|
||||
import com.fsck.k9.activity.setup.OAuthCredentials
|
||||
import com.fsck.k9.auth.K9OAuthCredentials
|
||||
import com.fsck.k9.auth.createOAuthConfigurationProvider
|
||||
import com.fsck.k9.backends.backendsModule
|
||||
import com.fsck.k9.controller.ControllerExtension
|
||||
import com.fsck.k9.crypto.EncryptionExtractor
|
||||
|
@ -31,7 +30,7 @@ private val mainAppModule = module {
|
|||
single(named("controllerExtensions")) { emptyList<ControllerExtension>() }
|
||||
single<EncryptionExtractor> { OpenPgpEncryptionExtractor.newInstance() }
|
||||
single<StoragePersister> { K9StoragePersister(get()) }
|
||||
factory<OAuthCredentials> { K9OAuthCredentials() }
|
||||
single { createOAuthConfigurationProvider() }
|
||||
}
|
||||
|
||||
val appModules = listOf(
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
package com.fsck.k9.auth
|
||||
|
||||
import com.fsck.k9.BuildConfig
|
||||
import com.fsck.k9.activity.setup.OAuthCredentials
|
||||
|
||||
class K9OAuthCredentials : OAuthCredentials {
|
||||
override val gmailClientId: String
|
||||
get() = BuildConfig.OAUTH_GMAIL_CLIENT_ID
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package com.fsck.k9.auth
|
||||
|
||||
import com.fsck.k9.BuildConfig
|
||||
import com.fsck.k9.oauth.OAuthConfiguration
|
||||
import com.fsck.k9.oauth.OAuthConfigurationProvider
|
||||
|
||||
fun createOAuthConfigurationProvider(): OAuthConfigurationProvider {
|
||||
val googleConfig = OAuthConfiguration(
|
||||
clientId = BuildConfig.OAUTH_GMAIL_CLIENT_ID,
|
||||
scopes = listOf("https://mail.google.com/"),
|
||||
authorizationEndpoint = "https://accounts.google.com/o/oauth2/v2/auth",
|
||||
tokenEndpoint = "https://oauth2.googleapis.com/token"
|
||||
)
|
||||
|
||||
return OAuthConfigurationProvider(
|
||||
configurations = mapOf(
|
||||
listOf("imap.gmail.com", "imap.googlemail.com", "smtp.gmail.com", "smtp.googlemail.com") to googleConfig,
|
||||
),
|
||||
googleConfiguration = googleConfig
|
||||
)
|
||||
}
|
|
@ -6,5 +6,5 @@ import org.koin.dsl.module
|
|||
|
||||
val activityModule = module {
|
||||
single { MessageLoaderHelperFactory(messageViewInfoExtractorFactory = get(), htmlSettingsProvider = get()) }
|
||||
viewModel { AuthViewModel(application = get(), accountManager = get(), oauthCredentials = get()) }
|
||||
viewModel { AuthViewModel(application = get(), accountManager = get(), oAuthConfigurationProvider = get()) }
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ import androidx.lifecycle.Lifecycle
|
|||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.fsck.k9.Account
|
||||
import com.fsck.k9.oauth.OAuthConfiguration
|
||||
import com.fsck.k9.oauth.OAuthConfigurationProvider
|
||||
import com.fsck.k9.preferences.AccountManager
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
@ -38,7 +40,7 @@ private const val KEY_AUTHORIZATION = "app.k9mail_auth"
|
|||
class AuthViewModel(
|
||||
application: Application,
|
||||
private val accountManager: AccountManager,
|
||||
private val oauthCredentials: OAuthCredentials
|
||||
private val oAuthConfigurationProvider: OAuthConfigurationProvider
|
||||
) : AndroidViewModel(application) {
|
||||
private var authService: AuthorizationService? = null
|
||||
private val authState = AuthState()
|
||||
|
@ -70,8 +72,7 @@ class AuthViewModel(
|
|||
}
|
||||
|
||||
fun isUsingGoogle(account: Account): Boolean {
|
||||
val config = findOAuthConfiguration(account)
|
||||
return config?.authorizationEndpoint == "https://accounts.google.com/o/oauth2/v2/auth"
|
||||
return oAuthConfigurationProvider.isGoogle(account.incomingServerSettings.host!!)
|
||||
}
|
||||
|
||||
private fun getOrCreateAuthState(account: Account): AuthState {
|
||||
|
@ -137,17 +138,7 @@ class AuthViewModel(
|
|||
}
|
||||
|
||||
private fun findOAuthConfiguration(account: Account): OAuthConfiguration? {
|
||||
return when (account.incomingServerSettings.host) {
|
||||
"imap.gmail.com", "imap.googlemail.com" -> {
|
||||
OAuthConfiguration(
|
||||
clientId = oauthCredentials.gmailClientId,
|
||||
scopes = listOf("https://mail.google.com/"),
|
||||
authorizationEndpoint = "https://accounts.google.com/o/oauth2/v2/auth",
|
||||
tokenEndpoint = "https://oauth2.googleapis.com/token"
|
||||
)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
return oAuthConfigurationProvider.getConfiguration(account.incomingServerSettings.host!!)
|
||||
}
|
||||
|
||||
private fun onLoginResult(authorizationResult: AuthorizationResult?) {
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
package com.fsck.k9.activity.setup
|
||||
|
||||
interface OAuthCredentials {
|
||||
val gmailClientId: String
|
||||
}
|
Loading…
Reference in a new issue