From 1d85bbc2fcd25eb99fcaf94a5302b9ea91b2dc0c Mon Sep 17 00:00:00 2001 From: Brian Yencho Date: Sun, 7 Jan 2024 16:46:12 -0600 Subject: [PATCH] Add SettingsRepository helpers for the current user (#525) --- .../platform/repository/SettingsRepository.kt | 10 +++ .../repository/SettingsRepositoryImpl.kt | 32 +++++++ .../repository/SettingsRepositoryTest.kt | 84 ++++++++++++++++++- 3 files changed, 122 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepository.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepository.kt index da2ed535b7..5015af6e43 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepository.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepository.kt @@ -8,6 +8,16 @@ import kotlinx.coroutines.flow.StateFlow * Provides an API for observing and modifying settings state. */ interface SettingsRepository { + /** + * The [VaultTimeout] for the current user. + */ + var vaultTimeout: VaultTimeout + + /** + * The [VaultTimeoutAction] for the current user. + */ + var vaultTimeoutAction: VaultTimeoutAction + /** * Gets updates for the [VaultTimeout] associated with the given [userId]. */ diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryImpl.kt index 1c5db73840..94f9709ff4 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryImpl.kt @@ -1,5 +1,6 @@ package com.x8bit.bitwarden.data.platform.repository +import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource import com.x8bit.bitwarden.data.platform.datasource.disk.SettingsDiskSource import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeout @@ -14,11 +15,42 @@ import kotlinx.coroutines.flow.stateIn * Primary implementation of [SettingsRepository]. */ class SettingsRepositoryImpl( + private val authDiskSource: AuthDiskSource, private val settingsDiskSource: SettingsDiskSource, private val dispatcherManager: DispatcherManager, ) : SettingsRepository { + private val activeUserId: String? get() = authDiskSource.userState?.activeUserId + private val unconfinedScope = CoroutineScope(dispatcherManager.unconfined) + override var vaultTimeout: VaultTimeout + get() = activeUserId + ?.let { + getVaultTimeoutStateFlow(userId = it).value + } + ?: VaultTimeout.Never + set(value) { + val userId = activeUserId ?: return + storeVaultTimeout( + userId = userId, + vaultTimeout = value, + ) + } + + override var vaultTimeoutAction: VaultTimeoutAction + get() = activeUserId + ?.let { + getVaultTimeoutActionStateFlow(userId = it).value + } + .orDefault() + set(value) { + val userId = activeUserId ?: return + storeVaultTimeoutAction( + userId = userId, + vaultTimeoutAction = value, + ) + } + override fun getVaultTimeoutStateFlow(userId: String): StateFlow = settingsDiskSource .getVaultTimeoutInMinutesFlow(userId = userId) diff --git a/app/src/test/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryTest.kt index 4e66737fd0..4d3a18f75c 100644 --- a/app/src/test/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryTest.kt @@ -1,10 +1,13 @@ package com.x8bit.bitwarden.data.platform.repository import app.cash.turbine.test +import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource import com.x8bit.bitwarden.data.platform.base.FakeDispatcherManager import com.x8bit.bitwarden.data.platform.datasource.disk.util.FakeSettingsDiskSource import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeout import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeoutAction +import io.mockk.every +import io.mockk.mockk import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertFalse @@ -12,13 +15,81 @@ import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test class SettingsRepositoryTest { + private val authDiskSource: AuthDiskSource = mockk() private val fakeSettingsDiskSource = FakeSettingsDiskSource() private val settingsRepository = SettingsRepositoryImpl( + authDiskSource = authDiskSource, settingsDiskSource = fakeSettingsDiskSource, dispatcherManager = FakeDispatcherManager(), ) + @Test + fun `vaultTimeout should pull from and update SettingsDiskSource for the current user`() { + every { authDiskSource.userState?.activeUserId } returns null + assertEquals( + VaultTimeout.Never, + settingsRepository.vaultTimeout, + ) + + val userId = "userId" + every { authDiskSource.userState?.activeUserId } returns userId + + // Updates to the disk source change the repository value + VAULT_TIMEOUT_MAP.forEach { (vaultTimeout, vaultTimeoutInMinutes) -> + fakeSettingsDiskSource.storeVaultTimeoutInMinutes( + userId = userId, + vaultTimeoutInMinutes = vaultTimeoutInMinutes, + ) + assertEquals( + vaultTimeout, + settingsRepository.vaultTimeout, + ) + } + + // Updates to the repository value change the disk source + VAULT_TIMEOUT_MAP.forEach { (vaultTimeout, vaultTimeoutInMinutes) -> + settingsRepository.vaultTimeout = vaultTimeout + assertEquals( + vaultTimeoutInMinutes, + fakeSettingsDiskSource.getVaultTimeoutInMinutes(userId = userId), + ) + } + } + + @Test + fun `vaultTimeoutAction should pull from and update SettingsDiskSource`() { + every { authDiskSource.userState?.activeUserId } returns null + assertEquals( + VaultTimeoutAction.LOCK, + settingsRepository.vaultTimeoutAction, + ) + + val userId = "userId" + every { authDiskSource.userState?.activeUserId } returns userId + + // Updates to the disk source change the repository value + VAULT_TIMEOUT_ACTIONS.forEach { vaultTimeoutAction -> + fakeSettingsDiskSource.storeVaultTimeoutAction( + userId = userId, + vaultTimeoutAction = vaultTimeoutAction, + ) + assertEquals( + vaultTimeoutAction, + settingsRepository.vaultTimeoutAction, + ) + } + + // Updates to the repository value change the disk source + VAULT_TIMEOUT_ACTIONS.forEach { vaultTimeoutAction -> + settingsRepository.vaultTimeoutAction = vaultTimeoutAction + assertEquals( + vaultTimeoutAction, + fakeSettingsDiskSource.getVaultTimeoutAction(userId = userId), + ) + } + } + @Test fun `getVaultTimeoutStateFlow should react to changes in SettingsDiskSource`() = runTest { val userId = "userId" @@ -67,9 +138,7 @@ class SettingsRepositoryTest { VaultTimeoutAction.LOCK, awaitItem(), ) - // Reverse the order of the entries to ensure the first value differs from the - // default. - VaultTimeoutAction.entries.reversed().forEach { vaultTimeoutAction -> + VAULT_TIMEOUT_ACTIONS.forEach { vaultTimeoutAction -> fakeSettingsDiskSource.storeVaultTimeoutAction( userId = userId, vaultTimeoutAction = vaultTimeoutAction, @@ -105,7 +174,7 @@ class SettingsRepositoryTest { @Test fun `storeVaultTimeoutAction should properly update SettingsDiskSource`() { val userId = "userId" - VaultTimeoutAction.entries.forEach { vaultTimeoutAction -> + VAULT_TIMEOUT_ACTIONS.forEach { vaultTimeoutAction -> settingsRepository.storeVaultTimeoutAction( userId = userId, vaultTimeoutAction = vaultTimeoutAction, @@ -118,6 +187,13 @@ class SettingsRepositoryTest { } } +/** + * A list of all [VaultTimeoutAction]. + * + * The order is reversed here in order to ensure that the first value differs from the default. + */ +private val VAULT_TIMEOUT_ACTIONS = VaultTimeoutAction.entries.reversed() + /** * Maps a VaultTimeout to its expected vaultTimeoutInMinutes value. */