mirror of
https://github.com/bitwarden/android.git
synced 2025-12-10 09:56:45 -06:00
PM-28355: Clear pin data on hard-logout or security stamp (#6232)
This commit is contained in:
parent
28db795790
commit
2eb8ad4221
@ -159,11 +159,11 @@ class AuthDiskSourceImpl(
|
|||||||
storeAuthenticatorSyncUnlockKey(userId = userId, authenticatorSyncUnlockKey = null)
|
storeAuthenticatorSyncUnlockKey(userId = userId, authenticatorSyncUnlockKey = null)
|
||||||
storeShowImportLogins(userId = userId, showImportLogins = null)
|
storeShowImportLogins(userId = userId, showImportLogins = null)
|
||||||
storeLastLockTimestamp(userId = userId, lastLockTimestamp = null)
|
storeLastLockTimestamp(userId = userId, lastLockTimestamp = null)
|
||||||
|
storeEncryptedPin(userId = userId, encryptedPin = null)
|
||||||
|
storePinProtectedUserKey(userId = userId, pinProtectedUserKey = null)
|
||||||
|
storePinProtectedUserKeyEnvelope(userId = userId, pinProtectedUserKeyEnvelope = null)
|
||||||
|
|
||||||
// Certain values are never removed as required by the feature requirements:
|
// Certain values are never removed as required by the feature requirements:
|
||||||
// * EncryptedPin
|
|
||||||
// * PinProtectedUserKey
|
|
||||||
// * PinProtectedUserKeyEnvelope
|
|
||||||
// * DeviceKey
|
// * DeviceKey
|
||||||
// * PendingAuthRequest
|
// * PendingAuthRequest
|
||||||
// * OnboardingStatus
|
// * OnboardingStatus
|
||||||
|
|||||||
@ -49,14 +49,14 @@ class UserLogoutManagerImpl(
|
|||||||
override fun logout(userId: String, reason: LogoutReason) {
|
override fun logout(userId: String, reason: LogoutReason) {
|
||||||
authDiskSource.userState ?: return
|
authDiskSource.userState ?: return
|
||||||
Timber.d("logout reason=$reason")
|
Timber.d("logout reason=$reason")
|
||||||
val isExpired = reason == LogoutReason.SecurityStamp
|
val isSecurityStamp = reason == LogoutReason.SecurityStamp
|
||||||
if (isExpired) {
|
if (isSecurityStamp) {
|
||||||
showToast(message = BitwardenString.login_expired)
|
showToast(message = BitwardenString.login_expired)
|
||||||
}
|
}
|
||||||
|
|
||||||
val ableToSwitchToNewAccount = switchUserIfAvailable(
|
val ableToSwitchToNewAccount = switchUserIfAvailable(
|
||||||
currentUserId = userId,
|
currentUserId = userId,
|
||||||
isExpired = isExpired,
|
isSecurityStamp = isSecurityStamp,
|
||||||
removeCurrentUserFromAccounts = true,
|
removeCurrentUserFromAccounts = true,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -73,19 +73,24 @@ class UserLogoutManagerImpl(
|
|||||||
|
|
||||||
override fun softLogout(userId: String, reason: LogoutReason) {
|
override fun softLogout(userId: String, reason: LogoutReason) {
|
||||||
Timber.d("softLogout reason=$reason")
|
Timber.d("softLogout reason=$reason")
|
||||||
val isExpired = reason == LogoutReason.SecurityStamp
|
val isSecurityStamp = reason == LogoutReason.SecurityStamp
|
||||||
if (isExpired) {
|
if (isSecurityStamp) {
|
||||||
showToast(message = BitwardenString.login_expired)
|
showToast(message = BitwardenString.login_expired)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save any data that will still need to be retained after otherwise clearing all dat
|
// Save any data that will still need to be retained after otherwise clearing all data
|
||||||
val vaultTimeoutInMinutes = settingsDiskSource.getVaultTimeoutInMinutes(userId = userId)
|
val vaultTimeoutInMinutes = settingsDiskSource.getVaultTimeoutInMinutes(userId = userId)
|
||||||
val vaultTimeoutAction = settingsDiskSource.getVaultTimeoutAction(userId = userId)
|
val vaultTimeoutAction = settingsDiskSource.getVaultTimeoutAction(userId = userId)
|
||||||
|
val encryptedPin = authDiskSource.getEncryptedPin(userId = userId)
|
||||||
|
val pinProtectedUserKey = authDiskSource.getPinProtectedUserKey(userId = userId)
|
||||||
|
val pinProtectedUserKeyEnvelope = authDiskSource.getPinProtectedUserKeyEnvelope(
|
||||||
|
userId = userId,
|
||||||
|
)
|
||||||
|
|
||||||
switchUserIfAvailable(
|
switchUserIfAvailable(
|
||||||
currentUserId = userId,
|
currentUserId = userId,
|
||||||
removeCurrentUserFromAccounts = false,
|
removeCurrentUserFromAccounts = false,
|
||||||
isExpired = isExpired,
|
isSecurityStamp = isSecurityStamp,
|
||||||
)
|
)
|
||||||
|
|
||||||
clearData(userId = userId)
|
clearData(userId = userId)
|
||||||
@ -102,6 +107,14 @@ class UserLogoutManagerImpl(
|
|||||||
vaultTimeoutAction = vaultTimeoutAction,
|
vaultTimeoutAction = vaultTimeoutAction,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
authDiskSource.apply {
|
||||||
|
storeEncryptedPin(userId = userId, encryptedPin = encryptedPin)
|
||||||
|
storePinProtectedUserKey(userId = userId, pinProtectedUserKey = pinProtectedUserKey)
|
||||||
|
storePinProtectedUserKeyEnvelope(
|
||||||
|
userId = userId,
|
||||||
|
pinProtectedUserKeyEnvelope = pinProtectedUserKeyEnvelope,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun clearData(userId: String) {
|
private fun clearData(userId: String) {
|
||||||
@ -123,7 +136,7 @@ class UserLogoutManagerImpl(
|
|||||||
private fun switchUserIfAvailable(
|
private fun switchUserIfAvailable(
|
||||||
currentUserId: String,
|
currentUserId: String,
|
||||||
removeCurrentUserFromAccounts: Boolean,
|
removeCurrentUserFromAccounts: Boolean,
|
||||||
isExpired: Boolean = false,
|
isSecurityStamp: Boolean,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val currentUserState = authDiskSource.userState ?: return false
|
val currentUserState = authDiskSource.userState ?: return false
|
||||||
|
|
||||||
@ -135,7 +148,7 @@ class UserLogoutManagerImpl(
|
|||||||
|
|
||||||
// Check if there is a new active user
|
// Check if there is a new active user
|
||||||
return if (updatedAccounts.isNotEmpty()) {
|
return if (updatedAccounts.isNotEmpty()) {
|
||||||
if (currentUserId == currentUserState.activeUserId && !isExpired) {
|
if (currentUserId == currentUserState.activeUserId && !isSecurityStamp) {
|
||||||
showToast(message = BitwardenString.account_switched_automatically)
|
showToast(message = BitwardenString.account_switched_automatically)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -310,7 +310,7 @@ class VaultSyncManagerImpl(
|
|||||||
localSecurityStamp?.let {
|
localSecurityStamp?.let {
|
||||||
if (serverSecurityStamp != localSecurityStamp) {
|
if (serverSecurityStamp != localSecurityStamp) {
|
||||||
// Ensure UserLogoutManager is available
|
// Ensure UserLogoutManager is available
|
||||||
userLogoutManager.softLogout(
|
userLogoutManager.logout(
|
||||||
userId = userId,
|
userId = userId,
|
||||||
reason = LogoutReason.SecurityStamp,
|
reason = LogoutReason.SecurityStamp,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -267,15 +267,14 @@ class AuthDiskSourceTest {
|
|||||||
userId = userId,
|
userId = userId,
|
||||||
biometricsKey = "1234-9876-0192",
|
biometricsKey = "1234-9876-0192",
|
||||||
)
|
)
|
||||||
val pinProtectedUserKey = "pinProtectedUserKey"
|
authDiskSource.storeEncryptedPin(userId = userId, encryptedPin = "encryptedPin")
|
||||||
authDiskSource.storePinProtectedUserKey(
|
authDiskSource.storePinProtectedUserKey(
|
||||||
userId = userId,
|
userId = userId,
|
||||||
pinProtectedUserKey = pinProtectedUserKey,
|
pinProtectedUserKey = "pinProtectedUserKey",
|
||||||
)
|
)
|
||||||
val pinProtectedUserKeyEnvelope = "pinProtectedUserKeyEnvelope"
|
|
||||||
authDiskSource.storePinProtectedUserKeyEnvelope(
|
authDiskSource.storePinProtectedUserKeyEnvelope(
|
||||||
userId = userId,
|
userId = userId,
|
||||||
pinProtectedUserKeyEnvelope = pinProtectedUserKeyEnvelope,
|
pinProtectedUserKeyEnvelope = "pinProtectedUserKeyEnvelope",
|
||||||
)
|
)
|
||||||
authDiskSource.storeInvalidUnlockAttempts(
|
authDiskSource.storeInvalidUnlockAttempts(
|
||||||
userId = userId,
|
userId = userId,
|
||||||
@ -310,8 +309,6 @@ class AuthDiskSourceTest {
|
|||||||
refreshToken = "refreshToken",
|
refreshToken = "refreshToken",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
val encryptedPin = "encryptedPin"
|
|
||||||
authDiskSource.storeEncryptedPin(userId = userId, encryptedPin = encryptedPin)
|
|
||||||
authDiskSource.storeMasterPasswordHash(userId = userId, passwordHash = "passwordHash")
|
authDiskSource.storeMasterPasswordHash(userId = userId, passwordHash = "passwordHash")
|
||||||
authDiskSource.storeAuthenticatorSyncUnlockKey(
|
authDiskSource.storeAuthenticatorSyncUnlockKey(
|
||||||
userId = userId,
|
userId = userId,
|
||||||
@ -333,12 +330,6 @@ class AuthDiskSourceTest {
|
|||||||
OnboardingStatus.AUTOFILL_SETUP,
|
OnboardingStatus.AUTOFILL_SETUP,
|
||||||
authDiskSource.getOnboardingStatus(userId = userId),
|
authDiskSource.getOnboardingStatus(userId = userId),
|
||||||
)
|
)
|
||||||
assertEquals(encryptedPin, authDiskSource.getEncryptedPin(userId = userId))
|
|
||||||
assertEquals(pinProtectedUserKey, authDiskSource.getPinProtectedUserKey(userId = userId))
|
|
||||||
assertEquals(
|
|
||||||
pinProtectedUserKeyEnvelope,
|
|
||||||
authDiskSource.getPinProtectedUserKeyEnvelope(userId = userId),
|
|
||||||
)
|
|
||||||
|
|
||||||
// These should be cleared
|
// These should be cleared
|
||||||
assertNull(authDiskSource.getUserBiometricInitVector(userId = userId))
|
assertNull(authDiskSource.getUserBiometricInitVector(userId = userId))
|
||||||
@ -357,6 +348,9 @@ class AuthDiskSourceTest {
|
|||||||
assertNull(authDiskSource.getIsTdeLoginComplete(userId = userId))
|
assertNull(authDiskSource.getIsTdeLoginComplete(userId = userId))
|
||||||
assertNull(authDiskSource.getAuthenticatorSyncUnlockKey(userId = userId))
|
assertNull(authDiskSource.getAuthenticatorSyncUnlockKey(userId = userId))
|
||||||
assertNull(authDiskSource.getShowImportLogins(userId = userId))
|
assertNull(authDiskSource.getShowImportLogins(userId = userId))
|
||||||
|
assertNull(authDiskSource.getEncryptedPin(userId = userId))
|
||||||
|
assertNull(authDiskSource.getPinProtectedUserKey(userId = userId))
|
||||||
|
assertNull(authDiskSource.getPinProtectedUserKeyEnvelope(userId = userId))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@ -91,11 +91,14 @@ class FakeAuthDiskSource : AuthDiskSource {
|
|||||||
storedBiometricKeys.remove(userId)
|
storedBiometricKeys.remove(userId)
|
||||||
storedOrganizationKeys.remove(userId)
|
storedOrganizationKeys.remove(userId)
|
||||||
storedPinProtectedUserKeyEnvelopes.remove(userId)
|
storedPinProtectedUserKeyEnvelopes.remove(userId)
|
||||||
|
storedEncryptedPins.remove(userId)
|
||||||
|
storedPinProtectedUserKeys.remove(userId)
|
||||||
|
|
||||||
mutableShouldUseKeyConnectorFlowMap.remove(userId)
|
mutableShouldUseKeyConnectorFlowMap.remove(userId)
|
||||||
mutableOrganizationsFlowMap.remove(userId)
|
mutableOrganizationsFlowMap.remove(userId)
|
||||||
mutablePoliciesFlowMap.remove(userId)
|
mutablePoliciesFlowMap.remove(userId)
|
||||||
mutableAccountTokensFlowMap.remove(userId)
|
mutableAccountTokensFlowMap.remove(userId)
|
||||||
|
mutablePinProtectedUserKeyEnvelopesFlowMap.remove(userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getMutablePinProtectedUserKeyEnvelopeFlow(
|
private fun getMutablePinProtectedUserKeyEnvelopeFlow(
|
||||||
|
|||||||
@ -120,6 +120,21 @@ class UserLogoutManagerTest {
|
|||||||
assertDataCleared(userId = userId)
|
assertDataCleared(userId = userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("MaxLineLength")
|
||||||
|
@Test
|
||||||
|
fun `logout with security stamp reason should switch active user and display the login expired toast`() {
|
||||||
|
val userId = USER_ID_1
|
||||||
|
every { authDiskSource.userState } returns MULTI_USER_STATE
|
||||||
|
|
||||||
|
userLogoutManager.logout(userId = userId, reason = LogoutReason.SecurityStamp)
|
||||||
|
|
||||||
|
verify(exactly = 1) {
|
||||||
|
authDiskSource.userState = SINGLE_USER_STATE_2
|
||||||
|
toastManager.show(messageId = BitwardenString.login_expired)
|
||||||
|
}
|
||||||
|
assertDataCleared(userId = userId)
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("MaxLineLength")
|
@Suppress("MaxLineLength")
|
||||||
@Test
|
@Test
|
||||||
fun `softLogout should clear most data associated with the given user and remove token data in the authDiskSource`() {
|
fun `softLogout should clear most data associated with the given user and remove token data in the authDiskSource`() {
|
||||||
@ -127,6 +142,8 @@ class UserLogoutManagerTest {
|
|||||||
val vaultTimeoutInMinutes = 360
|
val vaultTimeoutInMinutes = 360
|
||||||
val vaultTimeoutAction = VaultTimeoutAction.LOGOUT
|
val vaultTimeoutAction = VaultTimeoutAction.LOGOUT
|
||||||
val pinProtectedUserKey = "pinProtectedUserKey"
|
val pinProtectedUserKey = "pinProtectedUserKey"
|
||||||
|
val pinProtectedUserKeyEnvelope = "pinProtectedUserKeyEnvelope"
|
||||||
|
val encryptedPin = "encryptedPin"
|
||||||
|
|
||||||
every { authDiskSource.userState } returns MULTI_USER_STATE
|
every { authDiskSource.userState } returns MULTI_USER_STATE
|
||||||
every {
|
every {
|
||||||
@ -135,10 +152,26 @@ class UserLogoutManagerTest {
|
|||||||
every {
|
every {
|
||||||
settingsDiskSource.getVaultTimeoutAction(userId = userId)
|
settingsDiskSource.getVaultTimeoutAction(userId = userId)
|
||||||
} returns vaultTimeoutAction
|
} returns vaultTimeoutAction
|
||||||
|
|
||||||
every {
|
every {
|
||||||
authDiskSource.getPinProtectedUserKeyEnvelope(userId = userId)
|
authDiskSource.getPinProtectedUserKeyEnvelope(userId = userId)
|
||||||
} returns pinProtectedUserKey
|
} returns pinProtectedUserKeyEnvelope
|
||||||
|
every {
|
||||||
|
authDiskSource.storePinProtectedUserKeyEnvelope(
|
||||||
|
userId = userId,
|
||||||
|
pinProtectedUserKeyEnvelope = pinProtectedUserKeyEnvelope,
|
||||||
|
)
|
||||||
|
} just runs
|
||||||
|
every { authDiskSource.getPinProtectedUserKey(userId = userId) } returns pinProtectedUserKey
|
||||||
|
every {
|
||||||
|
authDiskSource.storePinProtectedUserKey(
|
||||||
|
userId = userId,
|
||||||
|
pinProtectedUserKey = pinProtectedUserKey,
|
||||||
|
)
|
||||||
|
} just runs
|
||||||
|
every { authDiskSource.getEncryptedPin(userId = userId) } returns encryptedPin
|
||||||
|
every {
|
||||||
|
authDiskSource.storeEncryptedPin(userId = userId, encryptedPin = encryptedPin)
|
||||||
|
} just runs
|
||||||
|
|
||||||
userLogoutManager.softLogout(userId = userId, reason = LogoutReason.Timeout)
|
userLogoutManager.softLogout(userId = userId, reason = LogoutReason.Timeout)
|
||||||
|
|
||||||
@ -162,6 +195,15 @@ class UserLogoutManagerTest {
|
|||||||
userId = userId,
|
userId = userId,
|
||||||
vaultTimeoutAction = vaultTimeoutAction,
|
vaultTimeoutAction = vaultTimeoutAction,
|
||||||
)
|
)
|
||||||
|
authDiskSource.storePinProtectedUserKeyEnvelope(
|
||||||
|
userId = userId,
|
||||||
|
pinProtectedUserKeyEnvelope = pinProtectedUserKeyEnvelope,
|
||||||
|
)
|
||||||
|
authDiskSource.storePinProtectedUserKey(
|
||||||
|
userId = userId,
|
||||||
|
pinProtectedUserKey = pinProtectedUserKey,
|
||||||
|
)
|
||||||
|
authDiskSource.storeEncryptedPin(userId = userId, encryptedPin = encryptedPin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,6 +213,8 @@ class UserLogoutManagerTest {
|
|||||||
val vaultTimeoutInMinutes = 360
|
val vaultTimeoutInMinutes = 360
|
||||||
val vaultTimeoutAction = VaultTimeoutAction.LOGOUT
|
val vaultTimeoutAction = VaultTimeoutAction.LOGOUT
|
||||||
val pinProtectedUserKey = "pinProtectedUserKey"
|
val pinProtectedUserKey = "pinProtectedUserKey"
|
||||||
|
val pinProtectedUserKeyEnvelope = "pinProtectedUserKeyEnvelope"
|
||||||
|
val encryptedPin = "encryptedPin"
|
||||||
|
|
||||||
every { authDiskSource.userState } returns MULTI_USER_STATE
|
every { authDiskSource.userState } returns MULTI_USER_STATE
|
||||||
every {
|
every {
|
||||||
@ -181,7 +225,24 @@ class UserLogoutManagerTest {
|
|||||||
} returns vaultTimeoutAction
|
} returns vaultTimeoutAction
|
||||||
every {
|
every {
|
||||||
authDiskSource.getPinProtectedUserKeyEnvelope(userId = userId)
|
authDiskSource.getPinProtectedUserKeyEnvelope(userId = userId)
|
||||||
} returns pinProtectedUserKey
|
} returns pinProtectedUserKeyEnvelope
|
||||||
|
every {
|
||||||
|
authDiskSource.storePinProtectedUserKeyEnvelope(
|
||||||
|
userId = userId,
|
||||||
|
pinProtectedUserKeyEnvelope = pinProtectedUserKeyEnvelope,
|
||||||
|
)
|
||||||
|
} just runs
|
||||||
|
every { authDiskSource.getPinProtectedUserKey(userId = userId) } returns pinProtectedUserKey
|
||||||
|
every {
|
||||||
|
authDiskSource.storePinProtectedUserKey(
|
||||||
|
userId = userId,
|
||||||
|
pinProtectedUserKey = pinProtectedUserKey,
|
||||||
|
)
|
||||||
|
} just runs
|
||||||
|
every { authDiskSource.getEncryptedPin(userId = userId) } returns encryptedPin
|
||||||
|
every {
|
||||||
|
authDiskSource.storeEncryptedPin(userId = userId, encryptedPin = encryptedPin)
|
||||||
|
} just runs
|
||||||
|
|
||||||
userLogoutManager.softLogout(userId = userId, reason = LogoutReason.Timeout)
|
userLogoutManager.softLogout(userId = userId, reason = LogoutReason.Timeout)
|
||||||
|
|
||||||
@ -199,44 +260,15 @@ class UserLogoutManagerTest {
|
|||||||
userId = userId,
|
userId = userId,
|
||||||
vaultTimeoutAction = vaultTimeoutAction,
|
vaultTimeoutAction = vaultTimeoutAction,
|
||||||
)
|
)
|
||||||
}
|
authDiskSource.storePinProtectedUserKeyEnvelope(
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("MaxLineLength")
|
|
||||||
@Test
|
|
||||||
fun `softLogout with security stamp reason should switch active user and keep previous user in accounts list but display the login expired toast`() {
|
|
||||||
val userId = USER_ID_1
|
|
||||||
val vaultTimeoutInMinutes = 360
|
|
||||||
val vaultTimeoutAction = VaultTimeoutAction.LOGOUT
|
|
||||||
val pinProtectedUserKey = "pinProtectedUserKey"
|
|
||||||
|
|
||||||
every { authDiskSource.userState } returns MULTI_USER_STATE
|
|
||||||
every {
|
|
||||||
authDiskSource.getPinProtectedUserKeyEnvelope(userId)
|
|
||||||
} returns pinProtectedUserKey
|
|
||||||
every {
|
|
||||||
settingsDiskSource.getVaultTimeoutInMinutes(userId = userId)
|
|
||||||
} returns vaultTimeoutInMinutes
|
|
||||||
every {
|
|
||||||
settingsDiskSource.getVaultTimeoutAction(userId = userId)
|
|
||||||
} returns vaultTimeoutAction
|
|
||||||
|
|
||||||
userLogoutManager.softLogout(userId = userId, reason = LogoutReason.SecurityStamp)
|
|
||||||
|
|
||||||
verify(exactly = 1) {
|
|
||||||
authDiskSource.userState = UserStateJson(
|
|
||||||
activeUserId = USER_ID_2,
|
|
||||||
accounts = MULTI_USER_STATE.accounts,
|
|
||||||
)
|
|
||||||
toastManager.show(messageId = BitwardenString.login_expired)
|
|
||||||
settingsDiskSource.storeVaultTimeoutInMinutes(
|
|
||||||
userId = userId,
|
userId = userId,
|
||||||
vaultTimeoutInMinutes = vaultTimeoutInMinutes,
|
pinProtectedUserKeyEnvelope = pinProtectedUserKeyEnvelope,
|
||||||
)
|
)
|
||||||
settingsDiskSource.storeVaultTimeoutAction(
|
authDiskSource.storePinProtectedUserKey(
|
||||||
userId = userId,
|
userId = userId,
|
||||||
vaultTimeoutAction = vaultTimeoutAction,
|
pinProtectedUserKey = pinProtectedUserKey,
|
||||||
)
|
)
|
||||||
|
authDiskSource.storeEncryptedPin(userId = userId, encryptedPin = encryptedPin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -126,7 +126,7 @@ class VaultSyncManagerTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private val userLogoutManager: UserLogoutManager = mockk {
|
private val userLogoutManager: UserLogoutManager = mockk {
|
||||||
every { softLogout(any(), any()) } just runs
|
every { logout(userId = any(), reason = LogoutReason.SecurityStamp) } just runs
|
||||||
}
|
}
|
||||||
private val userStateManager: UserStateManager = mockk {
|
private val userStateManager: UserStateManager = mockk {
|
||||||
val blockSlot = slot<suspend () -> SyncVaultDataResult>()
|
val blockSlot = slot<suspend () -> SyncVaultDataResult>()
|
||||||
@ -786,7 +786,7 @@ class VaultSyncManagerTest {
|
|||||||
vaultSyncManager.sync()
|
vaultSyncManager.sync()
|
||||||
|
|
||||||
coVerify(exactly = 1) {
|
coVerify(exactly = 1) {
|
||||||
userLogoutManager.softLogout(userId = userId, reason = LogoutReason.SecurityStamp)
|
userLogoutManager.logout(userId = userId, reason = LogoutReason.SecurityStamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
coVerify(exactly = 0) {
|
coVerify(exactly = 0) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user