diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/manager/UserLogoutManager.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/manager/UserLogoutManager.kt index 1c5093ae0..7a36ff315 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/manager/UserLogoutManager.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/manager/UserLogoutManager.kt @@ -14,15 +14,15 @@ interface UserLogoutManager { val logoutEventFlow: SharedFlow /** - * Completely logs out the given [userId], removing all data. - * If [isExpired] is true, a toast will be displayed - * letting the user know the session has expired. + * Completely logs out the given [userId], removing all data. If [isExpired] is true, a toast + * will be displayed letting the user know the session has expired. */ fun logout(userId: String, isExpired: Boolean = false) /** * Partially logs out the given [userId]. All data for the given [userId] will be removed with - * the exception of basic account data. + * the exception of basic account data. If [isExpired] is true, a toast will be displayed + * letting the user know the session has expired. */ - fun softLogout(userId: String) + fun softLogout(userId: String, isExpired: Boolean = false) } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/manager/UserLogoutManagerImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/manager/UserLogoutManagerImpl.kt index 4fdd53229..b69cc8661 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/manager/UserLogoutManagerImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/manager/UserLogoutManagerImpl.kt @@ -64,7 +64,10 @@ class UserLogoutManagerImpl( mutableLogoutEventFlow.tryEmit(LogoutEvent(loggedOutUserId = userId)) } - override fun softLogout(userId: String) { + override fun softLogout(userId: String, isExpired: Boolean) { + if (isExpired) { + showToast(message = R.string.login_expired) + } authDiskSource.storeAccountTokens( userId = userId, accountTokens = null, @@ -74,7 +77,11 @@ class UserLogoutManagerImpl( val vaultTimeoutInMinutes = settingsDiskSource.getVaultTimeoutInMinutes(userId = userId) val vaultTimeoutAction = settingsDiskSource.getVaultTimeoutAction(userId = userId) - switchUserIfAvailable(currentUserId = userId, removeCurrentUserFromAccounts = false) + switchUserIfAvailable( + currentUserId = userId, + removeCurrentUserFromAccounts = false, + isExpired = isExpired, + ) clearData(userId = userId) mutableLogoutEventFlow.tryEmit(LogoutEvent(loggedOutUserId = userId)) diff --git a/app/src/main/java/com/x8bit/bitwarden/data/vault/repository/VaultRepositoryImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/vault/repository/VaultRepositoryImpl.kt index 71373630b..e5c7bf4bb 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/vault/repository/VaultRepositoryImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/vault/repository/VaultRepositoryImpl.kt @@ -358,7 +358,7 @@ class VaultRepositoryImpl( // Log the user out if the stamps do not match localSecurityStamp?.let { if (serverSecurityStamp != localSecurityStamp) { - userLogoutManager.logout(userId = userId, isExpired = true) + userLogoutManager.softLogout(userId = userId, isExpired = true) return@launch } } diff --git a/app/src/test/java/com/x8bit/bitwarden/data/auth/manager/UserLogoutManagerTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/auth/manager/UserLogoutManagerTest.kt index f8dbb9def..5ab8e508c 100644 --- a/app/src/test/java/com/x8bit/bitwarden/data/auth/manager/UserLogoutManagerTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/data/auth/manager/UserLogoutManagerTest.kt @@ -138,21 +138,21 @@ class UserLogoutManagerTest { verify { authDiskSource.storeAccountTokens(userId = USER_ID_1, accountTokens = null) } assertDataCleared(userId = userId) - verify { + verify(exactly = 1) { settingsDiskSource.storeVaultTimeoutInMinutes( userId = userId, vaultTimeoutInMinutes = vaultTimeoutInMinutes, ) - } - verify { settingsDiskSource.storeVaultTimeoutAction( userId = userId, vaultTimeoutAction = vaultTimeoutAction, ) + Toast + .makeText(context, R.string.account_switched_automatically, Toast.LENGTH_SHORT) + .show() } } - @Suppress("MaxLineLength") @Test fun `softLogout should switch active user but keep previous user in accounts list`() { val userId = USER_ID_1 @@ -171,10 +171,44 @@ class UserLogoutManagerTest { userLogoutManager.softLogout(userId = userId) - verify { authDiskSource.storeAccountTokens(userId = USER_ID_1, accountTokens = null) } - verify { - authDiskSource.userState = - UserStateJson(activeUserId = USER_ID_2, accounts = MULTI_USER_STATE.accounts) + verify(exactly = 1) { + authDiskSource.storeAccountTokens(userId = USER_ID_1, accountTokens = null) + authDiskSource.userState = UserStateJson( + activeUserId = USER_ID_2, + accounts = MULTI_USER_STATE.accounts, + ) + Toast + .makeText(context, R.string.account_switched_automatically, Toast.LENGTH_SHORT) + .show() + } + } + + @Suppress("MaxLineLength") + @Test + fun `softLogout with isExpired true 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 + + mockToast(R.string.login_expired) + + every { authDiskSource.userState } returns MULTI_USER_STATE + every { + settingsDiskSource.getVaultTimeoutInMinutes(userId = userId) + } returns vaultTimeoutInMinutes + every { + settingsDiskSource.getVaultTimeoutAction(userId = userId) + } returns vaultTimeoutAction + + userLogoutManager.softLogout(userId = userId, isExpired = true) + + verify(exactly = 1) { + authDiskSource.storeAccountTokens(userId = USER_ID_1, accountTokens = null) + authDiskSource.userState = UserStateJson( + activeUserId = USER_ID_2, + accounts = MULTI_USER_STATE.accounts, + ) + Toast.makeText(context, R.string.login_expired, Toast.LENGTH_SHORT).show() } } diff --git a/app/src/test/java/com/x8bit/bitwarden/data/vault/repository/VaultRepositoryTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/vault/repository/VaultRepositoryTest.kt index c41aa8b06..0455052d2 100644 --- a/app/src/test/java/com/x8bit/bitwarden/data/vault/repository/VaultRepositoryTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/data/vault/repository/VaultRepositoryTest.kt @@ -140,7 +140,7 @@ class VaultRepositoryTest { ) private val dispatcherManager: DispatcherManager = FakeDispatcherManager() private val userLogoutManager: UserLogoutManager = mockk { - every { logout(any(), any()) } just runs + every { softLogout(any(), any()) } just runs } private val fileManager: FileManager = mockk { coEvery { delete(*anyVararg()) } just runs @@ -851,9 +851,8 @@ class VaultRepositoryTest { fakeAuthDiskSource.userState = MOCK_USER_STATE val userId = "mockId-1" val mockSyncResponse = createMockSyncResponse(number = 1) - coEvery { syncService.sync() } returns mockSyncResponse.copy( - profile = createMockProfile(number = 1).copy(securityStamp = "newStamp"), - ) + coEvery { syncService.sync() } returns mockSyncResponse + .copy(profile = createMockProfile(number = 1).copy(securityStamp = "newStamp")) .asSuccess() coEvery { @@ -868,7 +867,7 @@ class VaultRepositoryTest { vaultRepository.sync() coVerify { - userLogoutManager.logout(userId = userId, isExpired = true) + userLogoutManager.softLogout(userId = userId, isExpired = true) } coVerify(exactly = 0) {