Loading feature/migration/qrcode/src/main/kotlin/app/k9mail/feature/migration/qrcode/domain/entity/AccountData.kt +15 −50 Original line number Diff line number Diff line Loading @@ -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, } } feature/migration/qrcode/src/main/kotlin/app/k9mail/feature/migration/qrcode/payload/IntValueMapper.kt 0 → 100644 +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") } } feature/migration/qrcode/src/main/kotlin/app/k9mail/feature/migration/qrcode/payload/QrCodePayloadMapper.kt +6 −6 Original line number Diff line number Diff line Loading @@ -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, ) Loading @@ -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, ) Loading feature/migration/qrcode/src/main/kotlin/app/k9mail/feature/migration/qrcode/payload/QrCodePayloadValidator.kt +4 −5 Original line number Diff line number Diff line Loading @@ -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") Loading Loading @@ -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) { Loading @@ -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) { Loading feature/migration/qrcode/src/test/kotlin/app/k9mail/feature/migration/qrcode/payload/QrCodePayloadMapperTest.kt +18 −2 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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, Loading Loading @@ -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", Loading @@ -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 Loading
feature/migration/qrcode/src/main/kotlin/app/k9mail/feature/migration/qrcode/domain/entity/AccountData.kt +15 −50 Original line number Diff line number Diff line Loading @@ -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, } }
feature/migration/qrcode/src/main/kotlin/app/k9mail/feature/migration/qrcode/payload/IntValueMapper.kt 0 → 100644 +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") } }
feature/migration/qrcode/src/main/kotlin/app/k9mail/feature/migration/qrcode/payload/QrCodePayloadMapper.kt +6 −6 Original line number Diff line number Diff line Loading @@ -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, ) Loading @@ -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, ) Loading
feature/migration/qrcode/src/main/kotlin/app/k9mail/feature/migration/qrcode/payload/QrCodePayloadValidator.kt +4 −5 Original line number Diff line number Diff line Loading @@ -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") Loading Loading @@ -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) { Loading @@ -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) { Loading
feature/migration/qrcode/src/test/kotlin/app/k9mail/feature/migration/qrcode/payload/QrCodePayloadMapperTest.kt +18 −2 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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, Loading Loading @@ -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", Loading @@ -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