mirror of
https://github.com/bitwarden/android.git
synced 2025-03-15 10:48:47 +03:00
Add clearData calls DiskSources (#603)
This commit is contained in:
parent
67d7b7a9f5
commit
f1b9ded3e3
12 changed files with 161 additions and 12 deletions
|
@ -31,6 +31,13 @@ interface AuthDiskSource {
|
|||
*/
|
||||
val userStateFlow: Flow<UserStateJson?>
|
||||
|
||||
/**
|
||||
* Clears all the settings data for the given user.
|
||||
*
|
||||
* Note that this does not include any data saved in the [userState].
|
||||
*/
|
||||
fun clearData(userId: String)
|
||||
|
||||
/**
|
||||
* Retrieves the "last active time" for the given [userId], in milliseconds.
|
||||
*
|
||||
|
|
|
@ -67,6 +67,17 @@ class AuthDiskSourceImpl(
|
|||
get() = mutableUserStateFlow
|
||||
.onSubscription { emit(userState) }
|
||||
|
||||
private val mutableUserStateFlow = bufferedMutableSharedFlow<UserStateJson?>(replay = 1)
|
||||
|
||||
override fun clearData(userId: String) {
|
||||
storeLastActiveTimeMillis(userId = userId, lastActiveTimeMillis = null)
|
||||
storeUserKey(userId = userId, userKey = null)
|
||||
storeUserAutoUnlockKey(userId = userId, userAutoUnlockKey = null)
|
||||
storePrivateKey(userId = userId, privateKey = null)
|
||||
storeOrganizationKeys(userId = userId, organizationKeys = null)
|
||||
storeOrganizations(userId = userId, organizations = null)
|
||||
}
|
||||
|
||||
override fun getLastActiveTimeMillis(userId: String): Long? =
|
||||
getLong(key = "${LAST_ACTIVE_TIME_KEY}_$userId")
|
||||
|
||||
|
@ -80,8 +91,6 @@ class AuthDiskSourceImpl(
|
|||
)
|
||||
}
|
||||
|
||||
private val mutableUserStateFlow = bufferedMutableSharedFlow<UserStateJson?>(replay = 1)
|
||||
|
||||
override fun getUserKey(userId: String): String? =
|
||||
getString(key = "${MASTER_KEY_ENCRYPTION_USER_KEY}_$userId")
|
||||
|
||||
|
|
|
@ -13,6 +13,11 @@ interface SettingsDiskSource {
|
|||
*/
|
||||
var appLanguage: AppLanguage?
|
||||
|
||||
/**
|
||||
* Clears all the settings data for the given user.
|
||||
*/
|
||||
fun clearData(userId: String)
|
||||
|
||||
/**
|
||||
* Gets the current vault timeout (in minutes) for the given [userId] (or `null` if the vault
|
||||
* should never time out).
|
||||
|
|
|
@ -39,6 +39,11 @@ class SettingsDiskSourceImpl(
|
|||
)
|
||||
}
|
||||
|
||||
override fun clearData(userId: String) {
|
||||
storeVaultTimeoutInMinutes(userId = userId, vaultTimeoutInMinutes = null)
|
||||
storeVaultTimeoutAction(userId = userId, vaultTimeoutAction = null)
|
||||
}
|
||||
|
||||
override fun getVaultTimeoutInMinutes(userId: String): Int? =
|
||||
getInt(key = "${VAULT_TIME_IN_MINUTES_KEY}_$userId")
|
||||
|
||||
|
|
|
@ -59,16 +59,7 @@ class SettingsRepositoryImpl(
|
|||
}
|
||||
|
||||
override fun clearData(userId: String) {
|
||||
settingsDiskSource.apply {
|
||||
storeVaultTimeoutInMinutes(
|
||||
userId = userId,
|
||||
vaultTimeoutInMinutes = null,
|
||||
)
|
||||
storeVaultTimeoutAction(
|
||||
userId = userId,
|
||||
vaultTimeoutAction = null,
|
||||
)
|
||||
}
|
||||
settingsDiskSource.clearData(userId = userId)
|
||||
}
|
||||
|
||||
override fun setDefaultsIfNecessary(userId: String) {
|
||||
|
|
|
@ -7,6 +7,10 @@ import com.x8bit.bitwarden.data.tools.generator.repository.model.UsernameGenerat
|
|||
* Primary access point for disk information related to generation.
|
||||
*/
|
||||
interface GeneratorDiskSource {
|
||||
/**
|
||||
* Clears all the settings data for the given user.
|
||||
*/
|
||||
fun clearData(userId: String)
|
||||
|
||||
/**
|
||||
* Retrieves a user's passcode generation options using a [userId].
|
||||
|
|
|
@ -19,6 +19,11 @@ class GeneratorDiskSourceImpl(
|
|||
) : BaseDiskSource(sharedPreferences),
|
||||
GeneratorDiskSource {
|
||||
|
||||
override fun clearData(userId: String) {
|
||||
storePasscodeGenerationOptions(userId = userId, options = null)
|
||||
storeUsernameGenerationOptions(userId = userId, options = null)
|
||||
}
|
||||
|
||||
override fun getPasscodeGenerationOptions(userId: String): PasscodeGenerationOptions? {
|
||||
val key = getPasswordGenerationOptionsKey(userId)
|
||||
return getString(key)?.let { json.decodeFromString(it) }
|
||||
|
|
|
@ -118,6 +118,39 @@ class AuthDiskSourceTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `clearData should clear all necessary data for the given user`() {
|
||||
val userId = "userId"
|
||||
|
||||
authDiskSource.storeLastActiveTimeMillis(
|
||||
userId = userId,
|
||||
lastActiveTimeMillis = 123456789L,
|
||||
)
|
||||
authDiskSource.storeUserKey(userId = userId, userKey = "userKey")
|
||||
authDiskSource.storeUserAutoUnlockKey(
|
||||
userId = userId,
|
||||
userAutoUnlockKey = "userAutoUnlockKey",
|
||||
)
|
||||
authDiskSource.storePrivateKey(userId = userId, privateKey = "privateKey")
|
||||
authDiskSource.storeOrganizationKeys(
|
||||
userId = userId,
|
||||
organizationKeys = mapOf("organizationId" to "key"),
|
||||
)
|
||||
authDiskSource.storeOrganizations(
|
||||
userId = userId,
|
||||
organizations = listOf(createMockOrganization(1)),
|
||||
)
|
||||
|
||||
authDiskSource.clearData(userId = userId)
|
||||
|
||||
assertNull(authDiskSource.getLastActiveTimeMillis(userId = userId))
|
||||
assertNull(authDiskSource.getUserKey(userId = userId))
|
||||
assertNull(authDiskSource.getUserAutoUnlockKey(userId = userId))
|
||||
assertNull(authDiskSource.getPrivateKey(userId = userId))
|
||||
assertNull(authDiskSource.getOrganizationKeys(userId = userId))
|
||||
assertNull(authDiskSource.getOrganizations(userId = userId))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getLastActiveTimeMillis should pull from SharedPreferences`() {
|
||||
val lastActiveTimeBaseKey = "bwPreferencesStorage:lastActiveTime"
|
||||
|
|
|
@ -36,6 +36,17 @@ class FakeAuthDiskSource : AuthDiskSource {
|
|||
override val userStateFlow: Flow<UserStateJson?>
|
||||
get() = mutableUserStateFlow.onSubscription { emit(userState) }
|
||||
|
||||
override fun clearData(userId: String) {
|
||||
storedLastActiveTimeMillis.remove(userId)
|
||||
storedUserKeys.remove(userId)
|
||||
storedPrivateKeys.remove(userId)
|
||||
storedUserAutoUnlockKeys.remove(userId)
|
||||
storedOrganizations.remove(userId)
|
||||
|
||||
storedOrganizationKeys.remove(userId)
|
||||
mutableOrganizationsFlowMap.remove(userId)
|
||||
}
|
||||
|
||||
override fun getLastActiveTimeMillis(userId: String): Long? =
|
||||
storedLastActiveTimeMillis[userId]
|
||||
|
||||
|
|
|
@ -58,6 +58,24 @@ class SettingsDiskSourceTest {
|
|||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `clearData should clear all necessary data for the given user`() {
|
||||
val userId = "userId"
|
||||
settingsDiskSource.storeVaultTimeoutInMinutes(
|
||||
userId = userId,
|
||||
vaultTimeoutInMinutes = 30,
|
||||
)
|
||||
settingsDiskSource.storeVaultTimeoutAction(
|
||||
userId = userId,
|
||||
vaultTimeoutAction = VaultTimeoutAction.LOCK,
|
||||
)
|
||||
|
||||
settingsDiskSource.clearData(userId = userId)
|
||||
|
||||
assertNull(settingsDiskSource.getVaultTimeoutInMinutes(userId = userId))
|
||||
assertNull(settingsDiskSource.getVaultTimeoutAction(userId = userId))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getVaultTimeoutInMinutes when values are present should pull from SharedPreferences`() {
|
||||
val vaultTimeoutBaseKey = "bwPreferencesStorage:vaultTimeout"
|
||||
|
|
|
@ -24,6 +24,14 @@ class FakeSettingsDiskSource : SettingsDiskSource {
|
|||
|
||||
override var appLanguage: AppLanguage? = null
|
||||
|
||||
override fun clearData(userId: String) {
|
||||
storedVaultTimeoutActions.remove(userId)
|
||||
storedVaultTimeoutInMinutes.remove(userId)
|
||||
|
||||
mutableVaultTimeoutActionsFlowMap.remove(userId)
|
||||
mutableVaultTimeoutInMinutesFlowMap.remove(userId)
|
||||
}
|
||||
|
||||
override fun getVaultTimeoutInMinutes(userId: String): Int? =
|
||||
storedVaultTimeoutInMinutes[userId]
|
||||
|
||||
|
|
|
@ -25,6 +25,59 @@ class GeneratorDiskSourceTest {
|
|||
json = json,
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `clearData should clear all necessary data for the given user`() {
|
||||
val userId = "userId"
|
||||
|
||||
val passcodeOptions = PasscodeGenerationOptions(
|
||||
length = 14,
|
||||
allowAmbiguousChar = false,
|
||||
hasNumbers = true,
|
||||
minNumber = 0,
|
||||
hasUppercase = true,
|
||||
minUppercase = null,
|
||||
hasLowercase = false,
|
||||
minLowercase = null,
|
||||
allowSpecial = false,
|
||||
minSpecial = 1,
|
||||
allowCapitalize = false,
|
||||
allowIncludeNumber = false,
|
||||
wordSeparator = "-",
|
||||
numWords = 3,
|
||||
)
|
||||
val userNameOptions = UsernameGenerationOptions(
|
||||
type = UsernameGenerationOptions.UsernameType.RANDOM_WORD,
|
||||
serviceType = UsernameGenerationOptions.ForwardedEmailServiceType.NONE,
|
||||
capitalizeRandomWordUsername = true,
|
||||
includeNumberRandomWordUsername = false,
|
||||
plusAddressedEmail = "example+plus@gmail.com",
|
||||
catchAllEmailDomain = "example.com",
|
||||
firefoxRelayApiAccessToken = "access_token_firefox_relay",
|
||||
simpleLoginApiKey = "api_key_simple_login",
|
||||
duckDuckGoApiKey = "api_key_duck_duck_go",
|
||||
fastMailApiKey = "api_key_fast_mail",
|
||||
anonAddyApiAccessToken = "access_token_anon_addy",
|
||||
anonAddyDomainName = "anonaddy.com",
|
||||
forwardEmailApiAccessToken = "access_token_forward_email",
|
||||
forwardEmailDomainName = "forwardemail.net",
|
||||
emailWebsite = "email.example.com",
|
||||
)
|
||||
|
||||
generatorDiskSource.storePasscodeGenerationOptions(
|
||||
userId = userId,
|
||||
options = passcodeOptions,
|
||||
)
|
||||
generatorDiskSource.storeUsernameGenerationOptions(
|
||||
userId = userId,
|
||||
options = userNameOptions,
|
||||
)
|
||||
|
||||
generatorDiskSource.clearData(userId = userId)
|
||||
|
||||
assertNull(generatorDiskSource.getPasscodeGenerationOptions(userId = userId))
|
||||
assertNull(generatorDiskSource.getUsernameGenerationOptions(userId = userId))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getPasscodeGenerationOptions should return correct options when available`() {
|
||||
val userId = "user123"
|
||||
|
|
Loading…
Add table
Reference in a new issue