mirror of
https://github.com/bitwarden/android.git
synced 2024-10-31 07:05:35 +03:00
BIT-1699 Fix initial pasword type not checking policy (#954)
This commit is contained in:
parent
23721858b8
commit
28f805418d
2 changed files with 51 additions and 6 deletions
|
@ -57,7 +57,6 @@ import javax.inject.Inject
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
|
||||||
private const val KEY_STATE = "state"
|
private const val KEY_STATE = "state"
|
||||||
private const val KEY_GENERATOR_MODE = "key_generator_mode"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ViewModel responsible for handling user interactions in the generator screen.
|
* ViewModel responsible for handling user interactions in the generator screen.
|
||||||
|
@ -100,7 +99,7 @@ class GeneratorViewModel @Inject constructor(
|
||||||
init {
|
init {
|
||||||
stateFlow.onEach { savedStateHandle[KEY_STATE] = it }.launchIn(viewModelScope)
|
stateFlow.onEach { savedStateHandle[KEY_STATE] = it }.launchIn(viewModelScope)
|
||||||
when (val selectedType = mutableStateFlow.value.selectedType) {
|
when (val selectedType = mutableStateFlow.value.selectedType) {
|
||||||
is Passcode -> loadPasscodeOptions(selectedType)
|
is Passcode -> loadPasscodeOptions(selectedType, usePolicyDefault = true)
|
||||||
is Username -> loadUsernameOptions(selectedType)
|
is Username -> loadUsernameOptions(selectedType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,14 +247,26 @@ class GeneratorViewModel @Inject constructor(
|
||||||
//region Generation Handlers
|
//region Generation Handlers
|
||||||
|
|
||||||
@Suppress("CyclomaticComplexMethod")
|
@Suppress("CyclomaticComplexMethod")
|
||||||
private fun loadPasscodeOptions(selectedType: Passcode) {
|
private fun loadPasscodeOptions(selectedType: Passcode, usePolicyDefault: Boolean) {
|
||||||
|
val passwordType = if (usePolicyDefault) {
|
||||||
|
Passcode(
|
||||||
|
selectedType = generatorRepository
|
||||||
|
.getPasswordGeneratorPolicy()
|
||||||
|
?.defaultType
|
||||||
|
?.toSelectedType()
|
||||||
|
?: Password(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
selectedType
|
||||||
|
}
|
||||||
|
|
||||||
val options = generatorRepository.getPasscodeGenerationOptions()
|
val options = generatorRepository.getPasscodeGenerationOptions()
|
||||||
?: generatePasscodeDefaultOptions()
|
?: generatePasscodeDefaultOptions()
|
||||||
|
|
||||||
val policy = policyManager
|
val policy = policyManager
|
||||||
.getActivePolicies<PolicyInformation.PasswordGenerator>()
|
.getActivePolicies<PolicyInformation.PasswordGenerator>()
|
||||||
.toStrictestPolicy()
|
.toStrictestPolicy()
|
||||||
when (selectedType.selectedType) {
|
when (passwordType.selectedType) {
|
||||||
is Passphrase -> {
|
is Passphrase -> {
|
||||||
val minNumWords = policy.minNumberWords ?: Passphrase.PASSPHRASE_MIN_NUMBER_OF_WORDS
|
val minNumWords = policy.minNumberWords ?: Passphrase.PASSPHRASE_MIN_NUMBER_OF_WORDS
|
||||||
val passphrase = Passphrase(
|
val passphrase = Passphrase(
|
||||||
|
@ -638,7 +649,10 @@ class GeneratorViewModel @Inject constructor(
|
||||||
|
|
||||||
private fun handleMainTypeOptionSelect(action: GeneratorAction.MainTypeOptionSelect) {
|
private fun handleMainTypeOptionSelect(action: GeneratorAction.MainTypeOptionSelect) {
|
||||||
when (action.mainTypeOption) {
|
when (action.mainTypeOption) {
|
||||||
GeneratorState.MainTypeOption.PASSWORD -> loadPasscodeOptions(Passcode())
|
GeneratorState.MainTypeOption.PASSWORD -> {
|
||||||
|
loadPasscodeOptions(Passcode(), usePolicyDefault = true)
|
||||||
|
}
|
||||||
|
|
||||||
GeneratorState.MainTypeOption.USERNAME -> loadUsernameOptions(Username())
|
GeneratorState.MainTypeOption.USERNAME -> loadUsernameOptions(Username())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -653,10 +667,12 @@ class GeneratorViewModel @Inject constructor(
|
||||||
when (action.passcodeTypeOption) {
|
when (action.passcodeTypeOption) {
|
||||||
PasscodeTypeOption.PASSWORD -> loadPasscodeOptions(
|
PasscodeTypeOption.PASSWORD -> loadPasscodeOptions(
|
||||||
selectedType = Passcode(selectedType = Password()),
|
selectedType = Passcode(selectedType = Password()),
|
||||||
|
usePolicyDefault = false,
|
||||||
)
|
)
|
||||||
|
|
||||||
PasscodeTypeOption.PASSPHRASE -> loadPasscodeOptions(
|
PasscodeTypeOption.PASSPHRASE -> loadPasscodeOptions(
|
||||||
selectedType = Passcode(selectedType = Passphrase()),
|
selectedType = Passcode(selectedType = Passphrase()),
|
||||||
|
usePolicyDefault = false,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2340,3 +2356,9 @@ private fun UsernameGenerationOptions.ForwardedEmailServiceType?.toServiceType(
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun String?.toSelectedType(): Passcode.PasscodeType =
|
||||||
|
when (this) {
|
||||||
|
PolicyInformation.PasswordGenerator.TYPE_PASSPHRASE -> Passphrase()
|
||||||
|
else -> Password()
|
||||||
|
}
|
||||||
|
|
|
@ -5,10 +5,10 @@ import app.cash.turbine.test
|
||||||
import app.cash.turbine.turbineScope
|
import app.cash.turbine.turbineScope
|
||||||
import com.x8bit.bitwarden.R
|
import com.x8bit.bitwarden.R
|
||||||
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
|
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
|
||||||
|
import com.x8bit.bitwarden.data.auth.repository.model.PolicyInformation
|
||||||
import com.x8bit.bitwarden.data.auth.repository.model.UserState
|
import com.x8bit.bitwarden.data.auth.repository.model.UserState
|
||||||
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
|
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
|
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.util.getActivePolicies
|
|
||||||
import com.x8bit.bitwarden.data.platform.repository.model.Environment
|
import com.x8bit.bitwarden.data.platform.repository.model.Environment
|
||||||
import com.x8bit.bitwarden.data.tools.generator.repository.model.GeneratedCatchAllUsernameResult
|
import com.x8bit.bitwarden.data.tools.generator.repository.model.GeneratedCatchAllUsernameResult
|
||||||
import com.x8bit.bitwarden.data.tools.generator.repository.model.GeneratedForwardedServiceUsernameResult
|
import com.x8bit.bitwarden.data.tools.generator.repository.model.GeneratedForwardedServiceUsernameResult
|
||||||
|
@ -201,6 +201,8 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
||||||
@Test
|
@Test
|
||||||
fun `RegenerateClick action for passphrase state updates generatedText and saves passphrase generation options on successful passphrase generation`() =
|
fun `RegenerateClick action for passphrase state updates generatedText and saves passphrase generation options on successful passphrase generation`() =
|
||||||
runTest {
|
runTest {
|
||||||
|
setupMockPassphraseTypePolicy()
|
||||||
|
|
||||||
val updatedGeneratedPassphrase = "updatedPassphrase"
|
val updatedGeneratedPassphrase = "updatedPassphrase"
|
||||||
|
|
||||||
val viewModel = createViewModel(initialPassphraseState)
|
val viewModel = createViewModel(initialPassphraseState)
|
||||||
|
@ -242,6 +244,8 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
||||||
@Test
|
@Test
|
||||||
fun `RegenerateClick action for passphrase state sends ShowSnackbar event on passphrase generation failure`() =
|
fun `RegenerateClick action for passphrase state sends ShowSnackbar event on passphrase generation failure`() =
|
||||||
runTest {
|
runTest {
|
||||||
|
setupMockPassphraseTypePolicy()
|
||||||
|
|
||||||
val viewModel = createViewModel(initialPassphraseState)
|
val viewModel = createViewModel(initialPassphraseState)
|
||||||
|
|
||||||
fakeGeneratorRepository.setMockGeneratePassphraseResult(
|
fakeGeneratorRepository.setMockGeneratePassphraseResult(
|
||||||
|
@ -1035,6 +1039,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
fun setup() {
|
fun setup() {
|
||||||
|
setupMockPassphraseTypePolicy()
|
||||||
fakeGeneratorRepository.setMockGeneratePasswordResult(
|
fakeGeneratorRepository.setMockGeneratePasswordResult(
|
||||||
GeneratedPasswordResult.Success("defaultPassphrase"),
|
GeneratedPasswordResult.Success("defaultPassphrase"),
|
||||||
)
|
)
|
||||||
|
@ -1900,6 +1905,24 @@ class GeneratorViewModelTest : BaseViewModelTest() {
|
||||||
savedStateHandle = SavedStateHandle().apply { set("state", state) },
|
savedStateHandle = SavedStateHandle().apply { set("state", state) },
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private fun setupMockPassphraseTypePolicy() {
|
||||||
|
fakeGeneratorRepository.setMockPasswordGeneratorPolicy(
|
||||||
|
PolicyInformation.PasswordGenerator(
|
||||||
|
defaultType = "passphrase",
|
||||||
|
minLength = null,
|
||||||
|
useUpper = false,
|
||||||
|
useLower = false,
|
||||||
|
useNumbers = false,
|
||||||
|
useSpecial = false,
|
||||||
|
minNumbers = null,
|
||||||
|
minSpecial = null,
|
||||||
|
minNumberWords = null,
|
||||||
|
capitalize = false,
|
||||||
|
includeNumber = false,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
//endregion Helper Functions
|
//endregion Helper Functions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue