mirror of
https://github.com/bitwarden/android.git
synced 2025-02-22 08:39:01 +03:00
[PM-16670] Add check for 2fa status (#4542)
This commit is contained in:
parent
08d173e8e1
commit
ac80d662d5
6 changed files with 79 additions and 49 deletions
app/src
main/java/com/x8bit/bitwarden
data/auth/repository
ui/auth/feature/newdevicenotice
test/java/com/x8bit/bitwarden
data/auth/repository
ui/auth/feature/newdevicenotice
|
@ -1350,7 +1350,6 @@ class AuthRepositoryImpl(
|
|||
}
|
||||
|
||||
override fun checkUserNeedsNewDeviceTwoFactorNotice(): Boolean {
|
||||
vaultRepository.syncIfNecessary()
|
||||
return activeUserId?.let { userId ->
|
||||
val temporaryFlag = featureFlagManager.getFeatureFlag(FlagKey.NewDeviceTemporaryDismiss)
|
||||
val permanentFlag = featureFlagManager.getFeatureFlag(FlagKey.NewDevicePermanentDismiss)
|
||||
|
|
|
@ -2,12 +2,14 @@ package com.x8bit.bitwarden.ui.auth.feature.newdevicenotice
|
|||
|
||||
import android.os.Parcelable
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.NewDeviceNoticeDisplayStatus.CAN_ACCESS_EMAIL
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.NewDeviceNoticeDisplayStatus.CAN_ACCESS_EMAIL_PERMANENT
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.NewDeviceNoticeState
|
||||
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
|
||||
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.model.FlagKey
|
||||
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
|
||||
import com.x8bit.bitwarden.ui.auth.feature.newdevicenotice.NewDeviceNoticeEmailAccessAction.ContinueClick
|
||||
import com.x8bit.bitwarden.ui.auth.feature.newdevicenotice.NewDeviceNoticeEmailAccessAction.EmailAccessToggle
|
||||
import com.x8bit.bitwarden.ui.auth.feature.newdevicenotice.NewDeviceNoticeEmailAccessAction.LearnMoreClick
|
||||
|
@ -15,6 +17,7 @@ import com.x8bit.bitwarden.ui.auth.feature.newdevicenotice.NewDeviceNoticeEmailA
|
|||
import com.x8bit.bitwarden.ui.platform.base.BaseViewModel
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -26,6 +29,7 @@ private const val KEY_STATE = "state"
|
|||
@HiltViewModel
|
||||
class NewDeviceNoticeEmailAccessViewModel @Inject constructor(
|
||||
private val authRepository: AuthRepository,
|
||||
private val vaultRepository: VaultRepository,
|
||||
private val featureFlagManager: FeatureFlagManager,
|
||||
savedStateHandle: SavedStateHandle,
|
||||
) : BaseViewModel<
|
||||
|
@ -39,6 +43,15 @@ class NewDeviceNoticeEmailAccessViewModel @Inject constructor(
|
|||
isEmailAccessEnabled = false,
|
||||
),
|
||||
) {
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
vaultRepository.syncForResult()
|
||||
if (!authRepository.checkUserNeedsNewDeviceTwoFactorNotice()) {
|
||||
sendEvent(NewDeviceNoticeEmailAccessEvent.NavigateBackToVault)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun handleAction(action: NewDeviceNoticeEmailAccessAction) {
|
||||
when (action) {
|
||||
ContinueClick -> handleContinueClick()
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.x8bit.bitwarden.ui.auth.feature.newdevicenotice
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.NewDeviceNoticeDisplayStatus
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.NewDeviceNoticeState
|
||||
|
@ -10,6 +11,7 @@ import com.x8bit.bitwarden.data.platform.manager.model.FlagKey
|
|||
import com.x8bit.bitwarden.data.platform.repository.EnvironmentRepository
|
||||
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
|
||||
import com.x8bit.bitwarden.data.platform.repository.util.baseWebVaultUrlOrDefault
|
||||
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
|
||||
import com.x8bit.bitwarden.ui.auth.feature.newdevicenotice.NewDeviceNoticeTwoFactorAction.ChangeAccountEmailClick
|
||||
import com.x8bit.bitwarden.ui.auth.feature.newdevicenotice.NewDeviceNoticeTwoFactorAction.ContinueDialogClick
|
||||
import com.x8bit.bitwarden.ui.auth.feature.newdevicenotice.NewDeviceNoticeTwoFactorAction.DismissDialogClick
|
||||
|
@ -22,6 +24,7 @@ import com.x8bit.bitwarden.ui.platform.base.util.Text
|
|||
import com.x8bit.bitwarden.ui.platform.base.util.asText
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import java.time.Clock
|
||||
import java.time.ZonedDateTime
|
||||
|
@ -36,6 +39,7 @@ class NewDeviceNoticeTwoFactorViewModel @Inject constructor(
|
|||
val environmentRepository: EnvironmentRepository,
|
||||
val featureFlagManager: FeatureFlagManager,
|
||||
val settingsRepository: SettingsRepository,
|
||||
val vaultRepository: VaultRepository,
|
||||
private val clock: Clock,
|
||||
) : BaseViewModel<
|
||||
NewDeviceNoticeTwoFactorState,
|
||||
|
@ -48,6 +52,15 @@ class NewDeviceNoticeTwoFactorViewModel @Inject constructor(
|
|||
),
|
||||
),
|
||||
) {
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
vaultRepository.syncForResult()
|
||||
if (!authRepository.checkUserNeedsNewDeviceTwoFactorNotice()) {
|
||||
sendEvent(NewDeviceNoticeTwoFactorEvent.NavigateBackToVault)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val webTwoFactorUrl: String
|
||||
get() {
|
||||
val baseUrl = environmentRepository
|
||||
|
|
|
@ -170,7 +170,6 @@ class AuthRepositoryTest {
|
|||
private val vaultRepository: VaultRepository = mockk {
|
||||
every { vaultUnlockDataStateFlow } returns mutableVaultUnlockDataStateFlow
|
||||
every { deleteVaultData(any()) } just runs
|
||||
every { syncIfNecessary() } just runs
|
||||
}
|
||||
private val fakeAuthDiskSource = FakeAuthDiskSource()
|
||||
private val fakeEnvironmentRepository =
|
||||
|
@ -6543,9 +6542,6 @@ class AuthRepositoryTest {
|
|||
|
||||
val shouldShowNewDeviceNotice = repository.checkUserNeedsNewDeviceTwoFactorNotice()
|
||||
|
||||
verify(exactly = 1) {
|
||||
vaultRepository.syncIfNecessary()
|
||||
}
|
||||
assertTrue(shouldShowNewDeviceNotice)
|
||||
}
|
||||
|
||||
|
@ -6568,9 +6564,6 @@ class AuthRepositoryTest {
|
|||
|
||||
val shouldShowNewDeviceNotice = repository.checkUserNeedsNewDeviceTwoFactorNotice()
|
||||
|
||||
verify(exactly = 1) {
|
||||
vaultRepository.syncIfNecessary()
|
||||
}
|
||||
assertFalse(shouldShowNewDeviceNotice)
|
||||
}
|
||||
|
||||
|
@ -6592,9 +6585,6 @@ class AuthRepositoryTest {
|
|||
|
||||
val shouldShowNewDeviceNotice = repository.checkUserNeedsNewDeviceTwoFactorNotice()
|
||||
|
||||
verify(exactly = 1) {
|
||||
vaultRepository.syncIfNecessary()
|
||||
}
|
||||
assertTrue(shouldShowNewDeviceNotice)
|
||||
}
|
||||
|
||||
|
@ -6613,9 +6603,6 @@ class AuthRepositoryTest {
|
|||
|
||||
val shouldShowNewDeviceNotice = repository.checkUserNeedsNewDeviceTwoFactorNotice()
|
||||
|
||||
verify(exactly = 1) {
|
||||
vaultRepository.syncIfNecessary()
|
||||
}
|
||||
assertFalse(shouldShowNewDeviceNotice)
|
||||
}
|
||||
|
||||
|
@ -6636,9 +6623,6 @@ class AuthRepositoryTest {
|
|||
|
||||
val shouldShowNewDeviceNotice = repository.checkUserNeedsNewDeviceTwoFactorNotice()
|
||||
|
||||
verify(exactly = 1) {
|
||||
vaultRepository.syncIfNecessary()
|
||||
}
|
||||
assertFalse(shouldShowNewDeviceNotice)
|
||||
}
|
||||
|
||||
|
@ -6654,9 +6638,6 @@ class AuthRepositoryTest {
|
|||
|
||||
val shouldShowNewDeviceNotice = repository.checkUserNeedsNewDeviceTwoFactorNotice()
|
||||
|
||||
verify(exactly = 1) {
|
||||
vaultRepository.syncIfNecessary()
|
||||
}
|
||||
assertFalse(shouldShowNewDeviceNotice)
|
||||
}
|
||||
|
||||
|
@ -6682,9 +6663,6 @@ class AuthRepositoryTest {
|
|||
|
||||
val shouldShowNewDeviceNotice = repository.checkUserNeedsNewDeviceTwoFactorNotice()
|
||||
|
||||
verify(exactly = 1) {
|
||||
vaultRepository.syncIfNecessary()
|
||||
}
|
||||
assertFalse(shouldShowNewDeviceNotice)
|
||||
}
|
||||
|
||||
|
@ -6708,9 +6686,6 @@ class AuthRepositoryTest {
|
|||
|
||||
val shouldShowNewDeviceNotice = repository.checkUserNeedsNewDeviceTwoFactorNotice()
|
||||
|
||||
verify(exactly = 1) {
|
||||
vaultRepository.syncIfNecessary()
|
||||
}
|
||||
assertFalse(shouldShowNewDeviceNotice)
|
||||
}
|
||||
|
||||
|
@ -6734,9 +6709,6 @@ class AuthRepositoryTest {
|
|||
|
||||
val shouldShowNewDeviceNotice = repository.checkUserNeedsNewDeviceTwoFactorNotice()
|
||||
|
||||
verify(exactly = 1) {
|
||||
vaultRepository.syncIfNecessary()
|
||||
}
|
||||
assertTrue(shouldShowNewDeviceNotice)
|
||||
}
|
||||
|
||||
|
@ -6760,9 +6732,6 @@ class AuthRepositoryTest {
|
|||
|
||||
val shouldShowNewDeviceNotice = repository.checkUserNeedsNewDeviceTwoFactorNotice()
|
||||
|
||||
verify(exactly = 1) {
|
||||
vaultRepository.syncIfNecessary()
|
||||
}
|
||||
assertTrue(shouldShowNewDeviceNotice)
|
||||
}
|
||||
|
||||
|
@ -6786,9 +6755,6 @@ class AuthRepositoryTest {
|
|||
|
||||
val shouldShowNewDeviceNotice = repository.checkUserNeedsNewDeviceTwoFactorNotice()
|
||||
|
||||
verify(exactly = 1) {
|
||||
vaultRepository.syncIfNecessary()
|
||||
}
|
||||
assertFalse(shouldShowNewDeviceNotice)
|
||||
}
|
||||
|
||||
|
@ -6817,9 +6783,6 @@ class AuthRepositoryTest {
|
|||
} returns false
|
||||
|
||||
assertFalse(repository.checkUserNeedsNewDeviceTwoFactorNotice())
|
||||
verify(exactly = 2) {
|
||||
vaultRepository.syncIfNecessary()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -6833,9 +6796,6 @@ class AuthRepositoryTest {
|
|||
fakeAuthDiskSource.userState = null
|
||||
|
||||
assertFalse(repository.checkUserNeedsNewDeviceTwoFactorNotice())
|
||||
verify(exactly = 1) {
|
||||
vaultRepository.syncIfNecessary()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -6857,10 +6817,6 @@ class AuthRepositoryTest {
|
|||
),
|
||||
)
|
||||
assertFalse(repository.checkUserNeedsNewDeviceTwoFactorNotice())
|
||||
|
||||
verify(exactly = 1) {
|
||||
vaultRepository.syncIfNecessary()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -6884,9 +6840,6 @@ class AuthRepositoryTest {
|
|||
)
|
||||
|
||||
assertTrue(repository.checkUserNeedsNewDeviceTwoFactorNotice())
|
||||
verify(exactly = 1) {
|
||||
vaultRepository.syncIfNecessary()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -7,6 +7,7 @@ import com.x8bit.bitwarden.data.auth.datasource.disk.model.NewDeviceNoticeState
|
|||
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
|
||||
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.model.FlagKey
|
||||
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
|
||||
import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest
|
||||
import io.mockk.every
|
||||
import io.mockk.just
|
||||
|
@ -32,6 +33,8 @@ class NewDeviceNoticeEmailAccessViewModelTest : BaseViewModelTest() {
|
|||
every { getFeatureFlag(FlagKey.NewDeviceTemporaryDismiss) } returns true
|
||||
}
|
||||
|
||||
private val vaultRepository = mockk<VaultRepository>(relaxed = true)
|
||||
|
||||
@Test
|
||||
fun `initial state should be correct with email from state handle`() = runTest {
|
||||
val viewModel = createViewModel()
|
||||
|
@ -40,6 +43,27 @@ class NewDeviceNoticeEmailAccessViewModelTest : BaseViewModelTest() {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Init should not send events if user needs new device notice`() = runTest {
|
||||
every { authRepository.checkUserNeedsNewDeviceTwoFactorNotice() } returns true
|
||||
val viewModel = createViewModel()
|
||||
viewModel.eventFlow.test {
|
||||
expectNoEvents()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Init should send NavigateBackToVault if user does not need new device notice`() = runTest {
|
||||
every { authRepository.checkUserNeedsNewDeviceTwoFactorNotice() } returns false
|
||||
val viewModel = createViewModel()
|
||||
viewModel.eventFlow.test {
|
||||
assertEquals(
|
||||
NewDeviceNoticeEmailAccessEvent.NavigateBackToVault,
|
||||
awaitItem(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `EmailAccessToggle should update value of isEmailAccessEnabled`() = runTest {
|
||||
val viewModel = createViewModel()
|
||||
|
@ -127,6 +151,7 @@ class NewDeviceNoticeEmailAccessViewModelTest : BaseViewModelTest() {
|
|||
): NewDeviceNoticeEmailAccessViewModel = NewDeviceNoticeEmailAccessViewModel(
|
||||
authRepository = authRepository,
|
||||
featureFlagManager = featureFlagManager,
|
||||
vaultRepository = vaultRepository,
|
||||
savedStateHandle = savedStateHandle,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
|
|||
import com.x8bit.bitwarden.data.platform.manager.model.FlagKey
|
||||
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
|
||||
import com.x8bit.bitwarden.data.platform.repository.util.FakeEnvironmentRepository
|
||||
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
|
||||
import com.x8bit.bitwarden.ui.auth.feature.newdevicenotice.NewDeviceNoticeTwoFactorDialogState.ChangeAccountEmailDialog
|
||||
import com.x8bit.bitwarden.ui.auth.feature.newdevicenotice.NewDeviceNoticeTwoFactorDialogState.TurnOnTwoFactorDialog
|
||||
import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest
|
||||
|
@ -24,7 +25,9 @@ import java.time.ZonedDateTime
|
|||
|
||||
class NewDeviceNoticeTwoFactorViewModelTest : BaseViewModelTest() {
|
||||
private val environmentRepository = FakeEnvironmentRepository()
|
||||
private val authRepository = mockk<AuthRepository>(relaxed = true)
|
||||
private val authRepository = mockk<AuthRepository>(relaxed = true) {
|
||||
every { checkUserNeedsNewDeviceTwoFactorNotice() } returns true
|
||||
}
|
||||
|
||||
private val featureFlagManager = mockk<FeatureFlagManager>(relaxed = true) {
|
||||
every { getFeatureFlag(FlagKey.NewDevicePermanentDismiss) } returns false
|
||||
|
@ -33,6 +36,8 @@ class NewDeviceNoticeTwoFactorViewModelTest : BaseViewModelTest() {
|
|||
|
||||
private val settingsRepository = mockk<SettingsRepository>(relaxed = true)
|
||||
|
||||
private val vaultRepository = mockk<VaultRepository>(relaxed = true)
|
||||
|
||||
@Test
|
||||
fun `initial state should be correct with NewDevicePermanentDismiss flag false`() = runTest {
|
||||
val viewModel = createViewModel()
|
||||
|
@ -53,6 +58,27 @@ class NewDeviceNoticeTwoFactorViewModelTest : BaseViewModelTest() {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Init should not send events if user needs new device notice`() = runTest {
|
||||
every { authRepository.checkUserNeedsNewDeviceTwoFactorNotice() } returns true
|
||||
val viewModel = createViewModel()
|
||||
viewModel.eventFlow.test {
|
||||
expectNoEvents()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Init should send NavigateBackToVault if user does not need new device notice`() = runTest {
|
||||
every { authRepository.checkUserNeedsNewDeviceTwoFactorNotice() } returns false
|
||||
val viewModel = createViewModel()
|
||||
viewModel.eventFlow.test {
|
||||
assertEquals(
|
||||
NewDeviceNoticeTwoFactorEvent.NavigateBackToVault,
|
||||
awaitItem(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `initial state should be correct with email from state handle`() = runTest {
|
||||
val viewModel = createViewModel()
|
||||
|
@ -187,6 +213,7 @@ class NewDeviceNoticeTwoFactorViewModelTest : BaseViewModelTest() {
|
|||
environmentRepository = environmentRepository,
|
||||
featureFlagManager = featureFlagManager,
|
||||
settingsRepository = settingsRepository,
|
||||
vaultRepository = vaultRepository,
|
||||
clock = FIXED_CLOCK,
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue