@@ -8,10 +8,12 @@ import com.bitwarden.core.data.util.asSuccess
88import com.bitwarden.core.data.util.flatMap
99import com.bitwarden.data.manager.file.FileManager
1010import com.bitwarden.data.manager.model.DownloadResult
11+ import com.bitwarden.network.model.ArchiveCipherResponseJson
1112import com.bitwarden.network.model.AttachmentJsonResponse
1213import com.bitwarden.network.model.CreateCipherInOrganizationJsonRequest
1314import com.bitwarden.network.model.CreateCipherResponseJson
1415import com.bitwarden.network.model.ShareCipherJsonRequest
16+ import com.bitwarden.network.model.UnarchiveCipherResponseJson
1517import com.bitwarden.network.model.UpdateCipherCollectionsJsonRequest
1618import com.bitwarden.network.model.UpdateCipherResponseJson
1719import com.bitwarden.network.service.CiphersService
@@ -168,33 +170,29 @@ class CipherManagerImpl(
168170 cipherView : CipherView ,
169171 ): ArchiveCipherResult {
170172 val userId = activeUserId ? : return ArchiveCipherResult .Error (NoActiveUserException ())
171- return cipherView
172- .encryptCipherAndCheckForMigration(userId = userId, cipherId = cipherId)
173- .flatMap { encryptionContext ->
174- ciphersService
175- .archiveCipher(cipherId = cipherId)
176- .flatMap {
177- vaultSdkSource.decryptCipher(
173+ return ciphersService
174+ .archiveCipher(cipherId = cipherId)
175+ .flatMap { response ->
176+ when (response) {
177+ is ArchiveCipherResponseJson .Invalid -> {
178+ IllegalStateException (response.firstValidationErrorMessage)
179+ .asFailure()
180+ }
181+
182+ is ArchiveCipherResponseJson .Success -> {
183+ vaultDiskSource.saveCipher(
178184 userId = userId,
179- cipher = encryptionContext.cipher,
185+ cipher = response.cipher.copy(
186+ collectionIds = cipherView.collectionIds,
187+ ),
188+ )
189+ settingsDiskSource.storeIntroducingArchiveActionCardDismissed(
190+ userId = userId,
191+ isDismissed = true ,
180192 )
193+ response.asSuccess()
181194 }
182- }
183- .flatMap {
184- vaultSdkSource.encryptCipher(
185- userId = userId,
186- cipherView = it.copy(archivedDate = clock.instant()),
187- )
188- }
189- .onSuccess {
190- vaultDiskSource.saveCipher(
191- userId = userId,
192- cipher = it.toEncryptedNetworkCipherResponse(),
193- )
194- settingsDiskSource.storeIntroducingArchiveActionCardDismissed(
195- userId = userId,
196- isDismissed = true ,
197- )
195+ }
198196 }
199197 .fold(
200198 onSuccess = { ArchiveCipherResult .Success },
@@ -207,29 +205,25 @@ class CipherManagerImpl(
207205 cipherView : CipherView ,
208206 ): UnarchiveCipherResult {
209207 val userId = activeUserId ? : return UnarchiveCipherResult .Error (NoActiveUserException ())
210- return cipherView
211- .encryptCipherAndCheckForMigration(userId = userId, cipherId = cipherId)
212- .flatMap { encryptionContext ->
213- ciphersService
214- .unarchiveCipher(cipherId = cipherId)
215- .flatMap {
216- vaultSdkSource.decryptCipher(
208+ return ciphersService
209+ .unarchiveCipher(cipherId = cipherId)
210+ .flatMap { response ->
211+ when (response) {
212+ is UnarchiveCipherResponseJson .Invalid -> {
213+ IllegalStateException (response.firstValidationErrorMessage)
214+ .asFailure()
215+ }
216+
217+ is UnarchiveCipherResponseJson .Success -> {
218+ vaultDiskSource.saveCipher(
217219 userId = userId,
218- cipher = encryptionContext.cipher,
220+ cipher = response.cipher.copy(
221+ collectionIds = cipherView.collectionIds,
222+ ),
219223 )
224+ response.asSuccess()
220225 }
221- }
222- .flatMap {
223- vaultSdkSource.encryptCipher(
224- userId = userId,
225- cipherView = it.copy(archivedDate = null ),
226- )
227- }
228- .onSuccess {
229- vaultDiskSource.saveCipher(
230- userId = userId,
231- cipher = it.toEncryptedNetworkCipherResponse(),
232- )
226+ }
233227 }
234228 .fold(
235229 onSuccess = { UnarchiveCipherResult .Success },
@@ -255,6 +249,9 @@ class CipherManagerImpl(
255249 ): DeleteCipherResult {
256250 val userId = activeUserId
257251 ? : return DeleteCipherResult .Error (error = NoActiveUserException ())
252+ // Unlike archive/unarchive, soft delete requires edit permissions, so the
253+ // migration check is intentional here to ensure the cipher is up-to-date
254+ // before deletion.
258255 return cipherView
259256 .encryptCipherAndCheckForMigration(userId = userId, cipherId = cipherId)
260257 .flatMap { encryptionContext ->
0 commit comments