mirror of
https://github.com/bitwarden/android.git
synced 2026-07-27 16:50:40 -05:00
Remove the send password (#579)
This commit is contained in:
committed by
Álison Fernandes
parent
7a6088a23d
commit
3f7fe90c5c
@@ -35,4 +35,10 @@ interface SendsApi {
|
||||
*/
|
||||
@DELETE("sends/{sendId}")
|
||||
suspend fun deleteSend(@Path("sendId") sendId: String): Result<Unit>
|
||||
|
||||
/**
|
||||
* Deletes a send.
|
||||
*/
|
||||
@PUT("sends/{sendId}/remove-password")
|
||||
suspend fun removeSendPassword(@Path("sendId") sendId: String): Result<SyncResponseJson.Send>
|
||||
}
|
||||
|
||||
+8
-1
@@ -24,9 +24,16 @@ interface SendsService {
|
||||
): Result<UpdateSendResponseJson>
|
||||
|
||||
/**
|
||||
* Attempt to delete a cipher.
|
||||
* Attempt to delete a send.
|
||||
*/
|
||||
suspend fun deleteSend(
|
||||
sendId: String,
|
||||
): Result<Unit>
|
||||
|
||||
/**
|
||||
* Attempt to remove password protection from a send.
|
||||
*/
|
||||
suspend fun removeSendPassword(
|
||||
sendId: String,
|
||||
): Result<UpdateSendResponseJson>
|
||||
}
|
||||
|
||||
+14
@@ -40,4 +40,18 @@ class SendsServiceImpl(
|
||||
|
||||
override suspend fun deleteSend(sendId: String): Result<Unit> =
|
||||
sendsApi.deleteSend(sendId = sendId)
|
||||
|
||||
override suspend fun removeSendPassword(sendId: String): Result<UpdateSendResponseJson> =
|
||||
sendsApi
|
||||
.removeSendPassword(sendId = sendId)
|
||||
.map { UpdateSendResponseJson.Success(send = it) }
|
||||
.recoverCatching { throwable ->
|
||||
throwable
|
||||
.toBitwardenError()
|
||||
.parseErrorBodyOrNull<UpdateSendResponseJson.Invalid>(
|
||||
code = 400,
|
||||
json = json,
|
||||
)
|
||||
?: throw throwable
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.x8bit.bitwarden.data.platform.repository.model.DataState
|
||||
import com.x8bit.bitwarden.data.vault.manager.VaultLockManager
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.CreateCipherResult
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.CreateSendResult
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.RemovePasswordSendResult
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.SendData
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.TotpCodeResult
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.UpdateCipherResult
|
||||
@@ -151,4 +152,9 @@ interface VaultRepository : VaultLockManager {
|
||||
sendId: String,
|
||||
sendView: SendView,
|
||||
): UpdateSendResult
|
||||
|
||||
/**
|
||||
* Attempt to remove the password from a send.
|
||||
*/
|
||||
suspend fun removePasswordSend(sendId: String): RemovePasswordSendResult
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.x8bit.bitwarden.data.vault.datasource.sdk.VaultSdkSource
|
||||
import com.x8bit.bitwarden.data.vault.manager.VaultLockManager
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.CreateCipherResult
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.CreateSendResult
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.RemovePasswordSendResult
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.SendData
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.TotpCodeResult
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.UpdateCipherResult
|
||||
@@ -443,6 +444,34 @@ class VaultRepositoryImpl(
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun removePasswordSend(sendId: String): RemovePasswordSendResult {
|
||||
val userId = requireNotNull(activeUserId)
|
||||
return sendsService
|
||||
.removeSendPassword(sendId = sendId)
|
||||
.fold(
|
||||
onSuccess = { response ->
|
||||
when (response) {
|
||||
is UpdateSendResponseJson.Invalid -> {
|
||||
RemovePasswordSendResult.Error(errorMessage = response.message)
|
||||
}
|
||||
|
||||
is UpdateSendResponseJson.Success -> {
|
||||
vaultDiskSource.saveSend(userId = userId, send = response.send)
|
||||
vaultSdkSource
|
||||
.decryptSend(
|
||||
userId = userId,
|
||||
send = response.send.toEncryptedSdkSend(),
|
||||
)
|
||||
.getOrNull()
|
||||
?.let { RemovePasswordSendResult.Success(sendView = it) }
|
||||
?: RemovePasswordSendResult.Error(errorMessage = null)
|
||||
}
|
||||
}
|
||||
},
|
||||
onFailure = { RemovePasswordSendResult.Error(errorMessage = null) },
|
||||
)
|
||||
}
|
||||
|
||||
private fun storeProfileData(
|
||||
syncResponse: SyncResponseJson,
|
||||
) {
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package com.x8bit.bitwarden.data.vault.repository.model
|
||||
|
||||
import com.bitwarden.core.SendView
|
||||
|
||||
/**
|
||||
* Models result of removing the password protection from a send.
|
||||
*/
|
||||
sealed class RemovePasswordSendResult {
|
||||
|
||||
/**
|
||||
* Send has had the password protection successfully removed and contains the decrypted
|
||||
* [SendView].
|
||||
*/
|
||||
data class Success(val sendView: SendView) : RemovePasswordSendResult()
|
||||
|
||||
/**
|
||||
* Generic error while removing the password protection from a send. The optional
|
||||
* [errorMessage] may be displayed directly in the UI when present.
|
||||
*/
|
||||
data class Error(val errorMessage: String?) : RemovePasswordSendResult()
|
||||
}
|
||||
+6
-4
@@ -32,7 +32,7 @@ import com.x8bit.bitwarden.ui.platform.components.BitwardenTopAppBar
|
||||
import com.x8bit.bitwarden.ui.platform.components.LoadingDialogState
|
||||
import com.x8bit.bitwarden.ui.platform.components.OverflowMenuItemData
|
||||
import com.x8bit.bitwarden.ui.tools.feature.send.addsend.handlers.AddSendHandlers
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
||||
/**
|
||||
* Displays new send UX.
|
||||
@@ -92,7 +92,7 @@ fun AddSendScreen(
|
||||
)
|
||||
if (!state.isAddMode) {
|
||||
BitwardenOverflowActionItem(
|
||||
menuItemDataList = persistentListOf(
|
||||
menuItemDataList = listOfNotNull(
|
||||
OverflowMenuItemData(
|
||||
text = stringResource(id = R.string.remove_password),
|
||||
onClick = remember(viewModel) {
|
||||
@@ -102,7 +102,8 @@ fun AddSendScreen(
|
||||
)
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
.takeIf { state.hasPassword },
|
||||
OverflowMenuItemData(
|
||||
text = stringResource(id = R.string.copy_link),
|
||||
onClick = remember(viewModel) {
|
||||
@@ -121,7 +122,8 @@ fun AddSendScreen(
|
||||
{ viewModel.trySendAction(AddSendAction.DeleteClick) }
|
||||
},
|
||||
),
|
||||
),
|
||||
)
|
||||
.toPersistentList(),
|
||||
)
|
||||
}
|
||||
},
|
||||
|
||||
+60
-2
@@ -13,6 +13,7 @@ import com.x8bit.bitwarden.data.platform.repository.util.baseWebSendUrl
|
||||
import com.x8bit.bitwarden.data.platform.repository.util.takeUntilLoaded
|
||||
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.CreateSendResult
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.RemovePasswordSendResult
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.UpdateSendResult
|
||||
import com.x8bit.bitwarden.ui.platform.base.BaseViewModel
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.Text
|
||||
@@ -70,6 +71,7 @@ class AddSendViewModel @Inject constructor(
|
||||
.plusWeeks(1),
|
||||
expirationDate = null,
|
||||
sendUrl = null,
|
||||
hasPassword = false,
|
||||
),
|
||||
selectedType = AddSendState.ViewState.Content.SendType.Text(
|
||||
input = "",
|
||||
@@ -139,6 +141,10 @@ class AddSendViewModel @Inject constructor(
|
||||
private fun handleInternalAction(action: AddSendAction.Internal): Unit = when (action) {
|
||||
is AddSendAction.Internal.CreateSendResultReceive -> handleCreateSendResultReceive(action)
|
||||
is AddSendAction.Internal.UpdateSendResultReceive -> handleUpdateSendResultReceive(action)
|
||||
is AddSendAction.Internal.RemovePasswordResultReceive -> handleRemovePasswordResultReceive(
|
||||
action,
|
||||
)
|
||||
|
||||
is AddSendAction.Internal.UserStateReceive -> handleUserStateReceive(action)
|
||||
is AddSendAction.Internal.SendDataReceive -> handleSendDataReceive(action)
|
||||
}
|
||||
@@ -200,6 +206,32 @@ class AddSendViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleRemovePasswordResultReceive(
|
||||
action: AddSendAction.Internal.RemovePasswordResultReceive,
|
||||
) {
|
||||
when (val result = action.result) {
|
||||
is RemovePasswordSendResult.Error -> {
|
||||
mutableStateFlow.update {
|
||||
it.copy(
|
||||
dialogState = AddSendState.DialogState.Error(
|
||||
title = R.string.an_error_has_occurred.asText(),
|
||||
message = result
|
||||
.errorMessage
|
||||
?.asText()
|
||||
?: R.string.generic_error_message.asText(),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
is RemovePasswordSendResult.Success -> {
|
||||
updateCommonContent { it.copy(hasPassword = false) }
|
||||
mutableStateFlow.update { it.copy(dialogState = null) }
|
||||
sendEvent(AddSendEvent.ShowToast(message = R.string.send_password_removed.asText()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleUserStateReceive(action: AddSendAction.Internal.UserStateReceive) {
|
||||
mutableStateFlow.update {
|
||||
it.copy(isPremiumUser = action.userState?.activeAccount?.isPremium == true)
|
||||
@@ -288,8 +320,22 @@ class AddSendViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
private fun handleRemovePasswordClick() {
|
||||
// TODO Add remove password support (BIT-1435)
|
||||
sendEvent(AddSendEvent.ShowToast("Not yet implemented".asText()))
|
||||
when (val addSendType = state.addSendType) {
|
||||
AddSendType.AddItem -> Unit
|
||||
is AddSendType.EditItem -> {
|
||||
mutableStateFlow.update {
|
||||
it.copy(
|
||||
dialogState = AddSendState.DialogState.Loading(
|
||||
message = R.string.removing_send_password.asText(),
|
||||
),
|
||||
)
|
||||
}
|
||||
viewModelScope.launch {
|
||||
val result = vaultRepo.removePasswordSend(addSendType.sendItemId)
|
||||
sendAction(AddSendAction.Internal.RemovePasswordResultReceive(result))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleShareLinkClick() {
|
||||
@@ -516,6 +562,12 @@ data class AddSendState(
|
||||
*/
|
||||
val isAddMode: Boolean get() = addSendType is AddSendType.AddItem
|
||||
|
||||
/**
|
||||
* Helper to determine if the currently displayed send has a password already set.
|
||||
*/
|
||||
val hasPassword: Boolean
|
||||
get() = (viewState as? ViewState.Content)?.common?.hasPassword == true
|
||||
|
||||
/**
|
||||
* Represents the specific view states for the [AddSendScreen].
|
||||
*/
|
||||
@@ -566,6 +618,7 @@ data class AddSendState(
|
||||
val deletionDate: ZonedDateTime,
|
||||
val expirationDate: ZonedDateTime?,
|
||||
val sendUrl: String?,
|
||||
val hasPassword: Boolean,
|
||||
) : Parcelable {
|
||||
val dateFormatPattern: String get() = "M/d/yyyy"
|
||||
|
||||
@@ -767,6 +820,11 @@ sealed class AddSendAction {
|
||||
*/
|
||||
data class UpdateSendResultReceive(val result: UpdateSendResult) : Internal()
|
||||
|
||||
/**
|
||||
* Indicates a result for removing the password from a send has been received.
|
||||
*/
|
||||
data class RemovePasswordResultReceive(val result: RemovePasswordSendResult) : Internal()
|
||||
|
||||
/**
|
||||
* Indicates that the send item data has been received.
|
||||
*/
|
||||
|
||||
+1
@@ -28,6 +28,7 @@ fun SendView.toViewState(
|
||||
deletionDate = ZonedDateTime.ofInstant(this.deletionDate, clock.zone),
|
||||
expirationDate = this.expirationDate?.let { ZonedDateTime.ofInstant(it, clock.zone) },
|
||||
sendUrl = this.toSendUrl(baseWebSendUrl),
|
||||
hasPassword = this.hasPassword,
|
||||
),
|
||||
selectedType = when (type) {
|
||||
SendType.TEXT -> {
|
||||
|
||||
Reference in New Issue
Block a user