mirror of
https://github.com/bitwarden/android.git
synced 2026-10-23 03:23:53 -05:00
[PM-3553] Support SimpleLogin self hosted servers (#4723)
This commit is contained in:
1 parent
0ba67f5887
commit
65cc0a0dd8
13 files changed
+344
-6
No files matched your search
+3
@@ -52,6 +52,9 @@ data class UsernameGenerationOptions(
|
||||
@SerialName("simpleLoginApiKey")
|
||||
val simpleLoginApiKey: String? = null,
|
||||
|
||||
@SerialName("simpleLoginSelfHostServerUrl")
|
||||
val simpleLoginSelfHostServerUrl: String? = null,
|
||||
|
||||
@SerialName("duckDuckGoApiKey")
|
||||
val duckDuckGoApiKey: String? = null,
|
||||
|
||||
|
||||
@@ -530,6 +530,8 @@ private fun CoachMarkScope<ExploreGeneratorCoachMark>.ScrollContent(
|
||||
randomWordHandlers = randomWordHandlers,
|
||||
shouldShowSelfHostServerUrlField =
|
||||
state.shouldShowAnonAddySelfHostServerUrlField,
|
||||
shouldShowSimpleLoginSelfHostServerUrlField =
|
||||
state.shouldShowSimpleLoginSelfHostServerField,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1104,6 +1106,7 @@ private fun UsernameTypeItems(
|
||||
catchAllEmailHandlers: CatchAllEmailHandlers,
|
||||
randomWordHandlers: RandomWordHandlers,
|
||||
shouldShowSelfHostServerUrlField: Boolean,
|
||||
shouldShowSimpleLoginSelfHostServerUrlField: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(modifier = modifier) {
|
||||
@@ -1129,6 +1132,8 @@ private fun UsernameTypeItems(
|
||||
usernameTypeState = selectedType,
|
||||
forwardedEmailAliasHandlers = forwardedEmailAliasHandlers,
|
||||
shouldShowSelfHostServerUrlField = shouldShowSelfHostServerUrlField,
|
||||
shouldShowSimpleLoginSelfHostServerUrlField =
|
||||
shouldShowSimpleLoginSelfHostServerUrlField,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1190,6 +1195,7 @@ private fun ForwardedEmailAliasTypeContent(
|
||||
usernameTypeState: GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias,
|
||||
forwardedEmailAliasHandlers: ForwardedEmailAliasHandlers,
|
||||
shouldShowSelfHostServerUrlField: Boolean,
|
||||
shouldShowSimpleLoginSelfHostServerUrlField: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(modifier = modifier) {
|
||||
@@ -1329,6 +1335,22 @@ private fun ForwardedEmailAliasTypeContent(
|
||||
.standardHorizontalMargin()
|
||||
.fillMaxWidth(),
|
||||
)
|
||||
|
||||
if (shouldShowSimpleLoginSelfHostServerUrlField) {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
BitwardenTextField(
|
||||
label = stringResource(id = R.string.self_host_server_url),
|
||||
value = usernameTypeState.selectedServiceType.selfHostServerUrl,
|
||||
onValueChange =
|
||||
forwardedEmailAliasHandlers.onSimpleLoginSelfHostServerUrlChange,
|
||||
textFieldTestTag = "SimpleLoginSelfHostServerUrlEntry",
|
||||
cardStyle = CardStyle.Full,
|
||||
modifier = Modifier
|
||||
.standardHorizontalMargin()
|
||||
.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
null -> {
|
||||
|
||||
+67
@@ -115,6 +115,8 @@ class GeneratorViewModel @Inject constructor(
|
||||
shouldShowAnonAddySelfHostServerUrlField = featureFlagManager.getFeatureFlag(
|
||||
FlagKey.AnonAddySelfHostAlias,
|
||||
),
|
||||
shouldShowSimpleLoginSelfHostServerField =
|
||||
featureFlagManager.getFeatureFlag(FlagKey.SimpleLoginSelfHostAlias),
|
||||
)
|
||||
},
|
||||
) {
|
||||
@@ -152,6 +154,15 @@ class GeneratorViewModel @Inject constructor(
|
||||
}
|
||||
.onEach(::sendAction)
|
||||
.launchIn(viewModelScope)
|
||||
|
||||
featureFlagManager.getFeatureFlagFlow(FlagKey.SimpleLoginSelfHostAlias)
|
||||
.map { shouldShowSimpleLoginSelfHostServerField ->
|
||||
GeneratorAction.Internal.ShouldShowSimpleLoginSelfHostValueChangeReceive(
|
||||
shouldShowSelfHostServerField = shouldShowSimpleLoginSelfHostServerField,
|
||||
)
|
||||
}
|
||||
.onEach(::sendAction)
|
||||
.launchIn(viewModelScope)
|
||||
}
|
||||
|
||||
override fun handleAction(action: GeneratorAction) {
|
||||
@@ -249,6 +260,10 @@ class GeneratorViewModel @Inject constructor(
|
||||
is GeneratorAction.MainType.Username.UsernameType.RandomWord -> {
|
||||
handleRandomWordSpecificAction(action)
|
||||
}
|
||||
|
||||
is GeneratorAction.MainType.Username.UsernameType.ForwardedEmailAlias.SimpleLogin.SelfHostServerUrlChange -> {
|
||||
handleSimpleLoginSelfHostServerUrlChange(action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,6 +304,10 @@ class GeneratorViewModel @Inject constructor(
|
||||
is GeneratorAction.Internal.ShouldShowAnonAddySelfHostValueChangeReceive -> {
|
||||
handleShouldShowAnonAddySelfHostValueChange(action)
|
||||
}
|
||||
|
||||
is GeneratorAction.Internal.ShouldShowSimpleLoginSelfHostValueChangeReceive -> {
|
||||
handleShouldShowSimpleLoginSelfHostValueChange(action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -594,6 +613,8 @@ class GeneratorViewModel @Inject constructor(
|
||||
type = UsernameGenerationOptions.UsernameType.FORWARDED_EMAIL_ALIAS,
|
||||
serviceType = UsernameGenerationOptions.ForwardedEmailServiceType.SIMPLE_LOGIN,
|
||||
simpleLoginApiKey = forwardedEmailAlias.selectedServiceType.apiKey,
|
||||
simpleLoginSelfHostServerUrl =
|
||||
forwardedEmailAlias.selectedServiceType.selfHostServerUrl,
|
||||
)
|
||||
|
||||
is ForwardEmail -> options.copy(
|
||||
@@ -643,6 +664,7 @@ class GeneratorViewModel @Inject constructor(
|
||||
catchAllEmailDomain = "",
|
||||
firefoxRelayApiAccessToken = "",
|
||||
simpleLoginApiKey = "",
|
||||
simpleLoginSelfHostServerUrl = "",
|
||||
duckDuckGoApiKey = "",
|
||||
fastMailApiKey = "",
|
||||
anonAddyApiAccessToken = "",
|
||||
@@ -813,6 +835,14 @@ class GeneratorViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleShouldShowSimpleLoginSelfHostValueChange(
|
||||
action: GeneratorAction.Internal.ShouldShowSimpleLoginSelfHostValueChangeReceive,
|
||||
) {
|
||||
mutableStateFlow.update {
|
||||
it.copy(shouldShowSimpleLoginSelfHostServerField = action.shouldShowSelfHostServerField)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handlePasswordGeneratorPolicyReceive(
|
||||
action: GeneratorAction.Internal.PasswordGeneratorPolicyReceive,
|
||||
) {
|
||||
@@ -1392,6 +1422,21 @@ class GeneratorViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSimpleLoginSelfHostServerUrlChange(
|
||||
action: GeneratorAction
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.SimpleLogin
|
||||
.SelfHostServerUrlChange,
|
||||
) {
|
||||
updateSimpleLoginServiceType { simpleLoginServiceType ->
|
||||
val newServerUrl = action.url
|
||||
simpleLoginServiceType.copy(selfHostServerUrl = newServerUrl)
|
||||
}
|
||||
}
|
||||
|
||||
//endregion SimpleLogin Service Specific Handlers
|
||||
|
||||
//region Plus Addressed Email Specific Handlers
|
||||
@@ -1538,6 +1583,7 @@ class GeneratorViewModel @Inject constructor(
|
||||
?.toUsernameGeneratorRequest(
|
||||
website = state.website,
|
||||
allowAddyIoSelfHostUrl = state.shouldShowAnonAddySelfHostServerUrlField,
|
||||
allowSimpleLoginSelfHostUrl = state.shouldShowSimpleLoginSelfHostServerField,
|
||||
)
|
||||
?: run {
|
||||
mutableStateFlow.update { it.copy(generatedText = NO_GENERATED_TEXT) }
|
||||
@@ -1840,6 +1886,7 @@ data class GeneratorState(
|
||||
var passcodePolicyOverride: PasscodePolicyOverride? = null,
|
||||
private val shouldShowCoachMarkTour: Boolean,
|
||||
val shouldShowAnonAddySelfHostServerUrlField: Boolean,
|
||||
val shouldShowSimpleLoginSelfHostServerField: Boolean,
|
||||
) : Parcelable {
|
||||
|
||||
/**
|
||||
@@ -2243,9 +2290,15 @@ data class GeneratorState(
|
||||
@Parcelize
|
||||
data class SimpleLogin(
|
||||
val apiKey: String = "",
|
||||
val selfHostServerUrl: String = "",
|
||||
) : ServiceType(), Parcelable {
|
||||
override val displayStringResId: Int
|
||||
get() = ServiceTypeOption.SIMPLE_LOGIN.labelRes
|
||||
|
||||
@Suppress("UndocumentedPublicClass")
|
||||
companion object {
|
||||
const val DEFAULT_SIMPLE_LOGIN_URL = "https://app.simplelogin.io"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2586,6 +2639,13 @@ sealed class GeneratorAction {
|
||||
* @property apiKey The new api key text.
|
||||
*/
|
||||
data class ApiKeyTextChange(val apiKey: String) : SimpleLogin()
|
||||
|
||||
/**
|
||||
* Fired when the self host server url input text is changed.
|
||||
*
|
||||
* @property url The new self host server url text.
|
||||
*/
|
||||
data class SelfHostServerUrlChange(val url: String) : SimpleLogin()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2704,6 +2764,13 @@ sealed class GeneratorAction {
|
||||
data class ShouldShowAnonAddySelfHostValueChangeReceive(
|
||||
val shouldShowAnonAddySelfHostServerUrlField: Boolean,
|
||||
) : Internal()
|
||||
|
||||
/**
|
||||
* The value for the shouldShowSimpleLoginSelfHostServerField has changed.
|
||||
*/
|
||||
data class ShouldShowSimpleLoginSelfHostValueChangeReceive(
|
||||
val shouldShowSelfHostServerField: Boolean,
|
||||
) : Internal()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
-1
@@ -12,7 +12,7 @@ import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorAction.MainType.U
|
||||
* Each lambda corresponds to a specific user action, allowing for easy delegation of
|
||||
* logic when user input is detected.
|
||||
*/
|
||||
@Suppress("LongParameterList")
|
||||
@Suppress("LongParameterList", "LongMethod")
|
||||
data class ForwardedEmailAliasHandlers(
|
||||
val onServiceChange: (ForwardedEmailAlias.ServiceTypeOption) -> Unit,
|
||||
val onAddyIoAccessTokenTextChange: (String) -> Unit,
|
||||
@@ -24,6 +24,7 @@ data class ForwardedEmailAliasHandlers(
|
||||
val onForwardEmailApiKeyTextChange: (String) -> Unit,
|
||||
val onForwardEmailDomainNameTextChange: (String) -> Unit,
|
||||
val onSimpleLoginApiKeyTextChange: (String) -> Unit,
|
||||
val onSimpleLoginSelfHostServerUrlChange: (String) -> Unit,
|
||||
) {
|
||||
@Suppress("UndocumentedPublicClass")
|
||||
companion object {
|
||||
@@ -93,6 +94,13 @@ data class ForwardedEmailAliasHandlers(
|
||||
ForwardedEmailAliasAction.SimpleLogin.ApiKeyTextChange(apiKey = newApiKey),
|
||||
)
|
||||
},
|
||||
onSimpleLoginSelfHostServerUrlChange = { newServerUrl ->
|
||||
viewModel.trySendAction(
|
||||
ForwardedEmailAliasAction.SimpleLogin.SelfHostServerUrlChange(
|
||||
url = newServerUrl,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+6
-1
@@ -24,7 +24,12 @@ fun UsernameGenerationOptions.ForwardedEmailServiceType?.toServiceType(
|
||||
}
|
||||
|
||||
UsernameGenerationOptions.ForwardedEmailServiceType.SIMPLE_LOGIN -> {
|
||||
SimpleLogin(apiKey = options.simpleLoginApiKey.orEmpty())
|
||||
SimpleLogin(
|
||||
apiKey = options.simpleLoginApiKey.orEmpty(),
|
||||
selfHostServerUrl = options.simpleLoginSelfHostServerUrl
|
||||
?.prefixHttpsIfNecessary()
|
||||
.orEmpty(),
|
||||
)
|
||||
}
|
||||
|
||||
UsernameGenerationOptions.ForwardedEmailServiceType.DUCK_DUCK_GO -> {
|
||||
|
||||
+7
-1
@@ -13,6 +13,7 @@ import com.x8bit.bitwarden.ui.tools.feature.generator.GeneratorState.MainType.Us
|
||||
fun ServiceType.toUsernameGeneratorRequest(
|
||||
website: String?,
|
||||
allowAddyIoSelfHostUrl: Boolean,
|
||||
allowSimpleLoginSelfHostUrl: Boolean,
|
||||
): UsernameGeneratorRequest.Forwarded? {
|
||||
return when (this) {
|
||||
is ServiceType.AddyIo -> {
|
||||
@@ -80,12 +81,17 @@ fun ServiceType.toUsernameGeneratorRequest(
|
||||
}
|
||||
|
||||
is ServiceType.SimpleLogin -> {
|
||||
val baseUrl = if (allowSimpleLoginSelfHostUrl && selfHostServerUrl.isNotBlank()) {
|
||||
selfHostServerUrl.prefixHttpsIfNecessary()
|
||||
} else {
|
||||
ServiceType.SimpleLogin.DEFAULT_SIMPLE_LOGIN_URL
|
||||
}
|
||||
this
|
||||
.apiKey
|
||||
.orNullIfBlank()
|
||||
?.let {
|
||||
UsernameGeneratorRequest.Forwarded(
|
||||
service = ForwarderServiceType.SimpleLogin(apiKey = it),
|
||||
service = ForwarderServiceType.SimpleLogin(apiKey = it, baseUrl = baseUrl),
|
||||
website = website,
|
||||
)
|
||||
}
|
||||
|
||||
+3
@@ -53,6 +53,7 @@ class GeneratorDiskSourceTest {
|
||||
catchAllEmailDomain = "example.com",
|
||||
firefoxRelayApiAccessToken = "access_token_firefox_relay",
|
||||
simpleLoginApiKey = "api_key_simple_login",
|
||||
simpleLoginSelfHostServerUrl = "https://simplelogin.local",
|
||||
duckDuckGoApiKey = "api_key_duck_duck_go",
|
||||
fastMailApiKey = "api_key_fast_mail",
|
||||
anonAddyApiAccessToken = "access_token_anon_addy",
|
||||
@@ -157,6 +158,7 @@ class GeneratorDiskSourceTest {
|
||||
catchAllEmailDomain = "example.com",
|
||||
firefoxRelayApiAccessToken = "access_token_firefox_relay",
|
||||
simpleLoginApiKey = "api_key_simple_login",
|
||||
simpleLoginSelfHostServerUrl = "https://simplelogin.local",
|
||||
duckDuckGoApiKey = "api_key_duck_duck_go",
|
||||
fastMailApiKey = "api_key_fast_mail",
|
||||
anonAddyApiAccessToken = "access_token_anon_addy",
|
||||
@@ -195,6 +197,7 @@ class GeneratorDiskSourceTest {
|
||||
catchAllEmailDomain = "example.com",
|
||||
firefoxRelayApiAccessToken = "access_token_firefox_relay",
|
||||
simpleLoginApiKey = "api_key_simple_login",
|
||||
simpleLoginSelfHostServerUrl = "https://simplelogin.local",
|
||||
duckDuckGoApiKey = "api_key_duck_duck_go",
|
||||
fastMailApiKey = "api_key_fast_mail",
|
||||
anonAddyApiAccessToken = "access_token_anon_addy",
|
||||
|
||||
+3
@@ -645,6 +645,7 @@ class GeneratorRepositoryTest {
|
||||
catchAllEmailDomain = "example.com",
|
||||
firefoxRelayApiAccessToken = "access_token_firefox_relay",
|
||||
simpleLoginApiKey = "api_key_simple_login",
|
||||
simpleLoginSelfHostServerUrl = "https://simplelogin.local",
|
||||
duckDuckGoApiKey = "api_key_duck_duck_go",
|
||||
fastMailApiKey = "api_key_fast_mail",
|
||||
anonAddyApiAccessToken = "access_token_anon_addy",
|
||||
@@ -698,6 +699,7 @@ class GeneratorRepositoryTest {
|
||||
catchAllEmailDomain = "example.com",
|
||||
firefoxRelayApiAccessToken = "access_token_firefox_relay",
|
||||
simpleLoginApiKey = "api_key_simple_login",
|
||||
simpleLoginSelfHostServerUrl = "https://simplelogin.local",
|
||||
duckDuckGoApiKey = "api_key_duck_duck_go",
|
||||
fastMailApiKey = "api_key_fast_mail",
|
||||
anonAddyApiAccessToken = "access_token_anon_addy",
|
||||
@@ -729,6 +731,7 @@ class GeneratorRepositoryTest {
|
||||
catchAllEmailDomain = "example.com",
|
||||
firefoxRelayApiAccessToken = "access_token_firefox_relay",
|
||||
simpleLoginApiKey = "api_key_simple_login",
|
||||
simpleLoginSelfHostServerUrl = "https://simplelogin.local",
|
||||
duckDuckGoApiKey = "api_key_duck_duck_go",
|
||||
fastMailApiKey = "api_key_fast_mail",
|
||||
anonAddyApiAccessToken = "access_token_anon_addy",
|
||||
|
||||
+88
@@ -1365,6 +1365,93 @@ class GeneratorScreenTest : BaseComposeTest() {
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `in Username_ForwardedEmailAlias_SimpleLogin state, updating self host server url text input should send SelfHostServerUrlChange action`() {
|
||||
updateState(
|
||||
DEFAULT_STATE.copy(
|
||||
selectedType = GeneratorState.MainType.Username(
|
||||
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
|
||||
selectedServiceType = GeneratorState
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.ServiceType
|
||||
.SimpleLogin(),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
val newSelfHostServerUrl = "https://simplelogin.local"
|
||||
|
||||
composeTestRule
|
||||
.onNodeWithText("Self-host server URL")
|
||||
.performScrollTo()
|
||||
.performTextInput(newSelfHostServerUrl)
|
||||
|
||||
verify {
|
||||
viewModel.trySendAction(
|
||||
GeneratorAction
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.SimpleLogin
|
||||
.SelfHostServerUrlChange(url = newSelfHostServerUrl),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `in Username_ForwardedEmailAlias_SimpleLogin state, should display self host server url field based on state`() {
|
||||
updateState(
|
||||
DEFAULT_STATE.copy(
|
||||
selectedType = GeneratorState.MainType.Username(
|
||||
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
|
||||
selectedServiceType = GeneratorState
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.ServiceType
|
||||
.SimpleLogin(),
|
||||
),
|
||||
),
|
||||
shouldShowSimpleLoginSelfHostServerField = true,
|
||||
),
|
||||
)
|
||||
|
||||
composeTestRule
|
||||
.onNodeWithText("Self-host server URL")
|
||||
.performScrollTo()
|
||||
.assertIsDisplayed()
|
||||
|
||||
// Simulate disabling the feature flag.
|
||||
updateState(
|
||||
DEFAULT_STATE.copy(
|
||||
selectedType = GeneratorState.MainType.Username(
|
||||
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
|
||||
selectedServiceType = GeneratorState
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.ServiceType
|
||||
.SimpleLogin(),
|
||||
),
|
||||
),
|
||||
shouldShowSimpleLoginSelfHostServerField = false,
|
||||
),
|
||||
)
|
||||
|
||||
composeTestRule
|
||||
.onNodeWithText("Self-host server URL")
|
||||
.assertDoesNotExist()
|
||||
}
|
||||
|
||||
//endregion SimpleLogin Service Type Tests
|
||||
|
||||
//region ForwardEmail Service Type Tests
|
||||
@@ -1853,4 +1940,5 @@ private val DEFAULT_STATE = GeneratorState(
|
||||
currentEmailAddress = "currentEmail",
|
||||
shouldShowCoachMarkTour = false,
|
||||
shouldShowAnonAddySelfHostServerUrlField = true,
|
||||
shouldShowSimpleLoginSelfHostServerField = true,
|
||||
)
|
||||
+59
@@ -122,11 +122,16 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
||||
every { shouldShowGeneratorCoachMarkFlow } returns mutableShouldShowGeneratorCoachMarkFlow
|
||||
}
|
||||
private val mutableAnonAddySelfHostAliasFlow = MutableStateFlow(true)
|
||||
private val mutableShouldShowSimpleLoginSelfHostFlow = MutableStateFlow(true)
|
||||
private val featureFlagManager = mockk<FeatureFlagManager> {
|
||||
every { getFeatureFlag(FlagKey.AnonAddySelfHostAlias) } returns true
|
||||
every {
|
||||
getFeatureFlagFlow(FlagKey.AnonAddySelfHostAlias)
|
||||
} returns mutableAnonAddySelfHostAliasFlow
|
||||
every { getFeatureFlag(FlagKey.SimpleLoginSelfHostAlias) } returns true
|
||||
every {
|
||||
getFeatureFlagFlow(FlagKey.SimpleLoginSelfHostAlias)
|
||||
} returns mutableShouldShowSimpleLoginSelfHostFlow
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -145,6 +150,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
||||
fun `initial state should be correct for username modal`() {
|
||||
val usernameGenerationOptions = UsernameGenerationOptions(
|
||||
type = UsernameGenerationOptions.UsernameType.RANDOM_WORD,
|
||||
simpleLoginSelfHostServerUrl = "",
|
||||
)
|
||||
fakeGeneratorRepository.saveUsernameGenerationOptions(usernameGenerationOptions)
|
||||
val expected = GeneratorState(
|
||||
@@ -160,6 +166,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
||||
website = "",
|
||||
shouldShowCoachMarkTour = true,
|
||||
shouldShowAnonAddySelfHostServerUrlField = true,
|
||||
shouldShowSimpleLoginSelfHostServerField = true,
|
||||
)
|
||||
|
||||
val viewModel = createViewModel(
|
||||
@@ -195,6 +202,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
||||
currentEmailAddress = "currentEmail",
|
||||
shouldShowCoachMarkTour = true,
|
||||
shouldShowAnonAddySelfHostServerUrlField = true,
|
||||
shouldShowSimpleLoginSelfHostServerField = true,
|
||||
)
|
||||
|
||||
val viewModel = createViewModel(
|
||||
@@ -930,6 +938,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
||||
fakeGeneratorRepository.saveUsernameGenerationOptions(
|
||||
UsernameGenerationOptions(
|
||||
type = UsernameGenerationOptions.UsernameType.RANDOM_WORD,
|
||||
simpleLoginSelfHostServerUrl = "",
|
||||
),
|
||||
)
|
||||
val expectedState = initialState.copy(
|
||||
@@ -1010,6 +1019,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
||||
fakeGeneratorRepository.saveUsernameGenerationOptions(
|
||||
UsernameGenerationOptions(
|
||||
type = UsernameGenerationOptions.UsernameType.RANDOM_WORD,
|
||||
simpleLoginSelfHostServerUrl = "",
|
||||
),
|
||||
)
|
||||
// When this action is handled there will be another call to `loadOptions()`
|
||||
@@ -2049,6 +2059,42 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
||||
|
||||
assertEquals(expectedState, viewModel.stateFlow.value)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `SelfHostServerUrlChange should update self host server url correctly`() = runTest {
|
||||
val newSelfHostServerUrl = "https://newSelfHostServerUrl"
|
||||
val action = GeneratorAction
|
||||
.MainType
|
||||
.Username
|
||||
.UsernameType
|
||||
.ForwardedEmailAlias
|
||||
.SimpleLogin
|
||||
.SelfHostServerUrlChange(
|
||||
url = newSelfHostServerUrl,
|
||||
)
|
||||
|
||||
fakeGeneratorRepository.setMockGenerateForwardedServiceResult(
|
||||
GeneratedForwardedServiceUsernameResult.Success(
|
||||
generatedEmailAddress = "defaultSimpleLogin",
|
||||
),
|
||||
)
|
||||
|
||||
viewModel.trySendAction(action)
|
||||
|
||||
val expectedState = defaultSimpleLoginState.copy(
|
||||
generatedText = "-",
|
||||
selectedType = GeneratorState.MainType.Username(
|
||||
GeneratorState.MainType.Username.UsernameType.ForwardedEmailAlias(
|
||||
selectedServiceType = ServiceType
|
||||
.SimpleLogin(
|
||||
selfHostServerUrl = newSelfHostServerUrl,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(expectedState, viewModel.stateFlow.value)
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@@ -2336,6 +2382,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
||||
currentEmailAddress = "currentEmail",
|
||||
shouldShowCoachMarkTour = true,
|
||||
shouldShowAnonAddySelfHostServerUrlField = true,
|
||||
shouldShowSimpleLoginSelfHostServerField = true,
|
||||
)
|
||||
|
||||
private fun createPassphraseState(
|
||||
@@ -2356,6 +2403,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
||||
currentEmailAddress = "currentEmail",
|
||||
shouldShowCoachMarkTour = true,
|
||||
shouldShowAnonAddySelfHostServerUrlField = true,
|
||||
shouldShowSimpleLoginSelfHostServerField = true,
|
||||
)
|
||||
|
||||
private fun createUsernameModeState(
|
||||
@@ -2373,6 +2421,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
||||
currentEmailAddress = "currentEmail",
|
||||
shouldShowCoachMarkTour = true,
|
||||
shouldShowAnonAddySelfHostServerUrlField = true,
|
||||
shouldShowSimpleLoginSelfHostServerField = true,
|
||||
)
|
||||
|
||||
private fun createForwardedEmailAliasState(
|
||||
@@ -2390,6 +2439,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
||||
currentEmailAddress = "currentEmail",
|
||||
shouldShowCoachMarkTour = true,
|
||||
shouldShowAnonAddySelfHostServerUrlField = true,
|
||||
shouldShowSimpleLoginSelfHostServerField = true,
|
||||
)
|
||||
|
||||
private fun createAddyIoState(
|
||||
@@ -2406,6 +2456,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
||||
currentEmailAddress = "currentEmail",
|
||||
shouldShowCoachMarkTour = true,
|
||||
shouldShowAnonAddySelfHostServerUrlField = true,
|
||||
shouldShowSimpleLoginSelfHostServerField = true,
|
||||
)
|
||||
|
||||
private fun createDuckDuckGoState(
|
||||
@@ -2422,6 +2473,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
||||
currentEmailAddress = "currentEmail",
|
||||
shouldShowCoachMarkTour = true,
|
||||
shouldShowAnonAddySelfHostServerUrlField = true,
|
||||
shouldShowSimpleLoginSelfHostServerField = true,
|
||||
)
|
||||
|
||||
private fun createFastMailState(
|
||||
@@ -2438,6 +2490,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
||||
currentEmailAddress = "currentEmail",
|
||||
shouldShowCoachMarkTour = true,
|
||||
shouldShowAnonAddySelfHostServerUrlField = true,
|
||||
shouldShowSimpleLoginSelfHostServerField = true,
|
||||
)
|
||||
|
||||
private fun createFirefoxRelayState(
|
||||
@@ -2454,6 +2507,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
||||
currentEmailAddress = "currentEmail",
|
||||
shouldShowCoachMarkTour = true,
|
||||
shouldShowAnonAddySelfHostServerUrlField = true,
|
||||
shouldShowSimpleLoginSelfHostServerField = true,
|
||||
)
|
||||
|
||||
private fun createForwardEmailState(
|
||||
@@ -2470,6 +2524,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
||||
currentEmailAddress = "currentEmail",
|
||||
shouldShowCoachMarkTour = true,
|
||||
shouldShowAnonAddySelfHostServerUrlField = true,
|
||||
shouldShowSimpleLoginSelfHostServerField = true,
|
||||
)
|
||||
|
||||
private fun createSimpleLoginState(
|
||||
@@ -2486,6 +2541,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
||||
currentEmailAddress = "currentEmail",
|
||||
shouldShowCoachMarkTour = true,
|
||||
shouldShowAnonAddySelfHostServerUrlField = true,
|
||||
shouldShowSimpleLoginSelfHostServerField = true,
|
||||
)
|
||||
|
||||
private fun createPlusAddressedEmailState(
|
||||
@@ -2502,6 +2558,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
||||
currentEmailAddress = "currentEmail",
|
||||
shouldShowCoachMarkTour = true,
|
||||
shouldShowAnonAddySelfHostServerUrlField = true,
|
||||
shouldShowSimpleLoginSelfHostServerField = true,
|
||||
)
|
||||
|
||||
private fun createCatchAllEmailState(
|
||||
@@ -2518,6 +2575,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
||||
currentEmailAddress = "currentEmail",
|
||||
shouldShowCoachMarkTour = true,
|
||||
shouldShowAnonAddySelfHostServerUrlField = true,
|
||||
shouldShowSimpleLoginSelfHostServerField = true,
|
||||
)
|
||||
|
||||
private fun createRandomWordState(
|
||||
@@ -2536,6 +2594,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
||||
currentEmailAddress = "currentEmail",
|
||||
shouldShowCoachMarkTour = true,
|
||||
shouldShowAnonAddySelfHostServerUrlField = true,
|
||||
shouldShowSimpleLoginSelfHostServerField = true,
|
||||
)
|
||||
|
||||
private fun createSavedStateHandleWithState(state: GeneratorState) =
|
||||
|
||||
+5
@@ -18,6 +18,7 @@ class ForwardedEmailServiceTypeExtensionsTest {
|
||||
catchAllEmailDomain = "example.com",
|
||||
firefoxRelayApiAccessToken = "access_token_firefox_relay",
|
||||
simpleLoginApiKey = "api_key_simple_login",
|
||||
simpleLoginSelfHostServerUrl = "https://simplelogin.local",
|
||||
duckDuckGoApiKey = "api_key_duck_duck_go",
|
||||
fastMailApiKey = "api_key_fast_mail",
|
||||
anonAddyApiAccessToken = "access_token_anon_addy",
|
||||
@@ -51,6 +52,7 @@ class ForwardedEmailServiceTypeExtensionsTest {
|
||||
catchAllEmailDomain = null,
|
||||
firefoxRelayApiAccessToken = null,
|
||||
simpleLoginApiKey = null,
|
||||
simpleLoginSelfHostServerUrl = null,
|
||||
duckDuckGoApiKey = null,
|
||||
fastMailApiKey = null,
|
||||
anonAddyApiAccessToken = null,
|
||||
@@ -101,6 +103,9 @@ class ForwardedEmailServiceTypeExtensionsTest {
|
||||
apiKey = "api_key_simple_login"
|
||||
.takeUnless { useEmptyValues }
|
||||
.orEmpty(),
|
||||
selfHostServerUrl = "https://simplelogin.local"
|
||||
.takeUnless { useEmptyValues }
|
||||
.orEmpty(),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+71
-2
@@ -18,6 +18,7 @@ internal class ServiceTypeExtensionsTest {
|
||||
val request = addyIoServiceType.toUsernameGeneratorRequest(
|
||||
website = null,
|
||||
allowAddyIoSelfHostUrl = true,
|
||||
allowSimpleLoginSelfHostUrl = true,
|
||||
)
|
||||
|
||||
assertNull(request)
|
||||
@@ -32,6 +33,7 @@ internal class ServiceTypeExtensionsTest {
|
||||
val request = addyIoServiceType.toUsernameGeneratorRequest(
|
||||
website = null,
|
||||
allowAddyIoSelfHostUrl = true,
|
||||
allowSimpleLoginSelfHostUrl = true,
|
||||
)
|
||||
|
||||
assertNull(request)
|
||||
@@ -58,6 +60,7 @@ internal class ServiceTypeExtensionsTest {
|
||||
addyIoServiceType.toUsernameGeneratorRequest(
|
||||
website = website,
|
||||
allowAddyIoSelfHostUrl = true,
|
||||
allowSimpleLoginSelfHostUrl = true,
|
||||
),
|
||||
)
|
||||
|
||||
@@ -74,6 +77,7 @@ internal class ServiceTypeExtensionsTest {
|
||||
addyIoServiceType.toUsernameGeneratorRequest(
|
||||
website = website,
|
||||
allowAddyIoSelfHostUrl = false,
|
||||
allowSimpleLoginSelfHostUrl = true,
|
||||
),
|
||||
)
|
||||
}
|
||||
@@ -89,6 +93,7 @@ internal class ServiceTypeExtensionsTest {
|
||||
val request = addyIoServiceType.toUsernameGeneratorRequest(
|
||||
website = website,
|
||||
allowAddyIoSelfHostUrl = true,
|
||||
allowSimpleLoginSelfHostUrl = true,
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
@@ -110,6 +115,7 @@ internal class ServiceTypeExtensionsTest {
|
||||
val request = duckDuckGoServiceType.toUsernameGeneratorRequest(
|
||||
website = null,
|
||||
allowAddyIoSelfHostUrl = true,
|
||||
allowSimpleLoginSelfHostUrl = true,
|
||||
)
|
||||
|
||||
assertNull(request)
|
||||
@@ -122,6 +128,7 @@ internal class ServiceTypeExtensionsTest {
|
||||
val request = duckDuckGoServiceType.toUsernameGeneratorRequest(
|
||||
website = website,
|
||||
allowAddyIoSelfHostUrl = true,
|
||||
allowSimpleLoginSelfHostUrl = true,
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
@@ -139,6 +146,7 @@ internal class ServiceTypeExtensionsTest {
|
||||
val request = firefoxRelayServiceType.toUsernameGeneratorRequest(
|
||||
website = null,
|
||||
allowAddyIoSelfHostUrl = true,
|
||||
allowSimpleLoginSelfHostUrl = true,
|
||||
)
|
||||
|
||||
assertNull(request)
|
||||
@@ -151,6 +159,7 @@ internal class ServiceTypeExtensionsTest {
|
||||
val request = firefoxRelayServiceType.toUsernameGeneratorRequest(
|
||||
website = website,
|
||||
allowAddyIoSelfHostUrl = true,
|
||||
allowSimpleLoginSelfHostUrl = true,
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
@@ -168,6 +177,7 @@ internal class ServiceTypeExtensionsTest {
|
||||
val request = fastMailServiceType.toUsernameGeneratorRequest(
|
||||
website = null,
|
||||
allowAddyIoSelfHostUrl = true,
|
||||
allowSimpleLoginSelfHostUrl = true,
|
||||
)
|
||||
|
||||
assertNull(request)
|
||||
@@ -182,6 +192,7 @@ internal class ServiceTypeExtensionsTest {
|
||||
val request = fastMailServiceType.toUsernameGeneratorRequest(
|
||||
website = website,
|
||||
allowAddyIoSelfHostUrl = true,
|
||||
allowSimpleLoginSelfHostUrl = true,
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
@@ -202,6 +213,7 @@ internal class ServiceTypeExtensionsTest {
|
||||
val request = forwardMailServiceType.toUsernameGeneratorRequest(
|
||||
website = null,
|
||||
allowAddyIoSelfHostUrl = true,
|
||||
allowSimpleLoginSelfHostUrl = true,
|
||||
)
|
||||
|
||||
assertNull(request)
|
||||
@@ -216,6 +228,7 @@ internal class ServiceTypeExtensionsTest {
|
||||
val request = forwardMailServiceType.toUsernameGeneratorRequest(
|
||||
website = null,
|
||||
allowAddyIoSelfHostUrl = true,
|
||||
allowSimpleLoginSelfHostUrl = true,
|
||||
)
|
||||
|
||||
assertNull(request)
|
||||
@@ -231,6 +244,7 @@ internal class ServiceTypeExtensionsTest {
|
||||
val request = forwardEmailServiceType.toUsernameGeneratorRequest(
|
||||
website = website,
|
||||
allowAddyIoSelfHostUrl = true,
|
||||
allowSimpleLoginSelfHostUrl = true,
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
@@ -251,23 +265,78 @@ internal class ServiceTypeExtensionsTest {
|
||||
val request = simpleLoginServiceType.toUsernameGeneratorRequest(
|
||||
website = null,
|
||||
allowAddyIoSelfHostUrl = true,
|
||||
allowSimpleLoginSelfHostUrl = true,
|
||||
)
|
||||
|
||||
assertNull(request)
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `toUsernameGeneratorRequest for SimpleLogin returns correct request`() {
|
||||
fun `toUsernameGeneratorRequest for SimpleLogin returns correct request when allowSimpleLoginSelfHostServer is false and selfHostServerUrl is blank`() {
|
||||
val simpleLoginServiceType = ServiceType.SimpleLogin(apiKey = "testKey")
|
||||
val website = "bitwarden.com"
|
||||
val request = simpleLoginServiceType.toUsernameGeneratorRequest(
|
||||
website = website,
|
||||
allowAddyIoSelfHostUrl = true,
|
||||
allowSimpleLoginSelfHostUrl = true,
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
UsernameGeneratorRequest.Forwarded(
|
||||
service = ForwarderServiceType.SimpleLogin(apiKey = "testKey"),
|
||||
service = ForwarderServiceType.SimpleLogin(
|
||||
apiKey = "testKey",
|
||||
ServiceType.SimpleLogin.DEFAULT_SIMPLE_LOGIN_URL,
|
||||
),
|
||||
website = website,
|
||||
),
|
||||
request,
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `toUsernameGeneratorRequest for SimpleLogin returns correct request when allowSimpleLoginSelfHostServer is true and selfHostServerUrl is blank`() {
|
||||
val simpleLoginServiceType = ServiceType.SimpleLogin(apiKey = "testKey")
|
||||
val website = "bitwarden.com"
|
||||
val request = simpleLoginServiceType.toUsernameGeneratorRequest(
|
||||
website = website,
|
||||
allowAddyIoSelfHostUrl = true,
|
||||
allowSimpleLoginSelfHostUrl = true,
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
UsernameGeneratorRequest.Forwarded(
|
||||
service = ForwarderServiceType.SimpleLogin(
|
||||
apiKey = "testKey",
|
||||
ServiceType.SimpleLogin.DEFAULT_SIMPLE_LOGIN_URL,
|
||||
),
|
||||
website = website,
|
||||
),
|
||||
request,
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `toUsernameGeneratorRequest for SimpleLogin returns correct request when allowSimpleLoginSelfHostServer is true and selfHostServerUrl is not blank`() {
|
||||
val simpleLoginServiceType = ServiceType.SimpleLogin(
|
||||
apiKey = "testKey",
|
||||
selfHostServerUrl = "https://simplelogin.local",
|
||||
)
|
||||
val website = "bitwarden.com"
|
||||
val request = simpleLoginServiceType.toUsernameGeneratorRequest(
|
||||
website = website,
|
||||
allowAddyIoSelfHostUrl = true,
|
||||
allowSimpleLoginSelfHostUrl = true,
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
UsernameGeneratorRequest.Forwarded(
|
||||
service = ForwarderServiceType.SimpleLogin(
|
||||
apiKey = "testKey",
|
||||
baseUrl = "https://simplelogin.local",
|
||||
),
|
||||
website = website,
|
||||
),
|
||||
request,
|
||||
|
||||
@@ -26,7 +26,7 @@ androidxSplash = "1.1.0-rc01"
|
||||
androidXAppCompat = "1.7.0"
|
||||
androdixAutofill = "1.1.0"
|
||||
androidxWork = "2.10.0"
|
||||
bitwardenSdk = "1.0.0-20250203.153811-96"
|
||||
bitwardenSdk = "1.0.0-20250213.181812-113"
|
||||
crashlytics = "3.0.2"
|
||||
detekt = "1.23.7"
|
||||
firebaseBom = "33.8.0"
|
||||
|
||||
Reference in new issue
Block a user