mirror of
https://github.com/bitwarden/android.git
synced 2026-06-07 23:58:03 -05:00
Add underlying support for file sends (#646)
This commit is contained in:
committed by
Álison Fernandes
parent
dbbb9f6587
commit
cd236f183f
@@ -0,0 +1,25 @@
|
||||
package com.x8bit.bitwarden.data.vault.datasource.network.api
|
||||
|
||||
import okhttp3.RequestBody
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.Header
|
||||
import retrofit2.http.Headers
|
||||
import retrofit2.http.PUT
|
||||
import retrofit2.http.Url
|
||||
|
||||
/**
|
||||
* Defines raw calls to the Azure API without any authentication applied.
|
||||
*/
|
||||
interface AzureApi {
|
||||
/**
|
||||
* Attempts to upload an encrypted file to Azure.
|
||||
*/
|
||||
@PUT
|
||||
@Headers("x-ms-blob-type: BlockBlob")
|
||||
suspend fun uploadAzureBlob(
|
||||
@Url url: String,
|
||||
@Header("x-ms-date") date: String,
|
||||
@Header("x-ms-version") version: String?,
|
||||
@Body body: RequestBody,
|
||||
): Result<Unit>
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
package com.x8bit.bitwarden.data.vault.datasource.network.api
|
||||
|
||||
import androidx.annotation.Keep
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SendFileResponseJson
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SendJsonRequest
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
||||
import okhttp3.MultipartBody
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.DELETE
|
||||
import retrofit2.http.POST
|
||||
@@ -21,6 +23,12 @@ interface SendsApi {
|
||||
@POST("sends")
|
||||
suspend fun createSend(@Body body: SendJsonRequest): Result<SyncResponseJson.Send>
|
||||
|
||||
/**
|
||||
* Create a file send.
|
||||
*/
|
||||
@POST("sends/file/v2")
|
||||
suspend fun createFileSend(@Body body: SendJsonRequest): Result<SendFileResponseJson>
|
||||
|
||||
/**
|
||||
* Updates a send.
|
||||
*/
|
||||
@@ -30,6 +38,16 @@ interface SendsApi {
|
||||
@Body body: SendJsonRequest,
|
||||
): Result<SyncResponseJson.Send>
|
||||
|
||||
/**
|
||||
* Uploads the file associated with a send.
|
||||
*/
|
||||
@POST("sends/{sendId}/file/{fileId}")
|
||||
suspend fun uploadFile(
|
||||
@Path("sendId") sendId: String,
|
||||
@Path("fileId") fileId: String,
|
||||
@Body body: MultipartBody,
|
||||
): Result<Unit>
|
||||
|
||||
/**
|
||||
* Deletes a send.
|
||||
*/
|
||||
|
||||
@@ -13,6 +13,7 @@ import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import kotlinx.serialization.json.Json
|
||||
import retrofit2.create
|
||||
import java.time.Clock
|
||||
import javax.inject.Singleton
|
||||
|
||||
/**
|
||||
@@ -37,9 +38,17 @@ object VaultNetworkModule {
|
||||
fun provideSendsService(
|
||||
retrofits: Retrofits,
|
||||
json: Json,
|
||||
clock: Clock,
|
||||
): SendsService = SendsServiceImpl(
|
||||
azureApi = retrofits
|
||||
.staticRetrofitBuilder
|
||||
// This URL will be overridden dynamically
|
||||
.baseUrl("https://www.bitwaredn.com")
|
||||
.build()
|
||||
.create(),
|
||||
sendsApi = retrofits.authenticatedApiRetrofit.create(),
|
||||
json = json,
|
||||
clock = clock,
|
||||
)
|
||||
|
||||
@Provides
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.x8bit.bitwarden.data.vault.datasource.network.model
|
||||
|
||||
import androidx.annotation.Keep
|
||||
import com.x8bit.bitwarden.data.platform.datasource.network.serializer.BaseEnumeratedIntSerializer
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* Represents the JSON response from creating a new file send.
|
||||
*/
|
||||
@Serializable
|
||||
data class SendFileResponseJson(
|
||||
@SerialName("url")
|
||||
val url: String,
|
||||
|
||||
@SerialName("fileUploadType")
|
||||
val fileUploadType: FileUploadType,
|
||||
|
||||
@SerialName("sendResponse")
|
||||
val sendResponse: SyncResponseJson.Send,
|
||||
) {
|
||||
/**
|
||||
* Represents the type of file upload that should be used.
|
||||
*/
|
||||
@Serializable(FileUploadTypeSerializer::class)
|
||||
enum class FileUploadType {
|
||||
@SerialName("0")
|
||||
DIRECT,
|
||||
|
||||
@SerialName("1")
|
||||
AZURE,
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
private class FileUploadTypeSerializer :
|
||||
BaseEnumeratedIntSerializer<SendFileResponseJson.FileUploadType>(
|
||||
SendFileResponseJson.FileUploadType.entries.toTypedArray(),
|
||||
)
|
||||
@@ -16,6 +16,7 @@ import java.time.ZonedDateTime
|
||||
* @property expirationDate The date in which the send will expire (nullable).
|
||||
* @property deletionDate The date in which the send will be deleted.
|
||||
* @property file The file associated with this send (nullable).
|
||||
* @property fileLength The length of the file in bytes (nullable).
|
||||
* @property text The text associated with this send (nullable).
|
||||
* @property password The password protecting this send (nullable).
|
||||
* @property isDisabled Indicate if this send is disabled.
|
||||
@@ -46,6 +47,9 @@ data class SendJsonRequest(
|
||||
@Contextual
|
||||
val deletionDate: ZonedDateTime,
|
||||
|
||||
@SerialName("fileLength")
|
||||
val fileLength: Int?,
|
||||
|
||||
@SerialName("file")
|
||||
val file: SyncResponseJson.Send.File?,
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.x8bit.bitwarden.data.vault.datasource.network.service
|
||||
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SendFileResponseJson
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SendJsonRequest
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.UpdateSendResponseJson
|
||||
@@ -15,6 +16,21 @@ interface SendsService {
|
||||
body: SendJsonRequest,
|
||||
): Result<SyncResponseJson.Send>
|
||||
|
||||
/**
|
||||
* Attempt to create a file send.
|
||||
*/
|
||||
suspend fun createFileSend(
|
||||
body: SendJsonRequest,
|
||||
): Result<SendFileResponseJson>
|
||||
|
||||
/**
|
||||
* Attempt to upload the given [encryptedFile] associated with the [sendFileResponse].
|
||||
*/
|
||||
suspend fun uploadFile(
|
||||
sendFileResponse: SendFileResponseJson,
|
||||
encryptedFile: ByteArray,
|
||||
): Result<SyncResponseJson.Send>
|
||||
|
||||
/**
|
||||
* Attempt to update a send.
|
||||
*/
|
||||
|
||||
@@ -1,23 +1,38 @@
|
||||
package com.x8bit.bitwarden.data.vault.datasource.network.service
|
||||
|
||||
import androidx.core.net.toUri
|
||||
import com.x8bit.bitwarden.data.platform.datasource.network.model.toBitwardenError
|
||||
import com.x8bit.bitwarden.data.platform.datasource.network.util.parseErrorBodyOrNull
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.api.AzureApi
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.api.SendsApi
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SendFileResponseJson
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SendJsonRequest
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.UpdateSendResponseJson
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.MultipartBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import java.time.Clock
|
||||
import java.time.ZoneOffset
|
||||
import java.time.ZonedDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
/**
|
||||
* Default implementation of the [SendsService].
|
||||
*/
|
||||
class SendsServiceImpl(
|
||||
private val azureApi: AzureApi,
|
||||
private val sendsApi: SendsApi,
|
||||
private val clock: Clock,
|
||||
private val json: Json,
|
||||
) : SendsService {
|
||||
override suspend fun createSend(body: SendJsonRequest): Result<SyncResponseJson.Send> =
|
||||
sendsApi.createSend(body = body)
|
||||
|
||||
override suspend fun createFileSend(body: SendJsonRequest): Result<SendFileResponseJson> =
|
||||
sendsApi.createFileSend(body = body)
|
||||
|
||||
override suspend fun updateSend(
|
||||
sendId: String,
|
||||
body: SendJsonRequest,
|
||||
@@ -38,6 +53,48 @@ class SendsServiceImpl(
|
||||
?: throw throwable
|
||||
}
|
||||
|
||||
override suspend fun uploadFile(
|
||||
sendFileResponse: SendFileResponseJson,
|
||||
encryptedFile: ByteArray,
|
||||
): Result<SyncResponseJson.Send> {
|
||||
val send = sendFileResponse.sendResponse
|
||||
return when (sendFileResponse.fileUploadType) {
|
||||
SendFileResponseJson.FileUploadType.DIRECT -> {
|
||||
sendsApi.uploadFile(
|
||||
sendId = requireNotNull(send.id),
|
||||
fileId = requireNotNull(send.file?.id),
|
||||
body = MultipartBody
|
||||
.Builder(
|
||||
boundary = "--BWMobileFormBoundary${clock.instant().toEpochMilli()}",
|
||||
)
|
||||
.addPart(
|
||||
part = MultipartBody.Part.createFormData(
|
||||
body = encryptedFile.toRequestBody(
|
||||
contentType = "application/octet-stream".toMediaType(),
|
||||
),
|
||||
name = "data",
|
||||
filename = send.file?.fileName,
|
||||
),
|
||||
)
|
||||
.build(),
|
||||
)
|
||||
}
|
||||
|
||||
SendFileResponseJson.FileUploadType.AZURE -> {
|
||||
azureApi.uploadAzureBlob(
|
||||
url = sendFileResponse.url,
|
||||
date = DateTimeFormatter
|
||||
.RFC_1123_DATE_TIME
|
||||
.format(ZonedDateTime.ofInstant(clock.instant(), ZoneOffset.UTC)),
|
||||
version = sendFileResponse.url.toUri().getQueryParameter("sv"),
|
||||
body = encryptedFile.toRequestBody(),
|
||||
)
|
||||
}
|
||||
}
|
||||
.onFailure { sendsApi.deleteSend(send.id) }
|
||||
.map { send }
|
||||
}
|
||||
|
||||
override suspend fun deleteSend(sendId: String): Result<Unit> =
|
||||
sendsApi.deleteSend(sendId = sendId)
|
||||
|
||||
|
||||
@@ -169,6 +169,19 @@ interface VaultSdkSource {
|
||||
sendView: SendView,
|
||||
): Result<Send>
|
||||
|
||||
/**
|
||||
* Encrypts a [ByteArray] file buffer for the user with the given [userId], returning an
|
||||
* encrypted [ByteArray] wrapped in a [Result].
|
||||
*
|
||||
* This should only be called after a successful call to [initializeCrypto] for the associated
|
||||
* user.
|
||||
*/
|
||||
suspend fun encryptBuffer(
|
||||
userId: String,
|
||||
send: Send,
|
||||
fileBuffer: ByteArray,
|
||||
): Result<ByteArray>
|
||||
|
||||
/**
|
||||
* Decrypts a [Send] for the user with the given [userId], returning a [SendView] wrapped in a
|
||||
* [Result].
|
||||
|
||||
@@ -104,6 +104,21 @@ class VaultSdkSourceImpl(
|
||||
.encrypt(sendView)
|
||||
}
|
||||
|
||||
override suspend fun encryptBuffer(
|
||||
userId: String,
|
||||
send: Send,
|
||||
fileBuffer: ByteArray,
|
||||
): Result<ByteArray> =
|
||||
runCatching {
|
||||
getClient(userId = userId)
|
||||
.vault()
|
||||
.sends()
|
||||
.encryptBuffer(
|
||||
send = send,
|
||||
buffer = fileBuffer,
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun encryptCipher(
|
||||
userId: String,
|
||||
cipherView: CipherView,
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.x8bit.bitwarden.data.vault.manager
|
||||
|
||||
import android.net.Uri
|
||||
import com.x8bit.bitwarden.data.platform.annotation.OmitFromCoverage
|
||||
|
||||
/**
|
||||
* Manages reading files.
|
||||
*/
|
||||
@OmitFromCoverage
|
||||
interface FileManager {
|
||||
|
||||
/**
|
||||
* Reads the [fileUri] into memory and returns the raw [ByteArray]
|
||||
*/
|
||||
fun uriToByteArray(fileUri: Uri): ByteArray
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.x8bit.bitwarden.data.vault.manager
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import com.x8bit.bitwarden.data.platform.annotation.OmitFromCoverage
|
||||
import java.io.ByteArrayOutputStream
|
||||
|
||||
/**
|
||||
* The buffer size to be used when reading from an input stream.
|
||||
*/
|
||||
private const val BUFFER_SIZE: Int = 1024
|
||||
|
||||
/**
|
||||
* The default implementation of the [FileManager] interface.
|
||||
*/
|
||||
@OmitFromCoverage
|
||||
class FileManagerImpl(
|
||||
private val context: Context,
|
||||
) : FileManager {
|
||||
|
||||
override fun uriToByteArray(fileUri: Uri): ByteArray =
|
||||
context
|
||||
.contentResolver
|
||||
.openInputStream(fileUri)
|
||||
?.use { inputStream ->
|
||||
ByteArrayOutputStream().use { outputStream ->
|
||||
val buffer = ByteArray(BUFFER_SIZE)
|
||||
var length: Int
|
||||
while (inputStream.read(buffer).also { length = it } != -1) {
|
||||
outputStream.write(buffer, 0, length)
|
||||
}
|
||||
outputStream.toByteArray()
|
||||
}
|
||||
}
|
||||
?: byteArrayOf()
|
||||
}
|
||||
@@ -1,16 +1,20 @@
|
||||
package com.x8bit.bitwarden.data.vault.manager.di
|
||||
|
||||
import android.content.Context
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
|
||||
import com.x8bit.bitwarden.data.auth.manager.UserLogoutManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.AppForegroundManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
|
||||
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.VaultSdkSource
|
||||
import com.x8bit.bitwarden.data.vault.manager.FileManager
|
||||
import com.x8bit.bitwarden.data.vault.manager.FileManagerImpl
|
||||
import com.x8bit.bitwarden.data.vault.manager.VaultLockManager
|
||||
import com.x8bit.bitwarden.data.vault.manager.VaultLockManagerImpl
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@@ -21,6 +25,12 @@ import javax.inject.Singleton
|
||||
@InstallIn(SingletonComponent::class)
|
||||
object VaultManagerModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideFileManager(
|
||||
@ApplicationContext context: Context,
|
||||
): FileManager = FileManagerImpl(context)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideVaultLockManager(
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package com.x8bit.bitwarden.data.vault.repository
|
||||
|
||||
import android.net.Uri
|
||||
import com.bitwarden.core.CipherView
|
||||
import com.bitwarden.core.CollectionView
|
||||
import com.bitwarden.core.FolderView
|
||||
import com.bitwarden.core.SendType
|
||||
import com.bitwarden.core.SendView
|
||||
import com.bitwarden.crypto.Kdf
|
||||
import com.x8bit.bitwarden.data.platform.repository.model.DataState
|
||||
@@ -159,9 +161,10 @@ interface VaultRepository : VaultLockManager {
|
||||
): UpdateCipherResult
|
||||
|
||||
/**
|
||||
* Attempt to create a send.
|
||||
* Attempt to create a send. The [fileUri] _must_ be present when the given [SendView] has a
|
||||
* [SendView.type] of [SendType.FILE].
|
||||
*/
|
||||
suspend fun createSend(sendView: SendView): CreateSendResult
|
||||
suspend fun createSend(sendView: SendView, fileUri: Uri?): CreateSendResult
|
||||
|
||||
/**
|
||||
* Attempt to update a send.
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package com.x8bit.bitwarden.data.vault.repository
|
||||
|
||||
import android.net.Uri
|
||||
import com.bitwarden.core.CipherView
|
||||
import com.bitwarden.core.CollectionView
|
||||
import com.bitwarden.core.FolderView
|
||||
import com.bitwarden.core.InitOrgCryptoRequest
|
||||
import com.bitwarden.core.InitUserCryptoMethod
|
||||
import com.bitwarden.core.SendType
|
||||
import com.bitwarden.core.SendView
|
||||
import com.bitwarden.crypto.Kdf
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
|
||||
@@ -18,6 +20,7 @@ import com.x8bit.bitwarden.data.platform.repository.util.combineDataStates
|
||||
import com.x8bit.bitwarden.data.platform.repository.util.map
|
||||
import com.x8bit.bitwarden.data.platform.repository.util.observeWhenSubscribedAndLoggedIn
|
||||
import com.x8bit.bitwarden.data.platform.repository.util.updateToPendingOrLoading
|
||||
import com.x8bit.bitwarden.data.platform.util.asFailure
|
||||
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.SyncResponseJson
|
||||
@@ -27,6 +30,7 @@ import com.x8bit.bitwarden.data.vault.datasource.network.service.CiphersService
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.service.SendsService
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.service.SyncService
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.VaultSdkSource
|
||||
import com.x8bit.bitwarden.data.vault.manager.FileManager
|
||||
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
|
||||
@@ -80,6 +84,7 @@ class VaultRepositoryImpl(
|
||||
private val vaultDiskSource: VaultDiskSource,
|
||||
private val vaultSdkSource: VaultSdkSource,
|
||||
private val authDiskSource: AuthDiskSource,
|
||||
private val fileManager: FileManager,
|
||||
private val vaultLockManager: VaultLockManager,
|
||||
dispatcherManager: DispatcherManager,
|
||||
) : VaultRepository,
|
||||
@@ -415,14 +420,50 @@ class VaultRepositoryImpl(
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun createSend(sendView: SendView): CreateSendResult {
|
||||
override suspend fun createSend(
|
||||
sendView: SendView,
|
||||
fileUri: Uri?,
|
||||
): CreateSendResult {
|
||||
val userId = requireNotNull(activeUserId)
|
||||
return vaultSdkSource
|
||||
.encryptSend(
|
||||
userId = userId,
|
||||
sendView = sendView,
|
||||
)
|
||||
.flatMap { send -> sendsService.createSend(body = send.toEncryptedNetworkSend()) }
|
||||
.flatMap { send ->
|
||||
when (send.type) {
|
||||
SendType.TEXT -> {
|
||||
sendsService.createSend(body = send.toEncryptedNetworkSend())
|
||||
}
|
||||
|
||||
SendType.FILE -> {
|
||||
val uri = fileUri ?: return@flatMap IllegalArgumentException(
|
||||
"File URI must be present to create a File Send.",
|
||||
)
|
||||
.asFailure()
|
||||
vaultSdkSource
|
||||
.encryptBuffer(
|
||||
userId = userId,
|
||||
send = send,
|
||||
fileBuffer = fileManager.uriToByteArray(fileUri = uri),
|
||||
)
|
||||
.flatMap { encryptedFile ->
|
||||
sendsService
|
||||
.createFileSend(
|
||||
body = send.toEncryptedNetworkSend(
|
||||
fileLength = encryptedFile.size,
|
||||
),
|
||||
)
|
||||
.flatMap { sendFileResponse ->
|
||||
sendsService.uploadFile(
|
||||
sendFileResponse = sendFileResponse,
|
||||
encryptedFile = encryptedFile,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.onSuccess {
|
||||
// Save the send immediately, regardless of whether the decrypt succeeds
|
||||
vaultDiskSource.saveSend(userId = userId, send = it)
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.x8bit.bitwarden.data.vault.datasource.network.service.CiphersService
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.service.SendsService
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.service.SyncService
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.VaultSdkSource
|
||||
import com.x8bit.bitwarden.data.vault.manager.FileManager
|
||||
import com.x8bit.bitwarden.data.vault.manager.VaultLockManager
|
||||
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
|
||||
import com.x8bit.bitwarden.data.vault.repository.VaultRepositoryImpl
|
||||
@@ -32,6 +33,7 @@ object VaultRepositoryModule {
|
||||
vaultDiskSource: VaultDiskSource,
|
||||
vaultSdkSource: VaultSdkSource,
|
||||
authDiskSource: AuthDiskSource,
|
||||
fileManager: FileManager,
|
||||
vaultLockManager: VaultLockManager,
|
||||
dispatcherManager: DispatcherManager,
|
||||
): VaultRepository = VaultRepositoryImpl(
|
||||
@@ -41,6 +43,7 @@ object VaultRepositoryModule {
|
||||
vaultDiskSource = vaultDiskSource,
|
||||
vaultSdkSource = vaultSdkSource,
|
||||
authDiskSource = authDiskSource,
|
||||
fileManager = fileManager,
|
||||
vaultLockManager = vaultLockManager,
|
||||
dispatcherManager = dispatcherManager,
|
||||
)
|
||||
|
||||
@@ -13,7 +13,7 @@ import java.time.ZonedDateTime
|
||||
/**
|
||||
* Converts a Bitwarden SDK [Send] object to a corresponding [SyncResponseJson.Send] object.
|
||||
*/
|
||||
fun Send.toEncryptedNetworkSend(): SendJsonRequest =
|
||||
fun Send.toEncryptedNetworkSend(fileLength: Int? = null): SendJsonRequest =
|
||||
SendJsonRequest(
|
||||
type = type.toNetworkSendType(),
|
||||
name = name,
|
||||
@@ -22,6 +22,7 @@ fun Send.toEncryptedNetworkSend(): SendJsonRequest =
|
||||
maxAccessCount = maxAccessCount?.toInt(),
|
||||
expirationDate = expirationDate?.let { ZonedDateTime.ofInstant(it, ZoneOffset.UTC) },
|
||||
deletionDate = ZonedDateTime.ofInstant(deletionDate, ZoneOffset.UTC),
|
||||
fileLength = fileLength,
|
||||
file = file?.toNetworkSendFile(),
|
||||
text = text?.toNetworkSendText(),
|
||||
password = password,
|
||||
|
||||
@@ -452,7 +452,10 @@ class AddSendViewModel @Inject constructor(
|
||||
viewModelScope.launch {
|
||||
when (val addSendType = state.addSendType) {
|
||||
AddSendType.AddItem -> {
|
||||
val result = vaultRepo.createSend(content.toSendView(clock))
|
||||
val result = vaultRepo.createSend(
|
||||
sendView = content.toSendView(clock),
|
||||
fileUri = null,
|
||||
)
|
||||
sendAction(AddSendAction.Internal.CreateSendResultReceive(result))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user