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

Unverified Commit 8223abb2 authored by cketti's avatar cketti Committed by GitHub
Browse files

Merge pull request #8187 from thunderbird/qr_code_scanner_3

Change QR code validation/mapping
parents 7bfeb3e6 83bc0736
Loading
Loading
Loading
Loading
+15 −50
Original line number Diff line number Diff line
@@ -45,61 +45,26 @@ internal data class AccountData(
        val displayName: String,
    )

    @Suppress("MagicNumber")
    enum class IncomingServerProtocol(val intValue: Int) {
        Imap(0),
        Pop3(1),
        ;

        companion object {
            fun fromInt(value: Int): IncomingServerProtocol {
                return requireNotNull(entries.find { it.intValue == value }) { "Unsupported value: $value" }
            }
        }
    enum class IncomingServerProtocol {
        Imap,
        Pop3,
    }

    @Suppress("MagicNumber")
    enum class OutgoingServerProtocol(val intValue: Int) {
        Smtp(0),
        ;

        companion object {
            fun fromInt(value: Int): OutgoingServerProtocol {
                return requireNotNull(entries.find { it.intValue == value }) { "Unsupported value: $value" }
            }
        }
    enum class OutgoingServerProtocol {
        Smtp,
    }

    @Suppress("MagicNumber")
    enum class ConnectionSecurity(val intValue: Int) {
        Plain(0),
        TryStartTls(1),
        AlwaysStartTls(2),
        Tls(3),
        ;

        companion object {
            fun fromInt(value: Int): ConnectionSecurity {
                return requireNotNull(entries.find { it.intValue == value }) { "Unsupported value: $value" }
            }
        }
    enum class ConnectionSecurity {
        Plain,
        AlwaysStartTls,
        Tls,
    }

    @Suppress("MagicNumber")
    enum class AuthenticationType(val intValue: Int) {
        None(0),
        PasswordCleartext(1),
        PasswordEncrypted(2),
        Gssapi(3),
        Ntlm(4),
        TlsCertificate(5),
        OAuth2(6),
        ;

        companion object {
            fun fromInt(value: Int): AuthenticationType {
                return requireNotNull(entries.find { it.intValue == value }) { "Unsupported value: $value" }
            }
        }
    enum class AuthenticationType {
        None,
        PasswordCleartext,
        PasswordEncrypted,
        TlsCertificate,
        OAuth2,
    }
}
+47 −0
Original line number Diff line number Diff line
@file:Suppress("MagicNumber")

package app.k9mail.feature.migration.qrcode.payload

import app.k9mail.feature.migration.qrcode.domain.entity.AccountData.AuthenticationType
import app.k9mail.feature.migration.qrcode.domain.entity.AccountData.ConnectionSecurity
import app.k9mail.feature.migration.qrcode.domain.entity.AccountData.IncomingServerProtocol
import app.k9mail.feature.migration.qrcode.domain.entity.AccountData.OutgoingServerProtocol

internal fun Int.toIncomingServerProtocol(): IncomingServerProtocol {
    return when (this) {
        0 -> IncomingServerProtocol.Imap
        1 -> IncomingServerProtocol.Pop3
        else -> throw IllegalArgumentException("Unsupported value: $this")
    }
}

internal fun Int.toOutgoingServerProtocol(): OutgoingServerProtocol {
    return when (this) {
        0 -> OutgoingServerProtocol.Smtp
        else -> throw IllegalArgumentException("Unsupported value: $this")
    }
}

internal fun Int.toConnectionSecurity(): ConnectionSecurity {
    return when (this) {
        0 -> ConnectionSecurity.Plain
        1 -> ConnectionSecurity.AlwaysStartTls // TryStartTls, but we treat it like AlwaysStartTls
        2 -> ConnectionSecurity.AlwaysStartTls
        3 -> ConnectionSecurity.Tls
        else -> throw IllegalArgumentException("Unsupported value: $this")
    }
}

@Suppress("ThrowsCount")
internal fun Int.toAuthenticationType(): AuthenticationType {
    return when (this) {
        0 -> AuthenticationType.None
        1 -> AuthenticationType.PasswordCleartext
        2 -> AuthenticationType.PasswordEncrypted
        3 -> throw IllegalArgumentException("Unsupported authentication method: Gssapi")
        4 -> throw IllegalArgumentException("Unsupported authentication method: Ntlm")
        5 -> AuthenticationType.TlsCertificate
        6 -> AuthenticationType.OAuth2
        else -> throw IllegalArgumentException("Unsupported value: $this")
    }
}
+6 −6
Original line number Diff line number Diff line
@@ -49,11 +49,11 @@ internal class QrCodePayloadMapper(

    private fun mapIncomingServer(incomingServer: QrCodeData.IncomingServer): AccountData.IncomingServer {
        return AccountData.IncomingServer(
            protocol = AccountData.IncomingServerProtocol.fromInt(incomingServer.protocol),
            protocol = incomingServer.protocol.toIncomingServerProtocol(),
            hostname = incomingServer.hostname.toHostname(),
            port = incomingServer.port.toPort(),
            connectionSecurity = AccountData.ConnectionSecurity.fromInt(incomingServer.connectionSecurity),
            authenticationType = AccountData.AuthenticationType.fromInt(incomingServer.authenticationType),
            connectionSecurity = incomingServer.connectionSecurity.toConnectionSecurity(),
            authenticationType = incomingServer.authenticationType.toAuthenticationType(),
            username = incomingServer.username,
            password = incomingServer.password,
        )
@@ -72,11 +72,11 @@ internal class QrCodePayloadMapper(

    private fun mapOutgoingServer(outgoingServer: QrCodeData.OutgoingServer): AccountData.OutgoingServer {
        return AccountData.OutgoingServer(
            protocol = AccountData.OutgoingServerProtocol.fromInt(outgoingServer.protocol),
            protocol = outgoingServer.protocol.toOutgoingServerProtocol(),
            hostname = outgoingServer.hostname.toHostname(),
            port = outgoingServer.port.toPort(),
            connectionSecurity = AccountData.ConnectionSecurity.fromInt(outgoingServer.connectionSecurity),
            authenticationType = AccountData.AuthenticationType.fromInt(outgoingServer.authenticationType),
            connectionSecurity = outgoingServer.connectionSecurity.toConnectionSecurity(),
            authenticationType = outgoingServer.authenticationType.toAuthenticationType(),
            username = outgoingServer.username,
            password = outgoingServer.password,
        )
+4 −5
Original line number Diff line number Diff line
@@ -4,7 +4,6 @@ import app.k9mail.core.common.mail.EmailAddressParserException
import app.k9mail.core.common.mail.toUserEmailAddress
import app.k9mail.core.common.net.toHostname
import app.k9mail.core.common.net.toPort
import app.k9mail.feature.migration.qrcode.domain.entity.AccountData
import timber.log.Timber

@Suppress("TooManyFunctions")
@@ -86,11 +85,11 @@ internal class QrCodePayloadValidator {
    }

    private fun validateIncomingServerProtocol(protocol: Int) {
        AccountData.IncomingServerProtocol.fromInt(protocol)
        protocol.toIncomingServerProtocol()
    }

    private fun validateOutgoingServerProtocol(protocol: Int) {
        AccountData.OutgoingServerProtocol.fromInt(protocol)
        protocol.toOutgoingServerProtocol()
    }

    private fun validateHostname(hostname: String) {
@@ -102,11 +101,11 @@ internal class QrCodePayloadValidator {
    }

    private fun validateConnectionSecurity(value: Int) {
        AccountData.ConnectionSecurity.fromInt(value)
        value.toConnectionSecurity()
    }

    private fun validateAuthenticationType(value: Int) {
        AccountData.AuthenticationType.fromInt(value)
        value.toAuthenticationType()
    }

    private fun validateUsername(username: String) {
+18 −2
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@ import app.k9mail.core.common.mail.toUserEmailAddress
import app.k9mail.core.common.net.toHostname
import app.k9mail.core.common.net.toPort
import app.k9mail.feature.migration.qrcode.domain.entity.AccountData
import app.k9mail.feature.migration.qrcode.domain.entity.AccountData.ConnectionSecurity
import assertk.assertThat
import assertk.assertions.first
import assertk.assertions.isEqualTo
@@ -49,6 +50,21 @@ class QrCodePayloadMapperTest {
            .prop(AccountData.Account::accountName).isEqualTo("user@domain.example")
    }

    @Test
    fun `TryStartTls should be mapped to AlwaysStartTls`() {
        val input = INPUT.updateIncomingServer { server ->
            server.copy(connectionSecurity = 1)
        }

        val result = mapper.toAccountData(input)

        assertThat(result).isNotNull()
            .prop(AccountData::accounts).first()
            .prop(AccountData.Account::incomingServer)
            .prop(AccountData.IncomingServer::connectionSecurity)
            .isEqualTo(ConnectionSecurity.AlwaysStartTls)
    }

    companion object {
        private val INPUT = QrCodeData(
            version = 1,
@@ -99,7 +115,7 @@ class QrCodePayloadMapperTest {
                        protocol = AccountData.IncomingServerProtocol.Imap,
                        hostname = "imap.domain.example".toHostname(),
                        port = 993.toPort(),
                        connectionSecurity = AccountData.ConnectionSecurity.Tls,
                        connectionSecurity = ConnectionSecurity.Tls,
                        authenticationType = AccountData.AuthenticationType.PasswordCleartext,
                        username = "user@domain.example",
                        password = "password",
@@ -110,7 +126,7 @@ class QrCodePayloadMapperTest {
                                protocol = AccountData.OutgoingServerProtocol.Smtp,
                                hostname = "smtp.domain.example".toHostname(),
                                port = 465.toPort(),
                                connectionSecurity = AccountData.ConnectionSecurity.Tls,
                                connectionSecurity = ConnectionSecurity.Tls,
                                authenticationType = AccountData.AuthenticationType.PasswordCleartext,
                                username = "user@domain.example",
                                password = "password",
Loading