BIT-1699 Fix initial pasword type not checking policy (#954)

This commit is contained in:
Oleg Semenenko 2024-02-05 14:32:50 -06:00 committed by Álison Fernandes
parent 23721858b8
commit 28f805418d
2 changed files with 51 additions and 6 deletions

View file

@ -57,7 +57,6 @@ import javax.inject.Inject
import kotlin.math.max
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.
@ -100,7 +99,7 @@ class GeneratorViewModel @Inject constructor(
init {
stateFlow.onEach { savedStateHandle[KEY_STATE] = it }.launchIn(viewModelScope)
when (val selectedType = mutableStateFlow.value.selectedType) {
is Passcode -> loadPasscodeOptions(selectedType)
is Passcode -> loadPasscodeOptions(selectedType, usePolicyDefault = true)
is Username -> loadUsernameOptions(selectedType)
}
}
@ -248,14 +247,26 @@ class GeneratorViewModel @Inject constructor(
//region Generation Handlers
@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()
?: generatePasscodeDefaultOptions()
val policy = policyManager
.getActivePolicies<PolicyInformation.PasswordGenerator>()
.toStrictestPolicy()
when (selectedType.selectedType) {
when (passwordType.selectedType) {
is Passphrase -> {
val minNumWords = policy.minNumberWords ?: Passphrase.PASSPHRASE_MIN_NUMBER_OF_WORDS
val passphrase = Passphrase(
@ -638,7 +649,10 @@ class GeneratorViewModel @Inject constructor(
private fun handleMainTypeOptionSelect(action: GeneratorAction.MainTypeOptionSelect) {
when (action.mainTypeOption) {
GeneratorState.MainTypeOption.PASSWORD -> loadPasscodeOptions(Passcode())
GeneratorState.MainTypeOption.PASSWORD -> {
loadPasscodeOptions(Passcode(), usePolicyDefault = true)
}
GeneratorState.MainTypeOption.USERNAME -> loadUsernameOptions(Username())
}
}
@ -653,10 +667,12 @@ class GeneratorViewModel @Inject constructor(
when (action.passcodeTypeOption) {
PasscodeTypeOption.PASSWORD -> loadPasscodeOptions(
selectedType = Passcode(selectedType = Password()),
usePolicyDefault = false,
)
PasscodeTypeOption.PASSPHRASE -> loadPasscodeOptions(
selectedType = Passcode(selectedType = Passphrase()),
usePolicyDefault = false,
)
}
}
@ -2340,3 +2356,9 @@ private fun UsernameGenerationOptions.ForwardedEmailServiceType?.toServiceType(
else -> null
}
}
private fun String?.toSelectedType(): Passcode.PasscodeType =
when (this) {
PolicyInformation.PasswordGenerator.TYPE_PASSPHRASE -> Passphrase()
else -> Password()
}

View file

@ -5,10 +5,10 @@ import app.cash.turbine.test
import app.cash.turbine.turbineScope
import com.x8bit.bitwarden.R
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.platform.manager.PolicyManager
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.tools.generator.repository.model.GeneratedCatchAllUsernameResult
import com.x8bit.bitwarden.data.tools.generator.repository.model.GeneratedForwardedServiceUsernameResult
@ -201,6 +201,8 @@ class GeneratorViewModelTest : BaseViewModelTest() {
@Test
fun `RegenerateClick action for passphrase state updates generatedText and saves passphrase generation options on successful passphrase generation`() =
runTest {
setupMockPassphraseTypePolicy()
val updatedGeneratedPassphrase = "updatedPassphrase"
val viewModel = createViewModel(initialPassphraseState)
@ -242,6 +244,8 @@ class GeneratorViewModelTest : BaseViewModelTest() {
@Test
fun `RegenerateClick action for passphrase state sends ShowSnackbar event on passphrase generation failure`() =
runTest {
setupMockPassphraseTypePolicy()
val viewModel = createViewModel(initialPassphraseState)
fakeGeneratorRepository.setMockGeneratePassphraseResult(
@ -1035,6 +1039,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
@BeforeEach
fun setup() {
setupMockPassphraseTypePolicy()
fakeGeneratorRepository.setMockGeneratePasswordResult(
GeneratedPasswordResult.Success("defaultPassphrase"),
)
@ -1900,6 +1905,24 @@ class GeneratorViewModelTest : BaseViewModelTest() {
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
}