mirror of
https://github.com/bitwarden/android.git
synced 2025-12-10 09:56:45 -06:00
PM-1908: Push notifications for non-active accounts prompt for future sync
This commit is contained in:
parent
4a874668f2
commit
4641fd8709
@ -34,6 +34,8 @@ import java.time.Clock
|
|||||||
import java.time.ZoneOffset
|
import java.time.ZoneOffset
|
||||||
import java.time.ZonedDateTime
|
import java.time.ZonedDateTime
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import kotlin.contracts.ExperimentalContracts
|
||||||
|
import kotlin.contracts.contract
|
||||||
import kotlin.time.Duration
|
import kotlin.time.Duration
|
||||||
import kotlin.time.Duration.Companion.days
|
import kotlin.time.Duration.Companion.days
|
||||||
import kotlin.time.toJavaDuration
|
import kotlin.time.toJavaDuration
|
||||||
@ -134,7 +136,6 @@ class PushManagerImpl @Inject constructor(
|
|||||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||||
private fun onMessageReceived(notification: BitwardenNotification) {
|
private fun onMessageReceived(notification: BitwardenNotification) {
|
||||||
if (authDiskSource.uniqueAppId == notification.contextId) return
|
if (authDiskSource.uniqueAppId == notification.contextId) return
|
||||||
val userId = activeUserId ?: return
|
|
||||||
Timber.d("Push Notification Received: ${notification.notificationType}")
|
Timber.d("Push Notification Received: ${notification.notificationType}")
|
||||||
|
|
||||||
when (val type = notification.notificationType) {
|
when (val type = notification.notificationType) {
|
||||||
@ -179,11 +180,13 @@ class PushManagerImpl @Inject constructor(
|
|||||||
.decodeFromString<NotificationPayload.SyncCipherNotification>(
|
.decodeFromString<NotificationPayload.SyncCipherNotification>(
|
||||||
string = notification.payload,
|
string = notification.payload,
|
||||||
)
|
)
|
||||||
.takeIf { isLoggedIn(userId) && it.userMatchesNotification(userId) }
|
.takeIf {
|
||||||
?.takeIf { it.cipherId != null && it.revisionDate != null }
|
it.cipherId != null && it.revisionDate != null && isLoggedIn(it.userId)
|
||||||
|
}
|
||||||
?.let {
|
?.let {
|
||||||
mutableSyncCipherUpsertSharedFlow.tryEmit(
|
mutableSyncCipherUpsertSharedFlow.tryEmit(
|
||||||
SyncCipherUpsertData(
|
SyncCipherUpsertData(
|
||||||
|
userId = requireNotNull(it.userId),
|
||||||
cipherId = requireNotNull(it.cipherId),
|
cipherId = requireNotNull(it.cipherId),
|
||||||
revisionDate = requireNotNull(it.revisionDate),
|
revisionDate = requireNotNull(it.revisionDate),
|
||||||
organizationId = it.organizationId,
|
organizationId = it.organizationId,
|
||||||
@ -228,11 +231,13 @@ class PushManagerImpl @Inject constructor(
|
|||||||
.decodeFromString<NotificationPayload.SyncFolderNotification>(
|
.decodeFromString<NotificationPayload.SyncFolderNotification>(
|
||||||
string = notification.payload,
|
string = notification.payload,
|
||||||
)
|
)
|
||||||
.takeIf { isLoggedIn(userId) && it.userMatchesNotification(userId) }
|
.takeIf {
|
||||||
?.takeIf { it.folderId != null && it.revisionDate != null }
|
it.folderId != null && it.revisionDate != null && isLoggedIn(it.userId)
|
||||||
|
}
|
||||||
?.let {
|
?.let {
|
||||||
mutableSyncFolderUpsertSharedFlow.tryEmit(
|
mutableSyncFolderUpsertSharedFlow.tryEmit(
|
||||||
SyncFolderUpsertData(
|
SyncFolderUpsertData(
|
||||||
|
userId = requireNotNull(it.userId),
|
||||||
folderId = requireNotNull(it.folderId),
|
folderId = requireNotNull(it.folderId),
|
||||||
revisionDate = requireNotNull(it.revisionDate),
|
revisionDate = requireNotNull(it.revisionDate),
|
||||||
isUpdate = type == NotificationType.SYNC_FOLDER_UPDATE,
|
isUpdate = type == NotificationType.SYNC_FOLDER_UPDATE,
|
||||||
@ -273,11 +278,13 @@ class PushManagerImpl @Inject constructor(
|
|||||||
.decodeFromString<NotificationPayload.SyncSendNotification>(
|
.decodeFromString<NotificationPayload.SyncSendNotification>(
|
||||||
string = notification.payload,
|
string = notification.payload,
|
||||||
)
|
)
|
||||||
.takeIf { isLoggedIn(userId) && it.userMatchesNotification(userId) }
|
.takeIf {
|
||||||
?.takeIf { it.sendId != null && it.revisionDate != null }
|
it.sendId != null && it.revisionDate != null && isLoggedIn(it.userId)
|
||||||
|
}
|
||||||
?.let {
|
?.let {
|
||||||
mutableSyncSendUpsertSharedFlow.tryEmit(
|
mutableSyncSendUpsertSharedFlow.tryEmit(
|
||||||
SyncSendUpsertData(
|
SyncSendUpsertData(
|
||||||
|
userId = requireNotNull(it.userId),
|
||||||
sendId = requireNotNull(it.sendId),
|
sendId = requireNotNull(it.sendId),
|
||||||
revisionDate = requireNotNull(it.revisionDate),
|
revisionDate = requireNotNull(it.revisionDate),
|
||||||
isUpdate = type == NotificationType.SYNC_SEND_UPDATE,
|
isUpdate = type == NotificationType.SYNC_SEND_UPDATE,
|
||||||
@ -361,11 +368,11 @@ class PushManagerImpl @Inject constructor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalContracts::class)
|
||||||
private fun isLoggedIn(
|
private fun isLoggedIn(
|
||||||
userId: String,
|
userId: String?,
|
||||||
): Boolean = authDiskSource.getAccountTokens(userId)?.isLoggedIn == true
|
): Boolean {
|
||||||
}
|
contract { returns(true) implies (userId != null) }
|
||||||
|
return userId?.let { authDiskSource.getAccountTokens(it) }?.isLoggedIn == true
|
||||||
private fun NotificationPayload.userMatchesNotification(userId: String): Boolean {
|
}
|
||||||
return this.userId != null && this.userId == userId
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,12 +5,14 @@ import java.time.ZonedDateTime
|
|||||||
/**
|
/**
|
||||||
* Required data for sync cipher upsert operations.
|
* Required data for sync cipher upsert operations.
|
||||||
*
|
*
|
||||||
|
* @property userId The user ID associated with this update.
|
||||||
* @property cipherId The cipher ID.
|
* @property cipherId The cipher ID.
|
||||||
* @property revisionDate The cipher's revision date. This is used to determine if the local copy of
|
* @property revisionDate The cipher's revision date. This is used to determine if the local copy of
|
||||||
* the cipher is out-of-date.
|
* the cipher is out-of-date.
|
||||||
* @property isUpdate Whether or not this is an update of an existing cipher.
|
* @property isUpdate Whether or not this is an update of an existing cipher.
|
||||||
*/
|
*/
|
||||||
data class SyncCipherUpsertData(
|
data class SyncCipherUpsertData(
|
||||||
|
val userId: String,
|
||||||
val cipherId: String,
|
val cipherId: String,
|
||||||
val revisionDate: ZonedDateTime,
|
val revisionDate: ZonedDateTime,
|
||||||
val organizationId: String?,
|
val organizationId: String?,
|
||||||
|
|||||||
@ -5,12 +5,14 @@ import java.time.ZonedDateTime
|
|||||||
/**
|
/**
|
||||||
* Required data for sync folder upsert operations.
|
* Required data for sync folder upsert operations.
|
||||||
*
|
*
|
||||||
|
* @property userId The user ID associated with this update.
|
||||||
* @property folderId The folder ID.
|
* @property folderId The folder ID.
|
||||||
* @property revisionDate The folder's revision date. This is used to determine if the local copy of
|
* @property revisionDate The folder's revision date. This is used to determine if the local copy of
|
||||||
* the folder is out-of-date.
|
* the folder is out-of-date.
|
||||||
* @property isUpdate Whether or not this is an update of an existing folder.
|
* @property isUpdate Whether or not this is an update of an existing folder.
|
||||||
*/
|
*/
|
||||||
data class SyncFolderUpsertData(
|
data class SyncFolderUpsertData(
|
||||||
|
val userId: String,
|
||||||
val folderId: String,
|
val folderId: String,
|
||||||
val revisionDate: ZonedDateTime,
|
val revisionDate: ZonedDateTime,
|
||||||
val isUpdate: Boolean,
|
val isUpdate: Boolean,
|
||||||
|
|||||||
@ -5,12 +5,14 @@ import java.time.ZonedDateTime
|
|||||||
/**
|
/**
|
||||||
* Required data for sync send upsert operations.
|
* Required data for sync send upsert operations.
|
||||||
*
|
*
|
||||||
|
* @property userId The user ID associated with this update.
|
||||||
* @property sendId The send ID.
|
* @property sendId The send ID.
|
||||||
* @property revisionDate The send's revision date. This is used to determine if the local copy of
|
* @property revisionDate The send's revision date. This is used to determine if the local copy of
|
||||||
* the send is out-of-date.
|
* the send is out-of-date.
|
||||||
* @property isUpdate Whether or not this is an update of an existing send.
|
* @property isUpdate Whether or not this is an update of an existing send.
|
||||||
*/
|
*/
|
||||||
data class SyncSendUpsertData(
|
data class SyncSendUpsertData(
|
||||||
|
val userId: String,
|
||||||
val sendId: String,
|
val sendId: String,
|
||||||
val revisionDate: ZonedDateTime,
|
val revisionDate: ZonedDateTime,
|
||||||
val isUpdate: Boolean,
|
val isUpdate: Boolean,
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import com.bitwarden.vault.AttachmentView
|
|||||||
import com.bitwarden.vault.CipherView
|
import com.bitwarden.vault.CipherView
|
||||||
import com.bitwarden.vault.EncryptionContext
|
import com.bitwarden.vault.EncryptionContext
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
|
import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.disk.SettingsDiskSource
|
||||||
import com.x8bit.bitwarden.data.platform.error.NoActiveUserException
|
import com.x8bit.bitwarden.data.platform.error.NoActiveUserException
|
||||||
import com.x8bit.bitwarden.data.platform.manager.PushManager
|
import com.x8bit.bitwarden.data.platform.manager.PushManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.ReviewPromptManager
|
import com.x8bit.bitwarden.data.platform.manager.ReviewPromptManager
|
||||||
@ -53,6 +54,7 @@ import java.time.Clock
|
|||||||
class CipherManagerImpl(
|
class CipherManagerImpl(
|
||||||
private val fileManager: FileManager,
|
private val fileManager: FileManager,
|
||||||
private val authDiskSource: AuthDiskSource,
|
private val authDiskSource: AuthDiskSource,
|
||||||
|
private val settingsDiskSource: SettingsDiskSource,
|
||||||
private val ciphersService: CiphersService,
|
private val ciphersService: CiphersService,
|
||||||
private val vaultDiskSource: VaultDiskSource,
|
private val vaultDiskSource: VaultDiskSource,
|
||||||
private val vaultSdkSource: VaultSdkSource,
|
private val vaultSdkSource: VaultSdkSource,
|
||||||
@ -689,7 +691,7 @@ class CipherManagerImpl(
|
|||||||
* for now.
|
* for now.
|
||||||
*/
|
*/
|
||||||
private suspend fun syncCipherIfNecessary(syncCipherUpsertData: SyncCipherUpsertData) {
|
private suspend fun syncCipherIfNecessary(syncCipherUpsertData: SyncCipherUpsertData) {
|
||||||
val userId = activeUserId ?: return
|
val userId = syncCipherUpsertData.userId
|
||||||
val cipherId = syncCipherUpsertData.cipherId
|
val cipherId = syncCipherUpsertData.cipherId
|
||||||
val organizationId = syncCipherUpsertData.organizationId
|
val organizationId = syncCipherUpsertData.organizationId
|
||||||
val collectionIds = syncCipherUpsertData.collectionIds
|
val collectionIds = syncCipherUpsertData.collectionIds
|
||||||
@ -732,6 +734,12 @@ class CipherManagerImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!shouldUpdate) return
|
if (!shouldUpdate) return
|
||||||
|
if (activeUserId != userId) {
|
||||||
|
// We cannot update right now since the accounts do not match, so we will
|
||||||
|
// do a full-sync on the next check.
|
||||||
|
settingsDiskSource.storeLastSyncTime(userId = userId, lastSyncTime = null)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
ciphersService
|
ciphersService
|
||||||
.getCipher(cipherId = cipherId)
|
.getCipher(cipherId = cipherId)
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import com.bitwarden.network.model.UpdateFolderResponseJson
|
|||||||
import com.bitwarden.network.service.FolderService
|
import com.bitwarden.network.service.FolderService
|
||||||
import com.bitwarden.vault.FolderView
|
import com.bitwarden.vault.FolderView
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
|
import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.disk.SettingsDiskSource
|
||||||
import com.x8bit.bitwarden.data.platform.error.NoActiveUserException
|
import com.x8bit.bitwarden.data.platform.error.NoActiveUserException
|
||||||
import com.x8bit.bitwarden.data.platform.manager.PushManager
|
import com.x8bit.bitwarden.data.platform.manager.PushManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.model.SyncFolderDeleteData
|
import com.x8bit.bitwarden.data.platform.manager.model.SyncFolderDeleteData
|
||||||
@ -25,8 +26,10 @@ import kotlinx.coroutines.flow.onEach
|
|||||||
/**
|
/**
|
||||||
* The default implementation of the [FolderManager].
|
* The default implementation of the [FolderManager].
|
||||||
*/
|
*/
|
||||||
|
@Suppress("LongParameterList")
|
||||||
class FolderManagerImpl(
|
class FolderManagerImpl(
|
||||||
private val authDiskSource: AuthDiskSource,
|
private val authDiskSource: AuthDiskSource,
|
||||||
|
private val settingsDiskSource: SettingsDiskSource,
|
||||||
private val folderService: FolderService,
|
private val folderService: FolderService,
|
||||||
private val vaultDiskSource: VaultDiskSource,
|
private val vaultDiskSource: VaultDiskSource,
|
||||||
private val vaultSdkSource: VaultSdkSource,
|
private val vaultSdkSource: VaultSdkSource,
|
||||||
@ -148,7 +151,7 @@ class FolderManagerImpl(
|
|||||||
* are met.
|
* are met.
|
||||||
*/
|
*/
|
||||||
private suspend fun syncFolderIfNecessary(syncFolderUpsertData: SyncFolderUpsertData) {
|
private suspend fun syncFolderIfNecessary(syncFolderUpsertData: SyncFolderUpsertData) {
|
||||||
val userId = activeUserId ?: return
|
val userId = syncFolderUpsertData.userId
|
||||||
val folderId = syncFolderUpsertData.folderId
|
val folderId = syncFolderUpsertData.folderId
|
||||||
val isUpdate = syncFolderUpsertData.isUpdate
|
val isUpdate = syncFolderUpsertData.isUpdate
|
||||||
val revisionDate = syncFolderUpsertData.revisionDate
|
val revisionDate = syncFolderUpsertData.revisionDate
|
||||||
@ -162,6 +165,12 @@ class FolderManagerImpl(
|
|||||||
localFolder.revisionDate.toEpochSecond() < revisionDate.toEpochSecond()
|
localFolder.revisionDate.toEpochSecond() < revisionDate.toEpochSecond()
|
||||||
|
|
||||||
if (!isValidCreate && !isValidUpdate) return
|
if (!isValidCreate && !isValidUpdate) return
|
||||||
|
if (activeUserId != userId) {
|
||||||
|
// We cannot update right now since the accounts do not match, so we will
|
||||||
|
// do a full-sync on the next check.
|
||||||
|
settingsDiskSource.storeLastSyncTime(userId = userId, lastSyncTime = null)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
folderService
|
folderService
|
||||||
.getFolder(folderId = folderId)
|
.getFolder(folderId = folderId)
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import com.bitwarden.send.Send
|
|||||||
import com.bitwarden.send.SendType
|
import com.bitwarden.send.SendType
|
||||||
import com.bitwarden.send.SendView
|
import com.bitwarden.send.SendView
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
|
import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.disk.SettingsDiskSource
|
||||||
import com.x8bit.bitwarden.data.platform.error.NoActiveUserException
|
import com.x8bit.bitwarden.data.platform.error.NoActiveUserException
|
||||||
import com.x8bit.bitwarden.data.platform.manager.PushManager
|
import com.x8bit.bitwarden.data.platform.manager.PushManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.ReviewPromptManager
|
import com.x8bit.bitwarden.data.platform.manager.ReviewPromptManager
|
||||||
@ -38,6 +39,7 @@ import retrofit2.HttpException
|
|||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
class SendManagerImpl(
|
class SendManagerImpl(
|
||||||
private val authDiskSource: AuthDiskSource,
|
private val authDiskSource: AuthDiskSource,
|
||||||
|
private val settingsDiskSource: SettingsDiskSource,
|
||||||
private val vaultDiskSource: VaultDiskSource,
|
private val vaultDiskSource: VaultDiskSource,
|
||||||
private val vaultSdkSource: VaultSdkSource,
|
private val vaultSdkSource: VaultSdkSource,
|
||||||
private val sendsService: SendsService,
|
private val sendsService: SendsService,
|
||||||
@ -265,7 +267,7 @@ class SendManagerImpl(
|
|||||||
* now.
|
* now.
|
||||||
*/
|
*/
|
||||||
private suspend fun syncSendIfNecessary(syncSendUpsertData: SyncSendUpsertData) {
|
private suspend fun syncSendIfNecessary(syncSendUpsertData: SyncSendUpsertData) {
|
||||||
val userId = activeUserId ?: return
|
val userId = syncSendUpsertData.userId
|
||||||
val sendId = syncSendUpsertData.sendId
|
val sendId = syncSendUpsertData.sendId
|
||||||
val isUpdate = syncSendUpsertData.isUpdate
|
val isUpdate = syncSendUpsertData.isUpdate
|
||||||
val revisionDate = syncSendUpsertData.revisionDate
|
val revisionDate = syncSendUpsertData.revisionDate
|
||||||
@ -278,6 +280,12 @@ class SendManagerImpl(
|
|||||||
localSend != null &&
|
localSend != null &&
|
||||||
localSend.revisionDate.toEpochSecond() < revisionDate.toEpochSecond()
|
localSend.revisionDate.toEpochSecond() < revisionDate.toEpochSecond()
|
||||||
if (!isValidCreate && !isValidUpdate) return
|
if (!isValidCreate && !isValidUpdate) return
|
||||||
|
if (activeUserId != userId) {
|
||||||
|
// We cannot update right now since the accounts do not match, so we will
|
||||||
|
// do a full-sync on the next check.
|
||||||
|
settingsDiskSource.storeLastSyncTime(userId = userId, lastSyncTime = null)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
sendsService
|
sendsService
|
||||||
.getSend(sendId = sendId)
|
.getSend(sendId = sendId)
|
||||||
|
|||||||
@ -61,6 +61,7 @@ object VaultManagerModule {
|
|||||||
@Singleton
|
@Singleton
|
||||||
fun provideCipherManager(
|
fun provideCipherManager(
|
||||||
ciphersService: CiphersService,
|
ciphersService: CiphersService,
|
||||||
|
settingsDiskSource: SettingsDiskSource,
|
||||||
vaultDiskSource: VaultDiskSource,
|
vaultDiskSource: VaultDiskSource,
|
||||||
vaultSdkSource: VaultSdkSource,
|
vaultSdkSource: VaultSdkSource,
|
||||||
authDiskSource: AuthDiskSource,
|
authDiskSource: AuthDiskSource,
|
||||||
@ -71,6 +72,7 @@ object VaultManagerModule {
|
|||||||
pushManager: PushManager,
|
pushManager: PushManager,
|
||||||
): CipherManager = CipherManagerImpl(
|
): CipherManager = CipherManagerImpl(
|
||||||
fileManager = fileManager,
|
fileManager = fileManager,
|
||||||
|
settingsDiskSource = settingsDiskSource,
|
||||||
authDiskSource = authDiskSource,
|
authDiskSource = authDiskSource,
|
||||||
ciphersService = ciphersService,
|
ciphersService = ciphersService,
|
||||||
vaultDiskSource = vaultDiskSource,
|
vaultDiskSource = vaultDiskSource,
|
||||||
@ -85,6 +87,7 @@ object VaultManagerModule {
|
|||||||
@Singleton
|
@Singleton
|
||||||
fun provideFolderManager(
|
fun provideFolderManager(
|
||||||
folderService: FolderService,
|
folderService: FolderService,
|
||||||
|
settingsDiskSource: SettingsDiskSource,
|
||||||
vaultDiskSource: VaultDiskSource,
|
vaultDiskSource: VaultDiskSource,
|
||||||
vaultSdkSource: VaultSdkSource,
|
vaultSdkSource: VaultSdkSource,
|
||||||
authDiskSource: AuthDiskSource,
|
authDiskSource: AuthDiskSource,
|
||||||
@ -92,6 +95,7 @@ object VaultManagerModule {
|
|||||||
pushManager: PushManager,
|
pushManager: PushManager,
|
||||||
): FolderManager = FolderManagerImpl(
|
): FolderManager = FolderManagerImpl(
|
||||||
authDiskSource = authDiskSource,
|
authDiskSource = authDiskSource,
|
||||||
|
settingsDiskSource = settingsDiskSource,
|
||||||
folderService = folderService,
|
folderService = folderService,
|
||||||
vaultDiskSource = vaultDiskSource,
|
vaultDiskSource = vaultDiskSource,
|
||||||
vaultSdkSource = vaultSdkSource,
|
vaultSdkSource = vaultSdkSource,
|
||||||
@ -106,6 +110,7 @@ object VaultManagerModule {
|
|||||||
vaultDiskSource: VaultDiskSource,
|
vaultDiskSource: VaultDiskSource,
|
||||||
vaultSdkSource: VaultSdkSource,
|
vaultSdkSource: VaultSdkSource,
|
||||||
authDiskSource: AuthDiskSource,
|
authDiskSource: AuthDiskSource,
|
||||||
|
settingsDiskSource: SettingsDiskSource,
|
||||||
fileManager: FileManager,
|
fileManager: FileManager,
|
||||||
reviewPromptManager: ReviewPromptManager,
|
reviewPromptManager: ReviewPromptManager,
|
||||||
pushManager: PushManager,
|
pushManager: PushManager,
|
||||||
@ -113,6 +118,7 @@ object VaultManagerModule {
|
|||||||
): SendManager = SendManagerImpl(
|
): SendManager = SendManagerImpl(
|
||||||
fileManager = fileManager,
|
fileManager = fileManager,
|
||||||
authDiskSource = authDiskSource,
|
authDiskSource = authDiskSource,
|
||||||
|
settingsDiskSource = settingsDiskSource,
|
||||||
sendsService = sendsService,
|
sendsService = sendsService,
|
||||||
vaultDiskSource = vaultDiskSource,
|
vaultDiskSource = vaultDiskSource,
|
||||||
vaultSdkSource = vaultSdkSource,
|
vaultSdkSource = vaultSdkSource,
|
||||||
|
|||||||
@ -260,6 +260,7 @@ class PushManagerTest {
|
|||||||
pushManager.onMessageReceived(SYNC_CIPHER_CREATE_NOTIFICATION_MAP)
|
pushManager.onMessageReceived(SYNC_CIPHER_CREATE_NOTIFICATION_MAP)
|
||||||
assertEquals(
|
assertEquals(
|
||||||
SyncCipherUpsertData(
|
SyncCipherUpsertData(
|
||||||
|
userId = "078966a2-93c2-4618-ae2a-0a2394c88d37",
|
||||||
cipherId = "aab5cdcc-f4a7-4e65-bf6d-5e0eab052321",
|
cipherId = "aab5cdcc-f4a7-4e65-bf6d-5e0eab052321",
|
||||||
organizationId = "6a41d965-ed95-4eae-98c3-5f1ec609c2c1",
|
organizationId = "6a41d965-ed95-4eae-98c3-5f1ec609c2c1",
|
||||||
collectionIds = listOf(),
|
collectionIds = listOf(),
|
||||||
@ -293,6 +294,7 @@ class PushManagerTest {
|
|||||||
pushManager.onMessageReceived(SYNC_CIPHER_UPDATE_NOTIFICATION_MAP)
|
pushManager.onMessageReceived(SYNC_CIPHER_UPDATE_NOTIFICATION_MAP)
|
||||||
assertEquals(
|
assertEquals(
|
||||||
SyncCipherUpsertData(
|
SyncCipherUpsertData(
|
||||||
|
userId = "078966a2-93c2-4618-ae2a-0a2394c88d37",
|
||||||
cipherId = "aab5cdcc-f4a7-4e65-bf6d-5e0eab052321",
|
cipherId = "aab5cdcc-f4a7-4e65-bf6d-5e0eab052321",
|
||||||
organizationId = "6a41d965-ed95-4eae-98c3-5f1ec609c2c1",
|
organizationId = "6a41d965-ed95-4eae-98c3-5f1ec609c2c1",
|
||||||
collectionIds = listOf(),
|
collectionIds = listOf(),
|
||||||
@ -311,6 +313,7 @@ class PushManagerTest {
|
|||||||
pushManager.onMessageReceived(SYNC_FOLDER_CREATE_NOTIFICATION_MAP)
|
pushManager.onMessageReceived(SYNC_FOLDER_CREATE_NOTIFICATION_MAP)
|
||||||
assertEquals(
|
assertEquals(
|
||||||
SyncFolderUpsertData(
|
SyncFolderUpsertData(
|
||||||
|
userId = "078966a2-93c2-4618-ae2a-0a2394c88d37",
|
||||||
folderId = "aab5cdcc-f4a7-4e65-bf6d-5e0eab052321",
|
folderId = "aab5cdcc-f4a7-4e65-bf6d-5e0eab052321",
|
||||||
revisionDate = ZonedDateTime.parse("2023-10-27T12:00:00.000Z"),
|
revisionDate = ZonedDateTime.parse("2023-10-27T12:00:00.000Z"),
|
||||||
isUpdate = false,
|
isUpdate = false,
|
||||||
@ -342,6 +345,7 @@ class PushManagerTest {
|
|||||||
pushManager.onMessageReceived(SYNC_FOLDER_UPDATE_NOTIFICATION_MAP)
|
pushManager.onMessageReceived(SYNC_FOLDER_UPDATE_NOTIFICATION_MAP)
|
||||||
assertEquals(
|
assertEquals(
|
||||||
SyncFolderUpsertData(
|
SyncFolderUpsertData(
|
||||||
|
userId = "078966a2-93c2-4618-ae2a-0a2394c88d37",
|
||||||
folderId = "aab5cdcc-f4a7-4e65-bf6d-5e0eab052321",
|
folderId = "aab5cdcc-f4a7-4e65-bf6d-5e0eab052321",
|
||||||
revisionDate = ZonedDateTime.parse("2023-10-27T12:00:00.000Z"),
|
revisionDate = ZonedDateTime.parse("2023-10-27T12:00:00.000Z"),
|
||||||
isUpdate = true,
|
isUpdate = true,
|
||||||
@ -372,6 +376,7 @@ class PushManagerTest {
|
|||||||
pushManager.onMessageReceived(SYNC_SEND_CREATE_NOTIFICATION_MAP)
|
pushManager.onMessageReceived(SYNC_SEND_CREATE_NOTIFICATION_MAP)
|
||||||
assertEquals(
|
assertEquals(
|
||||||
SyncSendUpsertData(
|
SyncSendUpsertData(
|
||||||
|
userId = "078966a2-93c2-4618-ae2a-0a2394c88d37",
|
||||||
sendId = "aab5cdcc-f4a7-4e65-bf6d-5e0eab052321",
|
sendId = "aab5cdcc-f4a7-4e65-bf6d-5e0eab052321",
|
||||||
revisionDate = ZonedDateTime.parse("2023-10-27T12:00:00.000Z"),
|
revisionDate = ZonedDateTime.parse("2023-10-27T12:00:00.000Z"),
|
||||||
isUpdate = false,
|
isUpdate = false,
|
||||||
@ -401,6 +406,7 @@ class PushManagerTest {
|
|||||||
pushManager.onMessageReceived(SYNC_SEND_UPDATE_NOTIFICATION_MAP)
|
pushManager.onMessageReceived(SYNC_SEND_UPDATE_NOTIFICATION_MAP)
|
||||||
assertEquals(
|
assertEquals(
|
||||||
SyncSendUpsertData(
|
SyncSendUpsertData(
|
||||||
|
userId = "078966a2-93c2-4618-ae2a-0a2394c88d37",
|
||||||
sendId = "aab5cdcc-f4a7-4e65-bf6d-5e0eab052321",
|
sendId = "aab5cdcc-f4a7-4e65-bf6d-5e0eab052321",
|
||||||
revisionDate = ZonedDateTime.parse("2023-10-27T12:00:00.000Z"),
|
revisionDate = ZonedDateTime.parse("2023-10-27T12:00:00.000Z"),
|
||||||
isUpdate = true,
|
isUpdate = true,
|
||||||
@ -437,12 +443,13 @@ class PushManagerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `onMessageReceived with sync cipher create does nothing`() = runTest {
|
fun `onMessageReceived with sync cipher create emits to syncCipherUpsertFlow`() =
|
||||||
pushManager.syncCipherUpsertFlow.test {
|
runTest {
|
||||||
pushManager.onMessageReceived(SYNC_CIPHER_CREATE_NOTIFICATION_MAP)
|
pushManager.syncCipherUpsertFlow.test {
|
||||||
expectNoEvents()
|
pushManager.onMessageReceived(SYNC_CIPHER_CREATE_NOTIFICATION_MAP)
|
||||||
|
expectNoEvents()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `onMessageReceived with sync cipher delete does nothing`() = runTest {
|
fun `onMessageReceived with sync cipher delete does nothing`() = runTest {
|
||||||
@ -459,12 +466,13 @@ class PushManagerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `onMessageReceived with sync cipher update does nothing`() = runTest {
|
fun `onMessageReceived with sync cipher update emits to syncCipherUpsertFlow`() =
|
||||||
pushManager.syncCipherUpsertFlow.test {
|
runTest {
|
||||||
pushManager.onMessageReceived(SYNC_CIPHER_UPDATE_NOTIFICATION_MAP)
|
pushManager.syncCipherUpsertFlow.test {
|
||||||
expectNoEvents()
|
pushManager.onMessageReceived(SYNC_CIPHER_UPDATE_NOTIFICATION_MAP)
|
||||||
|
expectNoEvents()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `onMessageReceived with sync folder create does nothing`() = runTest {
|
fun `onMessageReceived with sync folder create does nothing`() = runTest {
|
||||||
@ -543,62 +551,6 @@ class PushManagerTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
|
||||||
inner class NullUserState {
|
|
||||||
@BeforeEach
|
|
||||||
fun setUp() {
|
|
||||||
authDiskSource.userState = null
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `onMessageReceived with logout does nothing`() = runTest {
|
|
||||||
pushManager.logoutFlow.test {
|
|
||||||
pushManager.onMessageReceived(LOGOUT_NOTIFICATION_MAP)
|
|
||||||
expectNoEvents()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `onMessageReceived with logout with kdf reason does nothing`() = runTest {
|
|
||||||
pushManager.logoutFlow.test {
|
|
||||||
pushManager.onMessageReceived(LOGOUT_KDF_NOTIFICATION_MAP)
|
|
||||||
expectNoEvents()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `onMessageReceived with sync ciphers does nothing`() = runTest {
|
|
||||||
pushManager.fullSyncFlow.test {
|
|
||||||
pushManager.onMessageReceived(SYNC_CIPHERS_NOTIFICATION_MAP)
|
|
||||||
expectNoEvents()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `onMessageReceived with sync org keys does nothing`() = runTest {
|
|
||||||
pushManager.fullSyncFlow.test {
|
|
||||||
pushManager.onMessageReceived(SYNC_ORG_KEYS_NOTIFICATION_MAP)
|
|
||||||
expectNoEvents()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `onMessageReceived with sync settings does nothing`() = runTest {
|
|
||||||
pushManager.fullSyncFlow.test {
|
|
||||||
pushManager.onMessageReceived(SYNC_SETTINGS_NOTIFICATION_MAP)
|
|
||||||
expectNoEvents()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `onMessageReceived with sync vault does nothing`() = runTest {
|
|
||||||
pushManager.fullSyncFlow.test {
|
|
||||||
pushManager.onMessageReceived(SYNC_VAULT_NOTIFICATION_MAP)
|
|
||||||
expectNoEvents()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
inner class NonNullUserState {
|
inner class NonNullUserState {
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
|
|||||||
@ -29,6 +29,7 @@ import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountJson
|
|||||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountTokensJson
|
import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountTokensJson
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.UserStateJson
|
import com.x8bit.bitwarden.data.auth.datasource.disk.model.UserStateJson
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.disk.util.FakeAuthDiskSource
|
import com.x8bit.bitwarden.data.auth.datasource.disk.util.FakeAuthDiskSource
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.disk.util.FakeSettingsDiskSource
|
||||||
import com.x8bit.bitwarden.data.platform.error.NoActiveUserException
|
import com.x8bit.bitwarden.data.platform.error.NoActiveUserException
|
||||||
import com.x8bit.bitwarden.data.platform.manager.PushManager
|
import com.x8bit.bitwarden.data.platform.manager.PushManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.ReviewPromptManager
|
import com.x8bit.bitwarden.data.platform.manager.ReviewPromptManager
|
||||||
@ -91,6 +92,7 @@ class CipherManagerTest {
|
|||||||
coEvery { delete(*anyVararg()) } just runs
|
coEvery { delete(*anyVararg()) } just runs
|
||||||
}
|
}
|
||||||
private val fakeAuthDiskSource = FakeAuthDiskSource()
|
private val fakeAuthDiskSource = FakeAuthDiskSource()
|
||||||
|
private val fakeSettingsDiskSource = FakeSettingsDiskSource()
|
||||||
private val ciphersService: CiphersService = mockk()
|
private val ciphersService: CiphersService = mockk()
|
||||||
private val vaultDiskSource: VaultDiskSource = mockk()
|
private val vaultDiskSource: VaultDiskSource = mockk()
|
||||||
private val vaultSdkSource: VaultSdkSource = mockk()
|
private val vaultSdkSource: VaultSdkSource = mockk()
|
||||||
@ -106,6 +108,7 @@ class CipherManagerTest {
|
|||||||
|
|
||||||
private val cipherManager: CipherManager = CipherManagerImpl(
|
private val cipherManager: CipherManager = CipherManagerImpl(
|
||||||
ciphersService = ciphersService,
|
ciphersService = ciphersService,
|
||||||
|
settingsDiskSource = fakeSettingsDiskSource,
|
||||||
vaultDiskSource = vaultDiskSource,
|
vaultDiskSource = vaultDiskSource,
|
||||||
vaultSdkSource = vaultSdkSource,
|
vaultSdkSource = vaultSdkSource,
|
||||||
authDiskSource = fakeAuthDiskSource,
|
authDiskSource = fakeAuthDiskSource,
|
||||||
@ -2403,6 +2406,7 @@ class CipherManagerTest {
|
|||||||
|
|
||||||
mutableSyncCipherUpsertFlow.tryEmit(
|
mutableSyncCipherUpsertFlow.tryEmit(
|
||||||
SyncCipherUpsertData(
|
SyncCipherUpsertData(
|
||||||
|
userId = userId,
|
||||||
cipherId = cipherId,
|
cipherId = cipherId,
|
||||||
revisionDate = ZonedDateTime.now(clock),
|
revisionDate = ZonedDateTime.now(clock),
|
||||||
isUpdate = false,
|
isUpdate = false,
|
||||||
@ -2450,6 +2454,7 @@ class CipherManagerTest {
|
|||||||
|
|
||||||
mutableSyncCipherUpsertFlow.tryEmit(
|
mutableSyncCipherUpsertFlow.tryEmit(
|
||||||
SyncCipherUpsertData(
|
SyncCipherUpsertData(
|
||||||
|
userId = userId,
|
||||||
cipherId = cipherId,
|
cipherId = cipherId,
|
||||||
revisionDate = ZonedDateTime.now(clock),
|
revisionDate = ZonedDateTime.now(clock),
|
||||||
isUpdate = false,
|
isUpdate = false,
|
||||||
@ -2492,6 +2497,7 @@ class CipherManagerTest {
|
|||||||
|
|
||||||
mutableSyncCipherUpsertFlow.tryEmit(
|
mutableSyncCipherUpsertFlow.tryEmit(
|
||||||
SyncCipherUpsertData(
|
SyncCipherUpsertData(
|
||||||
|
userId = userId,
|
||||||
cipherId = cipherId,
|
cipherId = cipherId,
|
||||||
revisionDate = ZonedDateTime.now(clock),
|
revisionDate = ZonedDateTime.now(clock),
|
||||||
isUpdate = true,
|
isUpdate = true,
|
||||||
@ -2518,6 +2524,7 @@ class CipherManagerTest {
|
|||||||
|
|
||||||
mutableSyncCipherUpsertFlow.tryEmit(
|
mutableSyncCipherUpsertFlow.tryEmit(
|
||||||
SyncCipherUpsertData(
|
SyncCipherUpsertData(
|
||||||
|
userId = userId,
|
||||||
cipherId = cipherId,
|
cipherId = cipherId,
|
||||||
revisionDate = ZonedDateTime.now(clock),
|
revisionDate = ZonedDateTime.now(clock),
|
||||||
isUpdate = true,
|
isUpdate = true,
|
||||||
@ -2552,6 +2559,7 @@ class CipherManagerTest {
|
|||||||
|
|
||||||
mutableSyncCipherUpsertFlow.tryEmit(
|
mutableSyncCipherUpsertFlow.tryEmit(
|
||||||
SyncCipherUpsertData(
|
SyncCipherUpsertData(
|
||||||
|
userId = userId,
|
||||||
cipherId = cipherId,
|
cipherId = cipherId,
|
||||||
revisionDate = ZonedDateTime.now(clock).minus(5, ChronoUnit.MINUTES),
|
revisionDate = ZonedDateTime.now(clock).minus(5, ChronoUnit.MINUTES),
|
||||||
isUpdate = true,
|
isUpdate = true,
|
||||||
@ -2589,6 +2597,7 @@ class CipherManagerTest {
|
|||||||
|
|
||||||
mutableSyncCipherUpsertFlow.tryEmit(
|
mutableSyncCipherUpsertFlow.tryEmit(
|
||||||
SyncCipherUpsertData(
|
SyncCipherUpsertData(
|
||||||
|
userId = userId,
|
||||||
cipherId = cipherId,
|
cipherId = cipherId,
|
||||||
revisionDate = ZonedDateTime.now(clock),
|
revisionDate = ZonedDateTime.now(clock),
|
||||||
isUpdate = true,
|
isUpdate = true,
|
||||||
@ -2620,6 +2629,7 @@ class CipherManagerTest {
|
|||||||
|
|
||||||
mutableSyncCipherUpsertFlow.tryEmit(
|
mutableSyncCipherUpsertFlow.tryEmit(
|
||||||
SyncCipherUpsertData(
|
SyncCipherUpsertData(
|
||||||
|
userId = userId,
|
||||||
cipherId = cipherId,
|
cipherId = cipherId,
|
||||||
revisionDate = ZonedDateTime.now(clock),
|
revisionDate = ZonedDateTime.now(clock),
|
||||||
isUpdate = false,
|
isUpdate = false,
|
||||||
@ -2659,6 +2669,7 @@ class CipherManagerTest {
|
|||||||
|
|
||||||
mutableSyncCipherUpsertFlow.tryEmit(
|
mutableSyncCipherUpsertFlow.tryEmit(
|
||||||
SyncCipherUpsertData(
|
SyncCipherUpsertData(
|
||||||
|
userId = userId,
|
||||||
cipherId = cipherId,
|
cipherId = cipherId,
|
||||||
revisionDate = ZonedDateTime.now(clock),
|
revisionDate = ZonedDateTime.now(clock),
|
||||||
isUpdate = false,
|
isUpdate = false,
|
||||||
@ -2697,6 +2708,7 @@ class CipherManagerTest {
|
|||||||
|
|
||||||
mutableSyncCipherUpsertFlow.tryEmit(
|
mutableSyncCipherUpsertFlow.tryEmit(
|
||||||
SyncCipherUpsertData(
|
SyncCipherUpsertData(
|
||||||
|
userId = userId,
|
||||||
cipherId = cipherId,
|
cipherId = cipherId,
|
||||||
revisionDate = ZonedDateTime.now(clock),
|
revisionDate = ZonedDateTime.now(clock),
|
||||||
isUpdate = true,
|
isUpdate = true,
|
||||||
@ -2712,6 +2724,43 @@ class CipherManagerTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `syncCipherUpsertFlow with inactive userId should clear the last sync time`() = runTest {
|
||||||
|
val number = 1
|
||||||
|
val userId = "nonActiveUserId"
|
||||||
|
val cipherId = "mockId-$number"
|
||||||
|
val originalCipher = mockk<SyncResponseJson.Cipher> {
|
||||||
|
every { revisionDate } returns ZonedDateTime.now(clock).minus(5, ChronoUnit.MINUTES)
|
||||||
|
}
|
||||||
|
val lastSyncTime = clock.instant()
|
||||||
|
|
||||||
|
fakeSettingsDiskSource.storeLastSyncTime(userId = userId, lastSyncTime = lastSyncTime)
|
||||||
|
fakeAuthDiskSource.userState = MOCK_USER_STATE
|
||||||
|
coEvery {
|
||||||
|
vaultDiskSource.getCipher(userId = userId, cipherId = cipherId)
|
||||||
|
} returns originalCipher
|
||||||
|
|
||||||
|
mutableSyncCipherUpsertFlow.tryEmit(
|
||||||
|
SyncCipherUpsertData(
|
||||||
|
userId = userId,
|
||||||
|
cipherId = cipherId,
|
||||||
|
revisionDate = ZonedDateTime.now(clock),
|
||||||
|
isUpdate = true,
|
||||||
|
collectionIds = null,
|
||||||
|
organizationId = null,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
fakeSettingsDiskSource.assertLastSyncTime(userId = userId, expected = null)
|
||||||
|
coVerify(exactly = 1) {
|
||||||
|
vaultDiskSource.getCipher(userId = userId, cipherId = cipherId)
|
||||||
|
}
|
||||||
|
coVerify(exactly = 0) {
|
||||||
|
ciphersService.getCipher(cipherId)
|
||||||
|
vaultDiskSource.saveCipher(userId = userId, cipher = any())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun setupMockUri(
|
private fun setupMockUri(
|
||||||
url: String,
|
url: String,
|
||||||
queryParams: Map<String, String> = emptyMap(),
|
queryParams: Map<String, String> = emptyMap(),
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountJson
|
|||||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountTokensJson
|
import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountTokensJson
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.UserStateJson
|
import com.x8bit.bitwarden.data.auth.datasource.disk.model.UserStateJson
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.disk.util.FakeAuthDiskSource
|
import com.x8bit.bitwarden.data.auth.datasource.disk.util.FakeAuthDiskSource
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.disk.util.FakeSettingsDiskSource
|
||||||
import com.x8bit.bitwarden.data.platform.error.NoActiveUserException
|
import com.x8bit.bitwarden.data.platform.error.NoActiveUserException
|
||||||
import com.x8bit.bitwarden.data.platform.manager.PushManager
|
import com.x8bit.bitwarden.data.platform.manager.PushManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.model.SyncFolderDeleteData
|
import com.x8bit.bitwarden.data.platform.manager.model.SyncFolderDeleteData
|
||||||
@ -49,6 +50,7 @@ import java.time.temporal.ChronoUnit
|
|||||||
|
|
||||||
class FolderManagerTest {
|
class FolderManagerTest {
|
||||||
private val fakeAuthDiskSource = FakeAuthDiskSource()
|
private val fakeAuthDiskSource = FakeAuthDiskSource()
|
||||||
|
private val fakeSettingsDiskSource = FakeSettingsDiskSource()
|
||||||
private val folderService = mockk<FolderService>()
|
private val folderService = mockk<FolderService>()
|
||||||
private val vaultDiskSource = mockk<VaultDiskSource>()
|
private val vaultDiskSource = mockk<VaultDiskSource>()
|
||||||
private val vaultSdkSource = mockk<VaultSdkSource>()
|
private val vaultSdkSource = mockk<VaultSdkSource>()
|
||||||
@ -61,6 +63,7 @@ class FolderManagerTest {
|
|||||||
|
|
||||||
private val folderManager: FolderManager = FolderManagerImpl(
|
private val folderManager: FolderManager = FolderManagerImpl(
|
||||||
authDiskSource = fakeAuthDiskSource,
|
authDiskSource = fakeAuthDiskSource,
|
||||||
|
settingsDiskSource = fakeSettingsDiskSource,
|
||||||
folderService = folderService,
|
folderService = folderService,
|
||||||
vaultDiskSource = vaultDiskSource,
|
vaultDiskSource = vaultDiskSource,
|
||||||
vaultSdkSource = vaultSdkSource,
|
vaultSdkSource = vaultSdkSource,
|
||||||
@ -435,6 +438,7 @@ class FolderManagerTest {
|
|||||||
|
|
||||||
mutableSyncFolderUpsertFlow.tryEmit(
|
mutableSyncFolderUpsertFlow.tryEmit(
|
||||||
SyncFolderUpsertData(
|
SyncFolderUpsertData(
|
||||||
|
userId = userId,
|
||||||
folderId = folderId,
|
folderId = folderId,
|
||||||
revisionDate = ZonedDateTime.now(FIXED_CLOCK),
|
revisionDate = ZonedDateTime.now(FIXED_CLOCK),
|
||||||
isUpdate = false,
|
isUpdate = false,
|
||||||
@ -460,6 +464,7 @@ class FolderManagerTest {
|
|||||||
|
|
||||||
mutableSyncFolderUpsertFlow.tryEmit(
|
mutableSyncFolderUpsertFlow.tryEmit(
|
||||||
SyncFolderUpsertData(
|
SyncFolderUpsertData(
|
||||||
|
userId = userId,
|
||||||
folderId = folderId,
|
folderId = folderId,
|
||||||
revisionDate = ZonedDateTime.now(FIXED_CLOCK),
|
revisionDate = ZonedDateTime.now(FIXED_CLOCK),
|
||||||
isUpdate = true,
|
isUpdate = true,
|
||||||
@ -486,6 +491,7 @@ class FolderManagerTest {
|
|||||||
|
|
||||||
mutableSyncFolderUpsertFlow.tryEmit(
|
mutableSyncFolderUpsertFlow.tryEmit(
|
||||||
SyncFolderUpsertData(
|
SyncFolderUpsertData(
|
||||||
|
userId = userId,
|
||||||
folderId = folderId,
|
folderId = folderId,
|
||||||
revisionDate = ZonedDateTime.ofInstant(
|
revisionDate = ZonedDateTime.ofInstant(
|
||||||
Instant.ofEpochSecond(0), ZoneId.of("UTC"),
|
Instant.ofEpochSecond(0), ZoneId.of("UTC"),
|
||||||
@ -518,6 +524,7 @@ class FolderManagerTest {
|
|||||||
|
|
||||||
mutableSyncFolderUpsertFlow.tryEmit(
|
mutableSyncFolderUpsertFlow.tryEmit(
|
||||||
SyncFolderUpsertData(
|
SyncFolderUpsertData(
|
||||||
|
userId = userId,
|
||||||
folderId = folderId,
|
folderId = folderId,
|
||||||
revisionDate = ZonedDateTime.now(FIXED_CLOCK),
|
revisionDate = ZonedDateTime.now(FIXED_CLOCK),
|
||||||
isUpdate = false,
|
isUpdate = false,
|
||||||
@ -552,6 +559,7 @@ class FolderManagerTest {
|
|||||||
|
|
||||||
mutableSyncFolderUpsertFlow.tryEmit(
|
mutableSyncFolderUpsertFlow.tryEmit(
|
||||||
SyncFolderUpsertData(
|
SyncFolderUpsertData(
|
||||||
|
userId = userId,
|
||||||
folderId = folderId,
|
folderId = folderId,
|
||||||
revisionDate = ZonedDateTime.now(FIXED_CLOCK),
|
revisionDate = ZonedDateTime.now(FIXED_CLOCK),
|
||||||
isUpdate = true,
|
isUpdate = true,
|
||||||
@ -563,6 +571,42 @@ class FolderManagerTest {
|
|||||||
vaultDiskSource.saveFolder(userId = userId, folder = folder)
|
vaultDiskSource.saveFolder(userId = userId, folder = folder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `syncFolderUpsertFlow with inactive userId should clear the last sync time`() = runTest {
|
||||||
|
val number = 1
|
||||||
|
val userId = "nonActiveUserId"
|
||||||
|
val folderId = "mockId-$number"
|
||||||
|
val lastSyncTime = FIXED_CLOCK.instant()
|
||||||
|
|
||||||
|
fakeSettingsDiskSource.storeLastSyncTime(userId = userId, lastSyncTime = lastSyncTime)
|
||||||
|
fakeAuthDiskSource.userState = MOCK_USER_STATE
|
||||||
|
val folderView = createMockFolder(
|
||||||
|
number = number,
|
||||||
|
revisionDate = ZonedDateTime.now(FIXED_CLOCK).minus(5, ChronoUnit.MINUTES),
|
||||||
|
)
|
||||||
|
coEvery {
|
||||||
|
vaultDiskSource.getFolders(userId = userId)
|
||||||
|
} returns MutableStateFlow(listOf(folderView))
|
||||||
|
|
||||||
|
mutableSyncFolderUpsertFlow.tryEmit(
|
||||||
|
SyncFolderUpsertData(
|
||||||
|
userId = userId,
|
||||||
|
folderId = folderId,
|
||||||
|
revisionDate = ZonedDateTime.now(FIXED_CLOCK),
|
||||||
|
isUpdate = true,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
fakeSettingsDiskSource.assertLastSyncTime(userId = userId, expected = null)
|
||||||
|
coVerify(exactly = 1) {
|
||||||
|
vaultDiskSource.getFolders(userId = userId)
|
||||||
|
}
|
||||||
|
coVerify(exactly = 0) {
|
||||||
|
folderService.getFolder(folderId = folderId)
|
||||||
|
vaultDiskSource.saveFolder(userId = userId, folder = any())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val FIXED_CLOCK: Clock = Clock.fixed(
|
private val FIXED_CLOCK: Clock = Clock.fixed(
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountJson
|
|||||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountTokensJson
|
import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountTokensJson
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.UserStateJson
|
import com.x8bit.bitwarden.data.auth.datasource.disk.model.UserStateJson
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.disk.util.FakeAuthDiskSource
|
import com.x8bit.bitwarden.data.auth.datasource.disk.util.FakeAuthDiskSource
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.disk.util.FakeSettingsDiskSource
|
||||||
import com.x8bit.bitwarden.data.platform.error.NoActiveUserException
|
import com.x8bit.bitwarden.data.platform.error.NoActiveUserException
|
||||||
import com.x8bit.bitwarden.data.platform.manager.PushManager
|
import com.x8bit.bitwarden.data.platform.manager.PushManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.ReviewPromptManager
|
import com.x8bit.bitwarden.data.platform.manager.ReviewPromptManager
|
||||||
@ -64,6 +65,7 @@ class SendManagerTest {
|
|||||||
coEvery { delete(files = anyVararg()) } just runs
|
coEvery { delete(files = anyVararg()) } just runs
|
||||||
}
|
}
|
||||||
private val fakeAuthDiskSource = FakeAuthDiskSource()
|
private val fakeAuthDiskSource = FakeAuthDiskSource()
|
||||||
|
private val fakeSettingsDiskSource = FakeSettingsDiskSource()
|
||||||
private val sendsService = mockk<SendsService>()
|
private val sendsService = mockk<SendsService>()
|
||||||
private val vaultDiskSource = mockk<VaultDiskSource>()
|
private val vaultDiskSource = mockk<VaultDiskSource>()
|
||||||
private val vaultSdkSource = mockk<VaultSdkSource>()
|
private val vaultSdkSource = mockk<VaultSdkSource>()
|
||||||
@ -82,6 +84,7 @@ class SendManagerTest {
|
|||||||
vaultDiskSource = vaultDiskSource,
|
vaultDiskSource = vaultDiskSource,
|
||||||
vaultSdkSource = vaultSdkSource,
|
vaultSdkSource = vaultSdkSource,
|
||||||
authDiskSource = fakeAuthDiskSource,
|
authDiskSource = fakeAuthDiskSource,
|
||||||
|
settingsDiskSource = fakeSettingsDiskSource,
|
||||||
fileManager = fileManager,
|
fileManager = fileManager,
|
||||||
reviewPromptManager = reviewPromptManager,
|
reviewPromptManager = reviewPromptManager,
|
||||||
pushManager = pushManager,
|
pushManager = pushManager,
|
||||||
@ -129,6 +132,7 @@ class SendManagerTest {
|
|||||||
|
|
||||||
mutableSyncSendUpsertFlow.tryEmit(
|
mutableSyncSendUpsertFlow.tryEmit(
|
||||||
SyncSendUpsertData(
|
SyncSendUpsertData(
|
||||||
|
userId = userId,
|
||||||
sendId = sendId,
|
sendId = sendId,
|
||||||
revisionDate = ZonedDateTime.now(FIXED_CLOCK),
|
revisionDate = ZonedDateTime.now(FIXED_CLOCK),
|
||||||
isUpdate = false,
|
isUpdate = false,
|
||||||
@ -152,6 +156,7 @@ class SendManagerTest {
|
|||||||
|
|
||||||
mutableSyncSendUpsertFlow.tryEmit(
|
mutableSyncSendUpsertFlow.tryEmit(
|
||||||
SyncSendUpsertData(
|
SyncSendUpsertData(
|
||||||
|
userId = userId,
|
||||||
sendId = sendId,
|
sendId = sendId,
|
||||||
revisionDate = ZonedDateTime.now(FIXED_CLOCK),
|
revisionDate = ZonedDateTime.now(FIXED_CLOCK),
|
||||||
isUpdate = true,
|
isUpdate = true,
|
||||||
@ -182,6 +187,7 @@ class SendManagerTest {
|
|||||||
|
|
||||||
mutableSyncSendUpsertFlow.tryEmit(
|
mutableSyncSendUpsertFlow.tryEmit(
|
||||||
SyncSendUpsertData(
|
SyncSendUpsertData(
|
||||||
|
userId = userId,
|
||||||
sendId = sendId,
|
sendId = sendId,
|
||||||
revisionDate = ZonedDateTime.now(FIXED_CLOCK).minus(5, ChronoUnit.MINUTES),
|
revisionDate = ZonedDateTime.now(FIXED_CLOCK).minus(5, ChronoUnit.MINUTES),
|
||||||
isUpdate = true,
|
isUpdate = true,
|
||||||
@ -221,6 +227,7 @@ class SendManagerTest {
|
|||||||
|
|
||||||
mutableSyncSendUpsertFlow.tryEmit(
|
mutableSyncSendUpsertFlow.tryEmit(
|
||||||
SyncSendUpsertData(
|
SyncSendUpsertData(
|
||||||
|
userId = userId,
|
||||||
sendId = sendId,
|
sendId = sendId,
|
||||||
revisionDate = ZonedDateTime.now(FIXED_CLOCK),
|
revisionDate = ZonedDateTime.now(FIXED_CLOCK),
|
||||||
isUpdate = true,
|
isUpdate = true,
|
||||||
@ -251,6 +258,7 @@ class SendManagerTest {
|
|||||||
|
|
||||||
mutableSyncSendUpsertFlow.tryEmit(
|
mutableSyncSendUpsertFlow.tryEmit(
|
||||||
SyncSendUpsertData(
|
SyncSendUpsertData(
|
||||||
|
userId = userId,
|
||||||
sendId = sendId,
|
sendId = sendId,
|
||||||
revisionDate = ZonedDateTime.now(FIXED_CLOCK),
|
revisionDate = ZonedDateTime.now(FIXED_CLOCK),
|
||||||
isUpdate = false,
|
isUpdate = false,
|
||||||
@ -283,6 +291,7 @@ class SendManagerTest {
|
|||||||
|
|
||||||
mutableSyncSendUpsertFlow.tryEmit(
|
mutableSyncSendUpsertFlow.tryEmit(
|
||||||
SyncSendUpsertData(
|
SyncSendUpsertData(
|
||||||
|
userId = userId,
|
||||||
sendId = sendId,
|
sendId = sendId,
|
||||||
revisionDate = ZonedDateTime.now(FIXED_CLOCK),
|
revisionDate = ZonedDateTime.now(FIXED_CLOCK),
|
||||||
isUpdate = false,
|
isUpdate = false,
|
||||||
@ -318,6 +327,7 @@ class SendManagerTest {
|
|||||||
|
|
||||||
mutableSyncSendUpsertFlow.tryEmit(
|
mutableSyncSendUpsertFlow.tryEmit(
|
||||||
SyncSendUpsertData(
|
SyncSendUpsertData(
|
||||||
|
userId = userId,
|
||||||
sendId = sendId,
|
sendId = sendId,
|
||||||
revisionDate = ZonedDateTime.now(FIXED_CLOCK),
|
revisionDate = ZonedDateTime.now(FIXED_CLOCK),
|
||||||
isUpdate = true,
|
isUpdate = true,
|
||||||
@ -330,6 +340,42 @@ class SendManagerTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `syncSendUpsertFlow with inactive userId should clear the last sync time`() = runTest {
|
||||||
|
val number = 1
|
||||||
|
val userId = "nonActiveUserId"
|
||||||
|
val sendId = "mockId-$number"
|
||||||
|
val lastSyncTime = FIXED_CLOCK.instant()
|
||||||
|
|
||||||
|
fakeSettingsDiskSource.storeLastSyncTime(userId = userId, lastSyncTime = lastSyncTime)
|
||||||
|
fakeAuthDiskSource.userState = MOCK_USER_STATE
|
||||||
|
val sendView = createMockSend(
|
||||||
|
number = number,
|
||||||
|
revisionDate = ZonedDateTime.now(FIXED_CLOCK).minus(5, ChronoUnit.MINUTES),
|
||||||
|
)
|
||||||
|
coEvery {
|
||||||
|
vaultDiskSource.getSends(userId = userId)
|
||||||
|
} returns MutableStateFlow(listOf(sendView))
|
||||||
|
|
||||||
|
mutableSyncSendUpsertFlow.tryEmit(
|
||||||
|
SyncSendUpsertData(
|
||||||
|
userId = userId,
|
||||||
|
sendId = sendId,
|
||||||
|
revisionDate = ZonedDateTime.now(FIXED_CLOCK),
|
||||||
|
isUpdate = true,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
fakeSettingsDiskSource.assertLastSyncTime(userId = userId, expected = null)
|
||||||
|
coVerify(exactly = 1) {
|
||||||
|
vaultDiskSource.getSends(userId = userId)
|
||||||
|
}
|
||||||
|
coVerify(exactly = 0) {
|
||||||
|
sendsService.getSend(sendId = sendId)
|
||||||
|
vaultDiskSource.saveSend(userId = userId, send = any())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `createSend with no active user should return CreateSendResult Error`() =
|
fun `createSend with no active user should return CreateSendResult Error`() =
|
||||||
runTest {
|
runTest {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user