Maybe working

This commit is contained in:
Hinton 2024-10-24 14:20:45 -07:00
parent 028d382a5b
commit 2e0f07e138
No known key found for this signature in database
GPG key ID: 5F7295599C5D965C
4 changed files with 91 additions and 0 deletions

View file

@ -26,6 +26,11 @@ interface VaultDiskSource {
*/
fun getOfflineCiphers(userId: String): Flow<List<OfflineCipherJson>>
/**
* Deletes an offline cipher from the data source for the given [userId] and [cipherId].
*/
suspend fun deleteOfflineCipher(userId: String, cipherId: String)
/**
* Retrieves all ciphers from the data source for a given [userId].
*/

View file

@ -105,6 +105,10 @@ class VaultDiskSourceImpl(
},
)
override suspend fun deleteOfflineCipher(userId: String, cipherId: String) {
offlineCiphersDao.deleteCipher(userId, cipherId)
}
override fun getCiphers(
userId: String,
): Flow<List<SyncResponseJson.Cipher>> =

View file

@ -6,11 +6,13 @@ import com.bitwarden.vault.AttachmentView
import com.bitwarden.vault.Cipher
import com.bitwarden.vault.CipherView
import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
import com.x8bit.bitwarden.data.platform.manager.NetworkConnectionManager
import com.x8bit.bitwarden.data.platform.util.asFailure
import com.x8bit.bitwarden.data.platform.util.asSuccess
import com.x8bit.bitwarden.data.platform.util.flatMap
import com.x8bit.bitwarden.data.vault.datasource.disk.VaultDiskSource
import com.x8bit.bitwarden.data.vault.datasource.network.model.CreateCipherInOrganizationJsonRequest
import com.x8bit.bitwarden.data.vault.datasource.network.model.OfflineCipherJson
import com.x8bit.bitwarden.data.vault.datasource.network.model.ShareCipherJsonRequest
import com.x8bit.bitwarden.data.vault.datasource.network.model.UpdateCipherCollectionsJsonRequest
import com.x8bit.bitwarden.data.vault.datasource.network.model.UpdateCipherResponseJson
@ -25,16 +27,28 @@ import com.x8bit.bitwarden.data.vault.repository.model.DownloadAttachmentResult
import com.x8bit.bitwarden.data.vault.repository.model.RestoreCipherResult
import com.x8bit.bitwarden.data.vault.repository.model.ShareCipherResult
import com.x8bit.bitwarden.data.vault.repository.model.UpdateCipherResult
import com.x8bit.bitwarden.data.vault.repository.util.toCipher
import com.x8bit.bitwarden.data.vault.repository.util.toEncryptedNetworkCipher
import com.x8bit.bitwarden.data.vault.repository.util.toEncryptedNetworkCipherResponse
import com.x8bit.bitwarden.data.vault.repository.util.toEncryptedSdkCipher
import com.x8bit.bitwarden.data.vault.repository.util.toNetworkAttachmentRequest
import com.x8bit.bitwarden.data.vault.repository.util.toOfflineCipher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flatMapConcat
import kotlinx.coroutines.flow.flattenConcat
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import java.io.File
import java.time.Clock
/**
* The default implementation of the [CipherManager].
*/
@OptIn(ExperimentalCoroutinesApi::class)
@Suppress("TooManyFunctions")
class CipherManagerImpl(
private val fileManager: FileManager,
@ -43,9 +57,74 @@ class CipherManagerImpl(
private val vaultDiskSource: VaultDiskSource,
private val vaultSdkSource: VaultSdkSource,
private val clock: Clock,
private val networkConnectionManager: NetworkConnectionManager,
private val externalScope: CoroutineScope,
) : CipherManager {
private val activeUserId: String? get() = authDiskSource.userState?.activeUserId
init {
externalScope.launch {
networkConnectionManager.isNetworkConnectedFlow
.map {
if (it && activeUserId != null) {
// Device went online
// TODO: We need to add support for non active users!
vaultDiskSource.getOfflineCiphers(activeUserId!!)
} else {
flowOf(listOf<OfflineCipherJson>())
}
}.flattenConcat().collect {
if (activeUserId == null) {
return@collect
}
val userId = activeUserId!!
it.map { c ->
val cipher = c.toOfflineCipher().toCipher()
when (cipher.id) {
null -> ciphersService.createCipher(body = cipher.toEncryptedNetworkCipher())
.onSuccess {
vaultDiskSource.saveCipher(userId = userId, cipher = it)
vaultDiskSource.deleteOfflineCipher(userId = userId, cipherId = c.id)
}
.fold(
onFailure = { CreateCipherResult.Error },
onSuccess = { CreateCipherResult.Success },
)
else -> ciphersService.updateCipher(
cipherId = cipher.id!!,
body = cipher.toEncryptedNetworkCipher()
).map { response ->
when (response) {
is UpdateCipherResponseJson.Invalid -> {
UpdateCipherResult.Error(errorMessage = response.message)
}
is UpdateCipherResponseJson.Success -> {
vaultDiskSource.saveCipher(
userId = userId,
// TODO: Why are we doing this?
cipher = response.cipher.copy(collectionIds = cipher.collectionIds),
)
UpdateCipherResult.Success
}
}
}
.fold(
onFailure = { UpdateCipherResult.Error(errorMessage = null) },
onSuccess = { it },
)
}
}
}
}
}
override suspend fun createOfflineCipher(cipherView: CipherView): CreateCipherResult {
val userId = activeUserId ?: return CreateCipherResult.Error

View file

@ -6,6 +6,7 @@ import com.x8bit.bitwarden.data.auth.datasource.sdk.AuthSdkSource
import com.x8bit.bitwarden.data.auth.manager.TrustedDeviceManager
import com.x8bit.bitwarden.data.auth.manager.UserLogoutManager
import com.x8bit.bitwarden.data.platform.manager.AppForegroundManager
import com.x8bit.bitwarden.data.platform.manager.NetworkConnectionManager
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
import com.x8bit.bitwarden.data.vault.datasource.disk.VaultDiskSource
@ -44,6 +45,7 @@ object VaultManagerModule {
authDiskSource: AuthDiskSource,
fileManager: FileManager,
clock: Clock,
networkConnectionManager: NetworkConnectionManager
): CipherManager = CipherManagerImpl(
fileManager = fileManager,
authDiskSource = authDiskSource,
@ -51,6 +53,7 @@ object VaultManagerModule {
vaultDiskSource = vaultDiskSource,
vaultSdkSource = vaultSdkSource,
clock = clock,
networkConnectionManager = networkConnectionManager
)
@Provides