[PM-10883] Support deserializing Forward Email service type details (#3739)

This commit is contained in:
Patrick Honkonen 2024-08-19 09:02:57 -04:00 committed by GitHub
parent b18d9f53c6
commit 8c8db78da6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 205 additions and 144 deletions

View file

@ -113,6 +113,9 @@ data class UsernameGenerationOptions(
@SerialName("4") @SerialName("4")
FASTMAIL, FASTMAIL,
@SerialName("5")
FORWARD_EMAIL,
} }
} }

View file

@ -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.PlusAddressedEmail
import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Username.UsernameType.RandomWord 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.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.toStrictestPolicy
import com.x8bit.bitwarden.ui.tools.feature.generator.util.toUsernameGeneratorRequest import com.x8bit.bitwarden.ui.tools.feature.generator.util.toUsernameGeneratorRequest
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
@ -472,6 +473,13 @@ class GeneratorViewModel @Inject constructor(
simpleLoginApiKey = forwardedEmailAlias.selectedServiceType.apiKey, 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( else -> options.copy(
type = UsernameGenerationOptions.UsernameType.FORWARDED_EMAIL_ALIAS, type = UsernameGenerationOptions.UsernameType.FORWARDED_EMAIL_ALIAS,
serviceType = UsernameGenerationOptions.ForwardedEmailServiceType.NONE, serviceType = UsernameGenerationOptions.ForwardedEmailServiceType.NONE,
@ -2595,37 +2603,6 @@ private val UsernameGenerationOptions?.usernameType: Username.UsernameType
else -> PlusAddressedEmail() 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 = private fun String?.toSelectedType(): Passcode.PasscodeType =
when (this) { when (this) {
PolicyInformation.PasswordGenerator.TYPE_PASSPHRASE -> Passphrase() PolicyInformation.PasswordGenerator.TYPE_PASSPHRASE -> Passphrase()

View file

@ -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
}
}

View file

@ -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.data.vault.datasource.network.model.createMockPolicy
import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest
import com.x8bit.bitwarden.ui.platform.base.util.asText 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 com.x8bit.bitwarden.ui.tools.feature.generator.model.GeneratorMode
import io.mockk.every import io.mockk.every
import io.mockk.just import io.mockk.just
@ -1564,49 +1566,70 @@ class GeneratorViewModelTest : BaseViewModelTest() {
@Test @Test
fun `ServiceTypeOptionSelect should update service type correctly`() = runTest { 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( fakeGeneratorRepository.setMockGenerateForwardedServiceResult(
GeneratedForwardedServiceUsernameResult.Success( GeneratedForwardedServiceUsernameResult.Success(
generatedEmailAddress = "defaultForwardedEmailAlias", generatedEmailAddress = "defaultForwardedEmailAlias",
), ),
) )
viewModel.trySendAction(action) ServiceTypeOption
.entries
val expectedState = defaultForwardedEmailAliasState.copy( .forEach {
generatedText = "-", val action = GeneratorAction
selectedType = GeneratorState.MainType.Username(
selectedType = GeneratorState
.MainType .MainType
.Username .Username
.UsernameType .UsernameType
.ForwardedEmailAlias( .ForwardedEmailAlias
selectedServiceType = GeneratorState .ServiceTypeOptionSelect(serviceTypeOption = it)
viewModel.trySendAction(action)
val serviceType = createMockForwardedEmailAliasGeneratorState(it)
val expectedState = defaultForwardedEmailAliasState.copy(
generatedText = "-",
selectedType = GeneratorState.MainType.Username(
selectedType = GeneratorState
.MainType .MainType
.Username .Username
.UsernameType .UsernameType
.ForwardedEmailAlias .ForwardedEmailAlias(
.ServiceType selectedServiceType = serviceType,
.AddyIo(), ),
), ),
), )
)
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 = "-", generatedText = "-",
selectedType = GeneratorState.MainType.Username( selectedType = GeneratorState.MainType.Username(
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
selectedServiceType = GeneratorState selectedServiceType = ServiceType
.MainType
.Username
.UsernameType
.ForwardedEmailAlias
.ServiceType
.AddyIo( .AddyIo(
apiAccessToken = newAccessToken, apiAccessToken = newAccessToken,
), ),
@ -1685,12 +1703,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
generatedText = "-", generatedText = "-",
selectedType = GeneratorState.MainType.Username( selectedType = GeneratorState.MainType.Username(
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
selectedServiceType = GeneratorState selectedServiceType = ServiceType
.MainType
.Username
.UsernameType
.ForwardedEmailAlias
.ServiceType
.AddyIo( .AddyIo(
domainName = newDomainName, domainName = newDomainName,
), ),
@ -1736,12 +1749,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
generatedText = "-", generatedText = "-",
selectedType = GeneratorState.MainType.Username( selectedType = GeneratorState.MainType.Username(
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
selectedServiceType = GeneratorState selectedServiceType = ServiceType
.MainType
.Username
.UsernameType
.ForwardedEmailAlias
.ServiceType
.DuckDuckGo( .DuckDuckGo(
apiKey = newApiKey, apiKey = newApiKey,
), ),
@ -1787,12 +1795,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
generatedText = "-", generatedText = "-",
selectedType = GeneratorState.MainType.Username( selectedType = GeneratorState.MainType.Username(
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
selectedServiceType = GeneratorState selectedServiceType = ServiceType
.MainType
.Username
.UsernameType
.ForwardedEmailAlias
.ServiceType
.FastMail( .FastMail(
apiKey = newApiKey, apiKey = newApiKey,
), ),
@ -1839,12 +1842,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
generatedText = "-", generatedText = "-",
selectedType = GeneratorState.MainType.Username( selectedType = GeneratorState.MainType.Username(
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
selectedServiceType = GeneratorState selectedServiceType = ServiceType
.MainType
.Username
.UsernameType
.ForwardedEmailAlias
.ServiceType
.FirefoxRelay( .FirefoxRelay(
apiAccessToken = newAccessToken, apiAccessToken = newAccessToken,
), ),
@ -1891,12 +1889,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
generatedText = "-", generatedText = "-",
selectedType = GeneratorState.MainType.Username( selectedType = GeneratorState.MainType.Username(
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
selectedServiceType = GeneratorState selectedServiceType = ServiceType
.MainType
.Username
.UsernameType
.ForwardedEmailAlias
.ServiceType
.ForwardEmail( .ForwardEmail(
apiKey = newApiKey, apiKey = newApiKey,
), ),
@ -1932,12 +1925,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
generatedText = "-", generatedText = "-",
selectedType = GeneratorState.MainType.Username( selectedType = GeneratorState.MainType.Username(
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
selectedServiceType = GeneratorState selectedServiceType = ServiceType
.MainType
.Username
.UsernameType
.ForwardedEmailAlias
.ServiceType
.ForwardEmail( .ForwardEmail(
domainName = newDomainName, domainName = newDomainName,
), ),
@ -1984,12 +1972,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
generatedText = "-", generatedText = "-",
selectedType = GeneratorState.MainType.Username( selectedType = GeneratorState.MainType.Username(
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
selectedServiceType = GeneratorState selectedServiceType = ServiceType
.MainType
.Username
.UsernameType
.ForwardedEmailAlias
.ServiceType
.SimpleLogin( .SimpleLogin(
apiKey = newApiKey, apiKey = newApiKey,
), ),
@ -2235,12 +2218,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
generatedText = generatedText, generatedText = generatedText,
selectedType = GeneratorState.MainType.Username( selectedType = GeneratorState.MainType.Username(
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
selectedServiceType = GeneratorState selectedServiceType = ServiceType
.MainType
.Username
.UsernameType
.ForwardedEmailAlias
.ServiceType
.AddyIo(), .AddyIo(),
), ),
), ),
@ -2254,12 +2232,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
generatedText = generatedText, generatedText = generatedText,
selectedType = GeneratorState.MainType.Username( selectedType = GeneratorState.MainType.Username(
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
selectedServiceType = GeneratorState selectedServiceType = ServiceType
.MainType
.Username
.UsernameType
.ForwardedEmailAlias
.ServiceType
.DuckDuckGo(), .DuckDuckGo(),
), ),
), ),
@ -2273,12 +2246,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
generatedText = generatedText, generatedText = generatedText,
selectedType = GeneratorState.MainType.Username( selectedType = GeneratorState.MainType.Username(
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
selectedServiceType = GeneratorState selectedServiceType = ServiceType
.MainType
.Username
.UsernameType
.ForwardedEmailAlias
.ServiceType
.FastMail(), .FastMail(),
), ),
), ),
@ -2292,12 +2260,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
generatedText = generatedText, generatedText = generatedText,
selectedType = GeneratorState.MainType.Username( selectedType = GeneratorState.MainType.Username(
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
selectedServiceType = GeneratorState selectedServiceType = ServiceType
.MainType
.Username
.UsernameType
.ForwardedEmailAlias
.ServiceType
.FirefoxRelay(), .FirefoxRelay(),
), ),
), ),
@ -2311,12 +2274,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
generatedText = generatedText, generatedText = generatedText,
selectedType = GeneratorState.MainType.Username( selectedType = GeneratorState.MainType.Username(
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
selectedServiceType = GeneratorState selectedServiceType = ServiceType
.MainType
.Username
.UsernameType
.ForwardedEmailAlias
.ServiceType
.ForwardEmail(), .ForwardEmail(),
), ),
), ),
@ -2330,12 +2288,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
generatedText = generatedText, generatedText = generatedText,
selectedType = GeneratorState.MainType.Username( selectedType = GeneratorState.MainType.Username(
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias( GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
selectedServiceType = GeneratorState selectedServiceType = ServiceType
.MainType
.Username
.UsernameType
.ForwardedEmailAlias
.ServiceType
.SimpleLogin(), .SimpleLogin(),
), ),
), ),

View file

@ -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",
)
}
}
}