mirror of
https://github.com/bitwarden/android.git
synced 2025-12-10 00:06:22 -06:00
PM-25462: Allow SYNC_FOLDER_DELETE notification to delete Folders for inactive user (#5832)
This commit is contained in:
parent
eec4233486
commit
aa39e6c6be
@ -227,9 +227,14 @@ class PushManagerImpl @Inject constructor(
|
||||
.decodeFromString<NotificationPayload.SyncFolderNotification>(
|
||||
string = notification.payload,
|
||||
)
|
||||
.takeIf { isLoggedIn(userId) && it.userMatchesNotification(userId) }
|
||||
?.folderId
|
||||
?.let { mutableSyncFolderDeleteSharedFlow.tryEmit(SyncFolderDeleteData(it)) }
|
||||
.takeIf { it.userId != null && it.folderId != null }
|
||||
?.let {
|
||||
SyncFolderDeleteData(
|
||||
userId = requireNotNull(it.userId),
|
||||
folderId = requireNotNull(it.folderId),
|
||||
)
|
||||
}
|
||||
?.let { mutableSyncFolderDeleteSharedFlow.tryEmit(it) }
|
||||
}
|
||||
|
||||
NotificationType.SYNC_ORG_KEYS -> {
|
||||
|
||||
@ -2,9 +2,8 @@ package com.x8bit.bitwarden.data.platform.manager.model
|
||||
|
||||
/**
|
||||
* Required data for sync folder delete operations.
|
||||
*
|
||||
* @property folderId The folder ID.
|
||||
*/
|
||||
data class SyncFolderDeleteData(
|
||||
val userId: String,
|
||||
val folderId: String,
|
||||
)
|
||||
|
||||
@ -929,11 +929,9 @@ class VaultRepositoryImpl(
|
||||
}
|
||||
|
||||
private suspend fun clearFolderIdFromCiphers(folderId: String, userId: String) {
|
||||
vaultDiskSource.getCiphersFlow(userId).firstOrNull()?.forEach {
|
||||
vaultDiskSource.getCiphers(userId = userId).forEach {
|
||||
if (it.folderId == folderId) {
|
||||
vaultDiskSource.saveCipher(
|
||||
userId, it.copy(folderId = null),
|
||||
)
|
||||
vaultDiskSource.saveCipher(userId = userId, cipher = it.copy(folderId = null))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1433,16 +1431,13 @@ class VaultRepositoryImpl(
|
||||
* Deletes the folder specified by [syncFolderDeleteData] from disk.
|
||||
*/
|
||||
private suspend fun deleteFolder(syncFolderDeleteData: SyncFolderDeleteData) {
|
||||
val userId = activeUserId ?: return
|
||||
|
||||
val folderId = syncFolderDeleteData.folderId
|
||||
clearFolderIdFromCiphers(
|
||||
folderId = folderId,
|
||||
userId = userId,
|
||||
folderId = syncFolderDeleteData.folderId,
|
||||
userId = syncFolderDeleteData.userId,
|
||||
)
|
||||
vaultDiskSource.deleteFolder(
|
||||
folderId = folderId,
|
||||
userId = userId,
|
||||
folderId = syncFolderDeleteData.folderId,
|
||||
userId = syncFolderDeleteData.userId,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -285,6 +285,7 @@ class PushManagerTest {
|
||||
pushManager.onMessageReceived(SYNC_FOLDER_DELETE_NOTIFICATION_MAP)
|
||||
assertEquals(
|
||||
SyncFolderDeleteData(
|
||||
userId = "078966a2-93c2-4618-ae2a-0a2394c88d37",
|
||||
folderId = "aab5cdcc-f4a7-4e65-bf6d-5e0eab052321",
|
||||
),
|
||||
awaitItem(),
|
||||
@ -425,12 +426,19 @@ class PushManagerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `onMessageReceived with sync folder delete does nothing`() = runTest {
|
||||
pushManager.syncFolderDeleteFlow.test {
|
||||
pushManager.onMessageReceived(SYNC_FOLDER_DELETE_NOTIFICATION_MAP)
|
||||
expectNoEvents()
|
||||
fun `onMessageReceived with sync folder delete emits to syncFolderDeleteFlow`() =
|
||||
runTest {
|
||||
pushManager.syncFolderDeleteFlow.test {
|
||||
pushManager.onMessageReceived(SYNC_FOLDER_DELETE_NOTIFICATION_MAP)
|
||||
assertEquals(
|
||||
SyncFolderDeleteData(
|
||||
userId = "078966a2-93c2-4618-ae2a-0a2394c88d37",
|
||||
folderId = "aab5cdcc-f4a7-4e65-bf6d-5e0eab052321",
|
||||
),
|
||||
awaitItem(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `onMessageReceived with sync folder update does nothing`() = runTest {
|
||||
|
||||
@ -2834,46 +2834,26 @@ class VaultRepositoryTest {
|
||||
fun `DeleteFolder with folderService Delete success should return DeleteFolderResult Success and update ciphers`() =
|
||||
runTest {
|
||||
fakeAuthDiskSource.userState = MOCK_USER_STATE
|
||||
val userId = MOCK_USER_STATE.activeUserId
|
||||
val folderId = "mockFolderId-1"
|
||||
val mockCipher = createMockCipher(number = 1)
|
||||
val ciphers = listOf(mockCipher, createMockCipher(number = 2))
|
||||
coEvery { folderService.deleteFolder(folderId) } returns Unit.asSuccess()
|
||||
coEvery {
|
||||
vaultDiskSource.deleteFolder(
|
||||
MOCK_USER_STATE.activeUserId,
|
||||
folderId,
|
||||
)
|
||||
} just runs
|
||||
|
||||
val mockCipher = createMockCipher(1)
|
||||
|
||||
val mutableCiphersStateFlow =
|
||||
MutableStateFlow(
|
||||
listOf(
|
||||
mockCipher,
|
||||
createMockCipher(2),
|
||||
),
|
||||
)
|
||||
|
||||
coEvery {
|
||||
vaultDiskSource.getCiphersFlow(MOCK_USER_STATE.activeUserId)
|
||||
} returns mutableCiphersStateFlow
|
||||
|
||||
coEvery { vaultDiskSource.deleteFolder(userId = userId, folderId = folderId) } just runs
|
||||
coEvery { vaultDiskSource.getCiphers(userId = userId) } returns ciphers
|
||||
coEvery {
|
||||
vaultDiskSource.saveCipher(
|
||||
MOCK_USER_STATE.activeUserId,
|
||||
mockCipher.copy(
|
||||
folderId = null,
|
||||
),
|
||||
userId = userId,
|
||||
cipher = mockCipher.copy(folderId = null),
|
||||
)
|
||||
} just runs
|
||||
|
||||
val result = vaultRepository.deleteFolder(folderId)
|
||||
val result = vaultRepository.deleteFolder(folderId = folderId)
|
||||
|
||||
coVerify(exactly = 1) {
|
||||
vaultDiskSource.saveCipher(
|
||||
MOCK_USER_STATE.activeUserId,
|
||||
mockCipher.copy(
|
||||
folderId = null,
|
||||
),
|
||||
userId = userId,
|
||||
cipher = mockCipher.copy(folderId = null),
|
||||
)
|
||||
}
|
||||
|
||||
@ -4020,20 +4000,21 @@ class VaultRepositoryTest {
|
||||
fun `syncFolderDeleteFlow should delete folder from disk and update ciphers`() {
|
||||
val userId = "mockId-1"
|
||||
val folderId = "mockId-1"
|
||||
val cipher = createMockCipher(number = 1, folderId = folderId)
|
||||
val updatedCipher = createMockCipher(number = 1, folderId = null)
|
||||
|
||||
fakeAuthDiskSource.userState = MOCK_USER_STATE
|
||||
coEvery { vaultDiskSource.deleteFolder(userId = userId, folderId = folderId) } just runs
|
||||
coEvery {
|
||||
vaultDiskSource.getCiphersFlow(userId)
|
||||
} returns flowOf()
|
||||
coEvery { vaultDiskSource.getCiphers(userId = userId) } returns listOf(cipher)
|
||||
coEvery { vaultDiskSource.saveCipher(userId = userId, cipher = updatedCipher) } just runs
|
||||
|
||||
mutableSyncFolderDeleteFlow.tryEmit(
|
||||
SyncFolderDeleteData(folderId = folderId),
|
||||
SyncFolderDeleteData(userId = userId, folderId = folderId),
|
||||
)
|
||||
|
||||
coVerify {
|
||||
coVerify(exactly = 1) {
|
||||
vaultDiskSource.deleteFolder(userId = userId, folderId = folderId)
|
||||
vaultDiskSource.getCiphersFlow(userId)
|
||||
vaultDiskSource.getCiphers(userId = userId)
|
||||
vaultDiskSource.saveCipher(userId = userId, cipher = updatedCipher)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user