PM-25474: Allow SYNC_CIPHER_DELETE notification to delete Cipher for inactive user (#5836)

This commit is contained in:
David Perez
2025-09-05 09:32:34 -05:00
committed by GitHub
parent fe6346013b
commit 393931a5c6
5 changed files with 33 additions and 18 deletions

View File

@@ -190,9 +190,14 @@ class PushManagerImpl @Inject constructor(
.decodeFromString<NotificationPayload.SyncCipherNotification>(
string = notification.payload,
)
.takeIf { isLoggedIn(userId) && it.userMatchesNotification(userId) }
?.cipherId
?.let { mutableSyncCipherDeleteSharedFlow.tryEmit(SyncCipherDeleteData(it)) }
.takeIf { it.userId != null && it.cipherId != null }
?.let {
SyncCipherDeleteData(
userId = requireNotNull(it.userId),
cipherId = requireNotNull(it.cipherId),
)
}
?.let { mutableSyncCipherDeleteSharedFlow.tryEmit(it) }
}
NotificationType.SYNC_CIPHERS,

View File

@@ -2,9 +2,8 @@ package com.x8bit.bitwarden.data.platform.manager.model
/**
* Required data for sync cipher delete operations.
*
* @property cipherId The cipher ID.
*/
data class SyncCipherDeleteData(
val userId: String,
val cipherId: String,
)

View File

@@ -1248,12 +1248,9 @@ class VaultRepositoryImpl(
* Deletes the cipher specified by [syncCipherDeleteData] from disk.
*/
private suspend fun deleteCipher(syncCipherDeleteData: SyncCipherDeleteData) {
val userId = activeUserId ?: return
val cipherId = syncCipherDeleteData.cipherId
vaultDiskSource.deleteCipher(
userId = userId,
cipherId = cipherId,
userId = syncCipherDeleteData.userId,
cipherId = syncCipherDeleteData.cipherId,
)
}

View File

@@ -237,6 +237,7 @@ class PushManagerTest {
pushManager.onMessageReceived(SYNC_CIPHER_DELETE_NOTIFICATION_MAP)
assertEquals(
SyncCipherDeleteData(
userId = "078966a2-93c2-4618-ae2a-0a2394c88d37",
cipherId = "aab5cdcc-f4a7-4e65-bf6d-5e0eab052321",
),
awaitItem(),
@@ -316,6 +317,7 @@ class PushManagerTest {
pushManager.onMessageReceived(SYNC_LOGIN_DELETE_NOTIFICATION_MAP)
assertEquals(
SyncCipherDeleteData(
userId = "078966a2-93c2-4618-ae2a-0a2394c88d37",
cipherId = "aab5cdcc-f4a7-4e65-bf6d-5e0eab052321",
),
awaitItem(),
@@ -405,7 +407,13 @@ class PushManagerTest {
fun `onMessageReceived with sync cipher delete does nothing`() = runTest {
pushManager.syncCipherDeleteFlow.test {
pushManager.onMessageReceived(SYNC_CIPHER_DELETE_NOTIFICATION_MAP)
expectNoEvents()
assertEquals(
SyncCipherDeleteData(
userId = "078966a2-93c2-4618-ae2a-0a2394c88d37",
cipherId = "aab5cdcc-f4a7-4e65-bf6d-5e0eab052321",
),
awaitItem(),
)
}
}
@@ -449,12 +457,19 @@ class PushManagerTest {
}
@Test
fun `onMessageReceived with sync login delete does nothing`() = runTest {
pushManager.syncCipherDeleteFlow.test {
pushManager.onMessageReceived(SYNC_LOGIN_DELETE_NOTIFICATION_MAP)
expectNoEvents()
fun `onMessageReceived with sync login delete emits to syncCipherDeleteFlow`() =
runTest {
pushManager.syncCipherDeleteFlow.test {
pushManager.onMessageReceived(SYNC_LOGIN_DELETE_NOTIFICATION_MAP)
assertEquals(
SyncCipherDeleteData(
userId = "078966a2-93c2-4618-ae2a-0a2394c88d37",
cipherId = "aab5cdcc-f4a7-4e65-bf6d-5e0eab052321",
),
awaitItem(),
)
}
}
}
@Test
fun `onMessageReceived with sync send create does nothing`() = runTest {

View File

@@ -3317,11 +3317,10 @@ class VaultRepositoryTest {
val userId = "mockId-1"
val cipherId = "mockId-1"
fakeAuthDiskSource.userState = MOCK_USER_STATE
coEvery { vaultDiskSource.deleteCipher(userId = userId, cipherId = cipherId) } just runs
mutableSyncCipherDeleteFlow.tryEmit(
SyncCipherDeleteData(cipherId = cipherId),
SyncCipherDeleteData(userId = userId, cipherId = cipherId),
)
coVerify { vaultDiskSource.deleteCipher(userId = userId, cipherId = cipherId) }