diff --git a/app/src/main/java/com/x8bit/bitwarden/data/tools/generator/repository/model/UsernameGenerationOptions.kt b/app/src/main/java/com/x8bit/bitwarden/data/tools/generator/repository/model/UsernameGenerationOptions.kt index 8fc1efb980..6f00601421 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/tools/generator/repository/model/UsernameGenerationOptions.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/tools/generator/repository/model/UsernameGenerationOptions.kt @@ -113,6 +113,9 @@ data class UsernameGenerationOptions( @SerialName("4") FASTMAIL, + + @SerialName("5") + FORWARD_EMAIL, } } diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/generator/GeneratorViewModel.kt b/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/generator/GeneratorViewModel.kt index 64faa41a85..cd01eaa82a 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/generator/GeneratorViewModel.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/generator/GeneratorViewModel.kt @@ -46,6 +46,7 @@ import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Us import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Username.UsernameType.PlusAddressedEmail import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Username.UsernameType.RandomWord import com.x8bit.bitwarden.ui.tools.feature.generator.model.GeneratorMode +import com.x8bit.bitwarden.ui.tools.feature.generator.util.toServiceType import com.x8bit.bitwarden.ui.tools.feature.generator.util.toStrictestPolicy import com.x8bit.bitwarden.ui.tools.feature.generator.util.toUsernameGeneratorRequest import dagger.hilt.android.lifecycle.HiltViewModel @@ -472,6 +473,13 @@ class GeneratorViewModel @Inject constructor( simpleLoginApiKey = forwardedEmailAlias.selectedServiceType.apiKey, ) + is ForwardEmail -> options.copy( + type = UsernameGenerationOptions.UsernameType.FORWARDED_EMAIL_ALIAS, + serviceType = UsernameGenerationOptions.ForwardedEmailServiceType.FORWARD_EMAIL, + forwardEmailApiAccessToken = forwardedEmailAlias.selectedServiceType.apiKey, + forwardEmailDomainName = forwardedEmailAlias.selectedServiceType.domainName, + ) + else -> options.copy( type = UsernameGenerationOptions.UsernameType.FORWARDED_EMAIL_ALIAS, serviceType = UsernameGenerationOptions.ForwardedEmailServiceType.NONE, @@ -2595,37 +2603,6 @@ private val UsernameGenerationOptions?.usernameType: Username.UsernameType else -> PlusAddressedEmail() } -private fun UsernameGenerationOptions.ForwardedEmailServiceType?.toServiceType( - options: UsernameGenerationOptions, -): ForwardedEmailAlias.ServiceType? { - return when (this) { - UsernameGenerationOptions.ForwardedEmailServiceType.FIREFOX_RELAY -> { - FirefoxRelay(apiAccessToken = options.firefoxRelayApiAccessToken.orEmpty()) - } - - UsernameGenerationOptions.ForwardedEmailServiceType.SIMPLE_LOGIN -> { - SimpleLogin(apiKey = options.simpleLoginApiKey.orEmpty()) - } - - UsernameGenerationOptions.ForwardedEmailServiceType.DUCK_DUCK_GO -> { - DuckDuckGo(apiKey = options.duckDuckGoApiKey.orEmpty()) - } - - UsernameGenerationOptions.ForwardedEmailServiceType.FASTMAIL -> { - FastMail(apiKey = options.fastMailApiKey.orEmpty()) - } - - UsernameGenerationOptions.ForwardedEmailServiceType.ANON_ADDY -> { - AddyIo( - apiAccessToken = options.anonAddyApiAccessToken.orEmpty(), - domainName = options.anonAddyDomainName.orEmpty(), - ) - } - - else -> null - } -} - private fun String?.toSelectedType(): Passcode.PasscodeType = when (this) { PolicyInformation.PasswordGenerator.TYPE_PASSPHRASE -> Passphrase() diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/generator/util/ForwardedEmailServiceTypeExtensions.kt b/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/generator/util/ForwardedEmailServiceTypeExtensions.kt new file mode 100644 index 0000000000..739b60ed36 --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/generator/util/ForwardedEmailServiceTypeExtensions.kt @@ -0,0 +1,53 @@ +package com.x8bit.bitwarden.ui.tools.feature.generator.util + +import com.x8bit.bitwarden.data.tools.generator.repository.model.UsernameGenerationOptions +import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias +import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias.ServiceType.AddyIo +import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias.ServiceType.DuckDuckGo +import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias.ServiceType.FastMail +import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias.ServiceType.FirefoxRelay +import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias.ServiceType.ForwardEmail +import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias.ServiceType.SimpleLogin + +/** + * Converts this [UsernameGenerationOptions.ForwardedEmailServiceType] into a corresponding + * [ForwardedEmailAlias.ServiceType] with the given [options], or `null`. + */ +fun UsernameGenerationOptions.ForwardedEmailServiceType?.toServiceType( + options: UsernameGenerationOptions, +): ForwardedEmailAlias.ServiceType? { + this ?: return null + return when (this) { + UsernameGenerationOptions.ForwardedEmailServiceType.FIREFOX_RELAY -> { + FirefoxRelay(apiAccessToken = options.firefoxRelayApiAccessToken.orEmpty()) + } + + UsernameGenerationOptions.ForwardedEmailServiceType.SIMPLE_LOGIN -> { + SimpleLogin(apiKey = options.simpleLoginApiKey.orEmpty()) + } + + UsernameGenerationOptions.ForwardedEmailServiceType.DUCK_DUCK_GO -> { + DuckDuckGo(apiKey = options.duckDuckGoApiKey.orEmpty()) + } + + UsernameGenerationOptions.ForwardedEmailServiceType.FASTMAIL -> { + FastMail(apiKey = options.fastMailApiKey.orEmpty()) + } + + UsernameGenerationOptions.ForwardedEmailServiceType.ANON_ADDY -> { + AddyIo( + apiAccessToken = options.anonAddyApiAccessToken.orEmpty(), + domainName = options.anonAddyDomainName.orEmpty(), + ) + } + + UsernameGenerationOptions.ForwardedEmailServiceType.FORWARD_EMAIL -> { + ForwardEmail( + apiKey = options.forwardEmailApiAccessToken.orEmpty(), + domainName = options.forwardEmailDomainName.orEmpty(), + ) + } + + UsernameGenerationOptions.ForwardedEmailServiceType.NONE -> null + } +} diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/generator/GeneratorViewModelTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/generator/GeneratorViewModelTest.kt index 3bce98de58..98aeb4f5dd 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/generator/GeneratorViewModelTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/generator/GeneratorViewModelTest.kt @@ -26,6 +26,8 @@ import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson import com.x8bit.bitwarden.data.vault.datasource.network.model.createMockPolicy import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest import com.x8bit.bitwarden.ui.platform.base.util.asText +import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias.ServiceType +import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias.ServiceTypeOption import com.x8bit.bitwarden.ui.tools.feature.generator.model.GeneratorMode import io.mockk.every import io.mockk.just @@ -1564,49 +1566,70 @@ class GeneratorViewModelTest : BaseViewModelTest() { @Test fun `ServiceTypeOptionSelect should update service type correctly`() = runTest { - val action = GeneratorAction - .MainType - .Username - .UsernameType - .ForwardedEmailAlias - .ServiceTypeOptionSelect( - serviceTypeOption = GeneratorState - .MainType - .Username - .UsernameType - .ForwardedEmailAlias - .ServiceTypeOption - .ADDY_IO, - ) - fakeGeneratorRepository.setMockGenerateForwardedServiceResult( GeneratedForwardedServiceUsernameResult.Success( generatedEmailAddress = "defaultForwardedEmailAlias", ), ) - viewModel.trySendAction(action) - - val expectedState = defaultForwardedEmailAliasState.copy( - generatedText = "-", - selectedType = GeneratorState.MainType.Username( - selectedType = GeneratorState + ServiceTypeOption + .entries + .forEach { + val action = GeneratorAction .MainType .Username .UsernameType - .ForwardedEmailAlias( - selectedServiceType = GeneratorState + .ForwardedEmailAlias + .ServiceTypeOptionSelect(serviceTypeOption = it) + + viewModel.trySendAction(action) + + val serviceType = createMockForwardedEmailAliasGeneratorState(it) + + val expectedState = defaultForwardedEmailAliasState.copy( + generatedText = "-", + selectedType = GeneratorState.MainType.Username( + selectedType = GeneratorState .MainType .Username .UsernameType - .ForwardedEmailAlias - .ServiceType - .AddyIo(), + .ForwardedEmailAlias( + selectedServiceType = serviceType, + ), ), - ), - ) + ) - assertEquals(expectedState, viewModel.stateFlow.value) + assertEquals(expectedState, viewModel.stateFlow.value) + } + } + + @Suppress("MaxLineLength") + private fun createMockForwardedEmailAliasGeneratorState( + serviceTypeOption: ServiceTypeOption, + ): ServiceType = when (serviceTypeOption) { + ServiceTypeOption.ADDY_IO -> { + ServiceType.AddyIo() + } + + ServiceTypeOption.DUCK_DUCK_GO -> { + ServiceType.DuckDuckGo() + } + + ServiceTypeOption.FAST_MAIL -> { + ServiceType.FastMail() + } + + ServiceTypeOption.FIREFOX_RELAY -> { + ServiceType.FirefoxRelay() + } + + ServiceTypeOption.FORWARD_EMAIL -> { + ServiceType.ForwardEmail() + } + + ServiceTypeOption.SIMPLE_LOGIN -> { + ServiceType.SimpleLogin() + } } } @@ -1645,12 +1668,7 @@ class GeneratorViewModelTest : BaseViewModelTest() { generatedText = "-", selectedType = GeneratorState.MainType.Username( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( - selectedServiceType = GeneratorState - .MainType - .Username - .UsernameType - .ForwardedEmailAlias - .ServiceType + selectedServiceType = ServiceType .AddyIo( apiAccessToken = newAccessToken, ), @@ -1685,12 +1703,7 @@ class GeneratorViewModelTest : BaseViewModelTest() { generatedText = "-", selectedType = GeneratorState.MainType.Username( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( - selectedServiceType = GeneratorState - .MainType - .Username - .UsernameType - .ForwardedEmailAlias - .ServiceType + selectedServiceType = ServiceType .AddyIo( domainName = newDomainName, ), @@ -1736,12 +1749,7 @@ class GeneratorViewModelTest : BaseViewModelTest() { generatedText = "-", selectedType = GeneratorState.MainType.Username( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( - selectedServiceType = GeneratorState - .MainType - .Username - .UsernameType - .ForwardedEmailAlias - .ServiceType + selectedServiceType = ServiceType .DuckDuckGo( apiKey = newApiKey, ), @@ -1787,12 +1795,7 @@ class GeneratorViewModelTest : BaseViewModelTest() { generatedText = "-", selectedType = GeneratorState.MainType.Username( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( - selectedServiceType = GeneratorState - .MainType - .Username - .UsernameType - .ForwardedEmailAlias - .ServiceType + selectedServiceType = ServiceType .FastMail( apiKey = newApiKey, ), @@ -1839,12 +1842,7 @@ class GeneratorViewModelTest : BaseViewModelTest() { generatedText = "-", selectedType = GeneratorState.MainType.Username( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( - selectedServiceType = GeneratorState - .MainType - .Username - .UsernameType - .ForwardedEmailAlias - .ServiceType + selectedServiceType = ServiceType .FirefoxRelay( apiAccessToken = newAccessToken, ), @@ -1891,12 +1889,7 @@ class GeneratorViewModelTest : BaseViewModelTest() { generatedText = "-", selectedType = GeneratorState.MainType.Username( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( - selectedServiceType = GeneratorState - .MainType - .Username - .UsernameType - .ForwardedEmailAlias - .ServiceType + selectedServiceType = ServiceType .ForwardEmail( apiKey = newApiKey, ), @@ -1932,12 +1925,7 @@ class GeneratorViewModelTest : BaseViewModelTest() { generatedText = "-", selectedType = GeneratorState.MainType.Username( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( - selectedServiceType = GeneratorState - .MainType - .Username - .UsernameType - .ForwardedEmailAlias - .ServiceType + selectedServiceType = ServiceType .ForwardEmail( domainName = newDomainName, ), @@ -1984,12 +1972,7 @@ class GeneratorViewModelTest : BaseViewModelTest() { generatedText = "-", selectedType = GeneratorState.MainType.Username( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( - selectedServiceType = GeneratorState - .MainType - .Username - .UsernameType - .ForwardedEmailAlias - .ServiceType + selectedServiceType = ServiceType .SimpleLogin( apiKey = newApiKey, ), @@ -2235,12 +2218,7 @@ class GeneratorViewModelTest : BaseViewModelTest() { generatedText = generatedText, selectedType = GeneratorState.MainType.Username( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( - selectedServiceType = GeneratorState - .MainType - .Username - .UsernameType - .ForwardedEmailAlias - .ServiceType + selectedServiceType = ServiceType .AddyIo(), ), ), @@ -2254,12 +2232,7 @@ class GeneratorViewModelTest : BaseViewModelTest() { generatedText = generatedText, selectedType = GeneratorState.MainType.Username( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( - selectedServiceType = GeneratorState - .MainType - .Username - .UsernameType - .ForwardedEmailAlias - .ServiceType + selectedServiceType = ServiceType .DuckDuckGo(), ), ), @@ -2273,12 +2246,7 @@ class GeneratorViewModelTest : BaseViewModelTest() { generatedText = generatedText, selectedType = GeneratorState.MainType.Username( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( - selectedServiceType = GeneratorState - .MainType - .Username - .UsernameType - .ForwardedEmailAlias - .ServiceType + selectedServiceType = ServiceType .FastMail(), ), ), @@ -2292,12 +2260,7 @@ class GeneratorViewModelTest : BaseViewModelTest() { generatedText = generatedText, selectedType = GeneratorState.MainType.Username( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( - selectedServiceType = GeneratorState - .MainType - .Username - .UsernameType - .ForwardedEmailAlias - .ServiceType + selectedServiceType = ServiceType .FirefoxRelay(), ), ), @@ -2311,12 +2274,7 @@ class GeneratorViewModelTest : BaseViewModelTest() { generatedText = generatedText, selectedType = GeneratorState.MainType.Username( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( - selectedServiceType = GeneratorState - .MainType - .Username - .UsernameType - .ForwardedEmailAlias - .ServiceType + selectedServiceType = ServiceType .ForwardEmail(), ), ), @@ -2330,12 +2288,7 @@ class GeneratorViewModelTest : BaseViewModelTest() { generatedText = generatedText, selectedType = GeneratorState.MainType.Username( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( - selectedServiceType = GeneratorState - .MainType - .Username - .UsernameType - .ForwardedEmailAlias - .ServiceType + selectedServiceType = ServiceType .SimpleLogin(), ), ), diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/generator/util/ForwardedEmailServiceTypeExtensionsTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/generator/util/ForwardedEmailServiceTypeExtensionsTest.kt new file mode 100644 index 0000000000..7c35a1e5ab --- /dev/null +++ b/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/generator/util/ForwardedEmailServiceTypeExtensionsTest.kt @@ -0,0 +1,75 @@ +package com.x8bit.bitwarden.ui.tools.feature.generator.util + +import com.x8bit.bitwarden.data.tools.generator.repository.model.UsernameGenerationOptions +import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias.ServiceType +import org.junit.Test +import org.junit.jupiter.api.Assertions.assertEquals + +class ForwardedEmailServiceTypeExtensionsTest { + + @Test + fun `toServiceType should map to correct service type`() { + val options = UsernameGenerationOptions( + type = UsernameGenerationOptions.UsernameType.RANDOM_WORD, + serviceType = UsernameGenerationOptions.ForwardedEmailServiceType.NONE, + capitalizeRandomWordUsername = true, + includeNumberRandomWordUsername = false, + plusAddressedEmail = "example+plus@gmail.com", + catchAllEmailDomain = "example.com", + firefoxRelayApiAccessToken = "access_token_firefox_relay", + simpleLoginApiKey = "api_key_simple_login", + duckDuckGoApiKey = "api_key_duck_duck_go", + fastMailApiKey = "api_key_fast_mail", + anonAddyApiAccessToken = "access_token_anon_addy", + anonAddyDomainName = "anonaddy.com", + forwardEmailApiAccessToken = "access_token_forward_email", + forwardEmailDomainName = "forwardemail.net", + emailWebsite = "email.example.com", + ) + UsernameGenerationOptions.ForwardedEmailServiceType.entries + .forEach { + val expected = createMockForwardedEmailAliasServiceType(it) + assertEquals( + expected, + it.toServiceType(options), + ) + } + } + + @Suppress("MaxLineLength") + private fun createMockForwardedEmailAliasServiceType( + serviceTypeOption: UsernameGenerationOptions.ForwardedEmailServiceType, + ): ServiceType? = when (serviceTypeOption) { + UsernameGenerationOptions.ForwardedEmailServiceType.NONE -> null + + UsernameGenerationOptions.ForwardedEmailServiceType.ANON_ADDY -> { + ServiceType.AddyIo( + apiAccessToken = "access_token_anon_addy", + domainName = "anonaddy.com", + ) + } + + UsernameGenerationOptions.ForwardedEmailServiceType.FIREFOX_RELAY -> { + ServiceType.FirefoxRelay(apiAccessToken = "access_token_firefox_relay") + } + + UsernameGenerationOptions.ForwardedEmailServiceType.SIMPLE_LOGIN -> { + ServiceType.SimpleLogin(apiKey = "api_key_simple_login") + } + + UsernameGenerationOptions.ForwardedEmailServiceType.DUCK_DUCK_GO -> { + ServiceType.DuckDuckGo(apiKey = "api_key_duck_duck_go") + } + + UsernameGenerationOptions.ForwardedEmailServiceType.FASTMAIL -> { + ServiceType.FastMail(apiKey = "api_key_fast_mail") + } + + UsernameGenerationOptions.ForwardedEmailServiceType.FORWARD_EMAIL -> { + ServiceType.ForwardEmail( + apiKey = "access_token_forward_email", + domainName = "forwardemail.net", + ) + } + } +}