mirror of
https://github.com/bitwarden/android.git
synced 2026-06-04 03:36:32 -05:00
BIT-1888 Add the check for the last revision date (#1029)
This commit is contained in:
committed by
Álison Fernandes
parent
2d54fc4616
commit
c33fc8cf97
@@ -77,6 +77,12 @@ interface VaultDiskSource {
|
||||
*/
|
||||
suspend fun replaceVaultData(userId: String, vault: SyncResponseJson)
|
||||
|
||||
/**
|
||||
* Trigger re-emissions from the [getCiphers], [getCollections], [getFolders], and [getSends]
|
||||
* functions.
|
||||
*/
|
||||
suspend fun resyncVaultData(userId: String)
|
||||
|
||||
/**
|
||||
* Deletes all stored vault data from the data source for a given [userId].
|
||||
*/
|
||||
|
||||
@@ -16,6 +16,7 @@ import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.merge
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -264,6 +265,20 @@ class VaultDiskSourceImpl(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun resyncVaultData(userId: String) {
|
||||
coroutineScope {
|
||||
val deferredCiphers = async { getCiphers(userId = userId).first() }
|
||||
val deferredCollections = async { getCollections(userId = userId).first() }
|
||||
val deferredFolders = async { getFolders(userId = userId).first() }
|
||||
val deferredSends = async { getSends(userId = userId).first() }
|
||||
|
||||
forceCiphersFlow.tryEmit(deferredCiphers.await())
|
||||
forceCollectionsFlow.tryEmit(deferredCollections.await())
|
||||
forceFolderFlow.tryEmit(deferredFolders.await())
|
||||
forceSendFlow.tryEmit(deferredSends.await())
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun deleteVaultData(userId: String) {
|
||||
coroutineScope {
|
||||
val deferredCiphers = async { ciphersDao.deleteAllCiphers(userId = userId) }
|
||||
|
||||
@@ -14,4 +14,7 @@ interface SyncApi {
|
||||
*/
|
||||
@GET("sync")
|
||||
suspend fun sync(): Result<SyncResponseJson>
|
||||
|
||||
@GET("/accounts/revision-date")
|
||||
suspend fun getAccountRevisionDateMillis(): Result<Long>
|
||||
}
|
||||
|
||||
@@ -10,4 +10,10 @@ interface SyncService {
|
||||
* Make sync request to get vault items.
|
||||
*/
|
||||
suspend fun sync(): Result<SyncResponseJson>
|
||||
|
||||
/**
|
||||
* Make a request to get the most recent revision date for the account that is returned as an
|
||||
* epoch time in milliseconds.
|
||||
*/
|
||||
suspend fun getAccountRevisionDateMillis(): Result<Long>
|
||||
}
|
||||
|
||||
@@ -7,4 +7,7 @@ class SyncServiceImpl(
|
||||
private val syncApi: SyncApi,
|
||||
) : SyncService {
|
||||
override suspend fun sync(): Result<SyncResponseJson> = syncApi.sync()
|
||||
|
||||
override suspend fun getAccountRevisionDateMillis(): Result<Long> =
|
||||
syncApi.getAccountRevisionDateMillis()
|
||||
}
|
||||
|
||||
@@ -317,6 +317,27 @@ class VaultRepositoryImpl(
|
||||
mutableCollectionsStateFlow.updateToPendingOrLoading()
|
||||
mutableSendDataStateFlow.updateToPendingOrLoading()
|
||||
syncJob = ioScope.launch {
|
||||
val lastSyncInstant = settingsDiskSource
|
||||
.getLastSyncTime(userId = userId)
|
||||
?.toEpochMilli()
|
||||
?: 0
|
||||
|
||||
syncService
|
||||
.getAccountRevisionDateMillis()
|
||||
.fold(
|
||||
onSuccess = { serverRevisionDate ->
|
||||
if (serverRevisionDate < lastSyncInstant) {
|
||||
// We can skip the actual sync call if there is no new data
|
||||
vaultDiskSource.resyncVaultData(userId)
|
||||
return@launch
|
||||
}
|
||||
},
|
||||
onFailure = {
|
||||
updateVaultStateFlowsToError(it)
|
||||
return@launch
|
||||
},
|
||||
)
|
||||
|
||||
syncService
|
||||
.sync()
|
||||
.fold(
|
||||
@@ -350,31 +371,7 @@ class VaultRepositoryImpl(
|
||||
settingsDiskSource.storeLastSyncTime(userId = userId, clock.instant())
|
||||
},
|
||||
onFailure = { throwable ->
|
||||
mutableCiphersStateFlow.update { currentState ->
|
||||
throwable.toNetworkOrErrorState(
|
||||
data = currentState.data,
|
||||
)
|
||||
}
|
||||
mutableDomainsStateFlow.update { currentState ->
|
||||
throwable.toNetworkOrErrorState(
|
||||
data = currentState.data,
|
||||
)
|
||||
}
|
||||
mutableFoldersStateFlow.update { currentState ->
|
||||
throwable.toNetworkOrErrorState(
|
||||
data = currentState.data,
|
||||
)
|
||||
}
|
||||
mutableCollectionsStateFlow.update { currentState ->
|
||||
throwable.toNetworkOrErrorState(
|
||||
data = currentState.data,
|
||||
)
|
||||
}
|
||||
mutableSendDataStateFlow.update { currentState ->
|
||||
throwable.toNetworkOrErrorState(
|
||||
data = currentState.data,
|
||||
)
|
||||
}
|
||||
updateVaultStateFlowsToError(throwable)
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -1407,6 +1404,34 @@ class VaultRepositoryImpl(
|
||||
}
|
||||
.onEach { mutableSendDataStateFlow.value = it }
|
||||
|
||||
private fun updateVaultStateFlowsToError(throwable: Throwable) {
|
||||
mutableCiphersStateFlow.update { currentState ->
|
||||
throwable.toNetworkOrErrorState(
|
||||
data = currentState.data,
|
||||
)
|
||||
}
|
||||
mutableDomainsStateFlow.update { currentState ->
|
||||
throwable.toNetworkOrErrorState(
|
||||
data = currentState.data,
|
||||
)
|
||||
}
|
||||
mutableFoldersStateFlow.update { currentState ->
|
||||
throwable.toNetworkOrErrorState(
|
||||
data = currentState.data,
|
||||
)
|
||||
}
|
||||
mutableCollectionsStateFlow.update { currentState ->
|
||||
throwable.toNetworkOrErrorState(
|
||||
data = currentState.data,
|
||||
)
|
||||
}
|
||||
mutableSendDataStateFlow.update { currentState ->
|
||||
throwable.toNetworkOrErrorState(
|
||||
data = currentState.data,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
//region Push notification helpers
|
||||
/**
|
||||
* Deletes the cipher specified by [syncCipherDeleteData] from disk.
|
||||
|
||||
Reference in New Issue
Block a user