mirror of
https://github.com/bitwarden/android.git
synced 2026-06-08 08:06:32 -05:00
BIT-1575: Update cipher collections functionality (#904)
This commit is contained in:
committed by
Álison Fernandes
parent
bb0c91ee5a
commit
2d0353d744
@@ -6,6 +6,7 @@ import com.x8bit.bitwarden.data.vault.datasource.network.model.CipherJsonRequest
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.CreateCipherInOrganizationJsonRequest
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.ShareCipherJsonRequest
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.UpdateCipherCollectionsJsonRequest
|
||||
import okhttp3.MultipartBody
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.DELETE
|
||||
@@ -71,6 +72,15 @@ interface CiphersApi {
|
||||
@Body body: ShareCipherJsonRequest,
|
||||
): Result<SyncResponseJson.Cipher>
|
||||
|
||||
/**
|
||||
* Updates a cipher's collections.
|
||||
*/
|
||||
@PUT("ciphers/{cipherId}/collections")
|
||||
suspend fun updateCipherCollections(
|
||||
@Path("cipherId") cipherId: String,
|
||||
@Body body: UpdateCipherCollectionsJsonRequest,
|
||||
): Result<Unit>
|
||||
|
||||
/**
|
||||
* Hard deletes a cipher.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.x8bit.bitwarden.data.vault.datasource.network.model
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* Represents an update cipher collections request.
|
||||
*
|
||||
* @property collectionIds A list of collection ids associated with the cipher.
|
||||
*/
|
||||
@Serializable
|
||||
data class UpdateCipherCollectionsJsonRequest(
|
||||
@SerialName("CollectionIds")
|
||||
val collectionIds: List<String>,
|
||||
)
|
||||
@@ -6,6 +6,7 @@ import com.x8bit.bitwarden.data.vault.datasource.network.model.CipherJsonRequest
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.CreateCipherInOrganizationJsonRequest
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.ShareCipherJsonRequest
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.UpdateCipherCollectionsJsonRequest
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.UpdateCipherResponseJson
|
||||
|
||||
/**
|
||||
@@ -57,6 +58,14 @@ interface CiphersService {
|
||||
body: ShareCipherJsonRequest,
|
||||
): Result<SyncResponseJson.Cipher>
|
||||
|
||||
/**
|
||||
* Attempt to update a cipher's collections.
|
||||
*/
|
||||
suspend fun updateCipherCollections(
|
||||
cipherId: String,
|
||||
body: UpdateCipherCollectionsJsonRequest,
|
||||
): Result<Unit>
|
||||
|
||||
/**
|
||||
* Attempt to hard delete a cipher.
|
||||
*/
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.x8bit.bitwarden.data.vault.datasource.network.model.CreateCipherInOrg
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.FileUploadType
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.ShareCipherJsonRequest
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.UpdateCipherCollectionsJsonRequest
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.UpdateCipherResponseJson
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
@@ -118,6 +119,15 @@ class CiphersServiceImpl(
|
||||
body = body,
|
||||
)
|
||||
|
||||
override suspend fun updateCipherCollections(
|
||||
cipherId: String,
|
||||
body: UpdateCipherCollectionsJsonRequest,
|
||||
): Result<Unit> =
|
||||
ciphersApi.updateCipherCollections(
|
||||
cipherId = cipherId,
|
||||
body = body,
|
||||
)
|
||||
|
||||
override suspend fun hardDeleteCipher(cipherId: String): Result<Unit> =
|
||||
ciphersApi.hardDeleteCipher(cipherId = cipherId)
|
||||
|
||||
|
||||
@@ -257,6 +257,15 @@ interface VaultRepository : VaultLockManager {
|
||||
collectionIds: List<String>,
|
||||
): ShareCipherResult
|
||||
|
||||
/**
|
||||
* Attempt to update a cipher with the given collectionIds.
|
||||
*/
|
||||
suspend fun updateCipherCollections(
|
||||
cipherId: String,
|
||||
cipherView: CipherView,
|
||||
collectionIds: List<String>,
|
||||
): ShareCipherResult
|
||||
|
||||
/**
|
||||
* Attempt to create a send. The [fileUri] _must_ be present when the given [SendView] has a
|
||||
* [SendView.type] of [SendType.FILE].
|
||||
|
||||
@@ -38,6 +38,7 @@ import com.x8bit.bitwarden.data.vault.datasource.network.model.AttachmentJsonReq
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.CreateCipherInOrganizationJsonRequest
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.ShareCipherJsonRequest
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.UpdateCipherCollectionsJsonRequest
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.UpdateCipherResponseJson
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.UpdateFolderResponseJson
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.UpdateSendResponseJson
|
||||
@@ -753,7 +754,7 @@ class VaultRepositoryImpl(
|
||||
cipherView: CipherView,
|
||||
collectionIds: List<String>,
|
||||
): ShareCipherResult {
|
||||
val userId = activeUserId ?: return ShareCipherResult.Error(null)
|
||||
val userId = activeUserId ?: return ShareCipherResult.Error
|
||||
return vaultSdkSource
|
||||
.encryptCipher(
|
||||
userId = userId,
|
||||
@@ -768,12 +769,40 @@ class VaultRepositoryImpl(
|
||||
),
|
||||
)
|
||||
}
|
||||
.onSuccess { vaultDiskSource.saveCipher(userId = userId, cipher = it) }
|
||||
.fold(
|
||||
onFailure = { ShareCipherResult.Error(errorMessage = null) },
|
||||
onSuccess = {
|
||||
vaultDiskSource.saveCipher(userId = userId, cipher = it)
|
||||
ShareCipherResult.Success
|
||||
},
|
||||
onFailure = { ShareCipherResult.Error },
|
||||
onSuccess = { ShareCipherResult.Success },
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun updateCipherCollections(
|
||||
cipherId: String,
|
||||
cipherView: CipherView,
|
||||
collectionIds: List<String>,
|
||||
): ShareCipherResult {
|
||||
val userId = activeUserId ?: return ShareCipherResult.Error
|
||||
return ciphersService
|
||||
.updateCipherCollections(
|
||||
cipherId = cipherId,
|
||||
body = UpdateCipherCollectionsJsonRequest(collectionIds = collectionIds),
|
||||
)
|
||||
.flatMap {
|
||||
vaultSdkSource
|
||||
.encryptCipher(
|
||||
userId = userId,
|
||||
cipherView = cipherView.copy(collectionIds = collectionIds),
|
||||
)
|
||||
}
|
||||
.onSuccess { cipher ->
|
||||
vaultDiskSource.saveCipher(
|
||||
userId = userId,
|
||||
cipher = cipher.toEncryptedNetworkCipherResponse(),
|
||||
)
|
||||
}
|
||||
.fold(
|
||||
onSuccess = { ShareCipherResult.Success },
|
||||
onFailure = { ShareCipherResult.Error },
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,8 +10,7 @@ sealed class ShareCipherResult {
|
||||
data object Success : ShareCipherResult()
|
||||
|
||||
/**
|
||||
* Generic error while sharing cipher. The optional [errorMessage] may be displayed directly in
|
||||
* the UI when present.
|
||||
* Generic error while sharing cipher.
|
||||
*/
|
||||
data class Error(val errorMessage: String?) : ShareCipherResult()
|
||||
data object Error : ShareCipherResult()
|
||||
}
|
||||
|
||||
@@ -60,14 +60,14 @@ class VaultMoveToOrganizationViewModel @Inject constructor(
|
||||
) { cipherViewState, collectionsState, userState ->
|
||||
VaultMoveToOrganizationAction.Internal.VaultDataReceive(
|
||||
vaultData = combineDataStates(
|
||||
dataState1 = cipherViewState.map { Unit },
|
||||
dataState1 = cipherViewState,
|
||||
dataState2 = collectionsState,
|
||||
dataState3 = DataState.Loaded(userState).map { Unit },
|
||||
) { _, collectionsData, _ ->
|
||||
dataState3 = DataState.Loaded(userState),
|
||||
) { cipherData, collectionsData, userData ->
|
||||
Triple(
|
||||
first = cipherViewState.data,
|
||||
first = cipherData,
|
||||
second = collectionsData,
|
||||
third = userState,
|
||||
third = userData,
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -270,6 +270,12 @@ class VaultMoveToOrganizationViewModel @Inject constructor(
|
||||
cipherView: CipherView,
|
||||
contentState: VaultMoveToOrganizationState.ViewState.Content,
|
||||
) {
|
||||
val collectionIds = contentState
|
||||
.selectedOrganization
|
||||
.collections
|
||||
.filter { it.isSelected }
|
||||
.map { it.id }
|
||||
|
||||
mutableStateFlow.update {
|
||||
it.copy(
|
||||
dialogState = VaultMoveToOrganizationState.DialogState.Loading(
|
||||
@@ -280,17 +286,21 @@ class VaultMoveToOrganizationViewModel @Inject constructor(
|
||||
viewModelScope.launch {
|
||||
trySendAction(
|
||||
VaultMoveToOrganizationAction.Internal.ShareCipherResultReceive(
|
||||
vaultRepository.shareCipher(
|
||||
cipherId = mutableStateFlow.value.vaultItemId,
|
||||
cipherView = cipherView.copy(
|
||||
organizationId = contentState.selectedOrganizationId,
|
||||
),
|
||||
collectionIds = contentState
|
||||
.selectedOrganization
|
||||
.collections
|
||||
.filter { it.isSelected }
|
||||
.map { it.id },
|
||||
),
|
||||
if (state.onlyShowCollections) {
|
||||
vaultRepository.updateCipherCollections(
|
||||
cipherId = mutableStateFlow.value.vaultItemId,
|
||||
cipherView = cipherView,
|
||||
collectionIds = collectionIds,
|
||||
)
|
||||
} else {
|
||||
vaultRepository.shareCipher(
|
||||
cipherId = mutableStateFlow.value.vaultItemId,
|
||||
cipherView = cipherView.copy(
|
||||
organizationId = contentState.selectedOrganizationId,
|
||||
),
|
||||
collectionIds = collectionIds,
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user