mirror of
https://github.com/bitwarden/android.git
synced 2026-06-08 23:16:33 -05:00
BIT-1205: Save login items (Encryption) (#295)
This commit is contained in:
committed by
Álison Fernandes
parent
9fcd2b1690
commit
b279633166
@@ -21,6 +21,11 @@ interface VaultSdkSource {
|
||||
*/
|
||||
suspend fun initializeCrypto(request: InitUserCryptoRequest): Result<InitializeCryptoResult>
|
||||
|
||||
/**
|
||||
* Encrypts a [CipherView] returning a [Cipher] wrapped in a [Result].
|
||||
*/
|
||||
suspend fun encryptCipher(cipherView: CipherView): Result<Cipher>
|
||||
|
||||
/**
|
||||
* Decrypts a [Cipher] returning a [CipherView] wrapped in a [Result].
|
||||
*/
|
||||
|
||||
@@ -34,6 +34,9 @@ class VaultSdkSourceImpl(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun encryptCipher(cipherView: CipherView): Result<Cipher> =
|
||||
runCatching { clientVault.ciphers().encrypt(cipherView) }
|
||||
|
||||
override suspend fun decryptCipher(cipher: Cipher): Result<CipherView> =
|
||||
runCatching { clientVault.ciphers().decrypt(cipher) }
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.bitwarden.core.CipherView
|
||||
import com.bitwarden.core.FolderView
|
||||
import com.bitwarden.core.Kdf
|
||||
import com.x8bit.bitwarden.data.platform.repository.model.DataState
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.CreateCipherResult
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.SendData
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.VaultData
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.VaultState
|
||||
@@ -75,4 +76,9 @@ interface VaultRepository {
|
||||
privateKey: String,
|
||||
organizationalKeys: Map<String, String>,
|
||||
): VaultUnlockResult
|
||||
|
||||
/**
|
||||
* Attempt to create a cipher.
|
||||
*/
|
||||
suspend fun createCipher(cipherView: CipherView): CreateCipherResult
|
||||
}
|
||||
|
||||
@@ -14,12 +14,15 @@ import com.x8bit.bitwarden.data.platform.repository.model.DataState
|
||||
import com.x8bit.bitwarden.data.platform.repository.util.map
|
||||
import com.x8bit.bitwarden.data.platform.util.flatMap
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.service.CiphersService
|
||||
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.repository.model.CreateCipherResult
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.SendData
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.VaultData
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.VaultState
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockResult
|
||||
import com.x8bit.bitwarden.data.vault.repository.util.toEncryptedNetworkCipher
|
||||
import com.x8bit.bitwarden.data.vault.repository.util.toEncryptedSdkCipherList
|
||||
import com.x8bit.bitwarden.data.vault.repository.util.toEncryptedSdkFolderList
|
||||
import com.x8bit.bitwarden.data.vault.repository.util.toEncryptedSdkSendList
|
||||
@@ -44,6 +47,7 @@ import kotlinx.coroutines.launch
|
||||
@Suppress("TooManyFunctions")
|
||||
class VaultRepositoryImpl constructor(
|
||||
private val syncService: SyncService,
|
||||
private val ciphersService: CiphersService,
|
||||
private val vaultSdkSource: VaultSdkSource,
|
||||
private val authDiskSource: AuthDiskSource,
|
||||
dispatcherManager: DispatcherManager,
|
||||
@@ -227,6 +231,25 @@ class VaultRepositoryImpl constructor(
|
||||
.onCompletion { willSyncAfterUnlock = false }
|
||||
.first()
|
||||
|
||||
override suspend fun createCipher(cipherView: CipherView): CreateCipherResult =
|
||||
vaultSdkSource
|
||||
.encryptCipher(cipherView = cipherView)
|
||||
.flatMap { cipher ->
|
||||
ciphersService
|
||||
.createCipher(
|
||||
body = cipher.toEncryptedNetworkCipher(),
|
||||
)
|
||||
}
|
||||
.fold(
|
||||
onFailure = {
|
||||
CreateCipherResult.Error
|
||||
},
|
||||
onSuccess = {
|
||||
sync()
|
||||
CreateCipherResult.Success
|
||||
},
|
||||
)
|
||||
|
||||
// TODO: This is temporary. Eventually this needs to be based on the presence of various
|
||||
// user keys but this will likely require SDK updates to support this (BIT-1190).
|
||||
private fun setVaultToUnlocked(userId: String) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.x8bit.bitwarden.data.vault.repository.di
|
||||
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
|
||||
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.service.CiphersService
|
||||
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.repository.VaultRepository
|
||||
@@ -23,11 +24,13 @@ object VaultRepositoryModule {
|
||||
@Singleton
|
||||
fun providesVaultRepository(
|
||||
syncService: SyncService,
|
||||
ciphersService: CiphersService,
|
||||
vaultSdkSource: VaultSdkSource,
|
||||
authDiskSource: AuthDiskSource,
|
||||
dispatcherManager: DispatcherManager,
|
||||
): VaultRepository = VaultRepositoryImpl(
|
||||
syncService = syncService,
|
||||
ciphersService = ciphersService,
|
||||
vaultSdkSource = vaultSdkSource,
|
||||
authDiskSource = authDiskSource,
|
||||
dispatcherManager = dispatcherManager,
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.x8bit.bitwarden.data.vault.repository.model
|
||||
|
||||
/**
|
||||
* Models result of creating a cipher.
|
||||
*/
|
||||
sealed class CreateCipherResult {
|
||||
|
||||
/**
|
||||
* Cipher created successfully.
|
||||
*/
|
||||
data object Success : CreateCipherResult()
|
||||
|
||||
/**
|
||||
* Generic error while creating cipher.
|
||||
*/
|
||||
data object Error : CreateCipherResult()
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
@file:Suppress("TooManyFunctions")
|
||||
|
||||
package com.x8bit.bitwarden.data.vault.repository.util
|
||||
|
||||
import CipherJsonRequest
|
||||
import com.bitwarden.core.Attachment
|
||||
import com.bitwarden.core.Card
|
||||
import com.bitwarden.core.Cipher
|
||||
@@ -18,11 +20,205 @@ import com.bitwarden.core.UriMatchType
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.CipherRepromptTypeJson
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.CipherTypeJson
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.FieldTypeJson
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.LinkedIdTypeJson
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SecureNoteTypeJson
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.UriMatchTypeJson
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneOffset
|
||||
|
||||
/**
|
||||
* Converts a Bitwarden SDK [Cipher] object to a corresponding
|
||||
* [SyncResponseJson.Cipher] object.
|
||||
*/
|
||||
fun Cipher.toEncryptedNetworkCipher(): CipherJsonRequest =
|
||||
CipherJsonRequest(
|
||||
notes = notes,
|
||||
reprompt = reprompt.toNetworkRepromptType(),
|
||||
passwordHistory = passwordHistory?.toEncryptedNetworkPasswordHistoryList(),
|
||||
lastKnownRevisionDate = LocalDateTime.ofInstant(revisionDate, ZoneOffset.UTC),
|
||||
type = type.toNetworkCipherType(),
|
||||
login = login?.toEncryptedNetworkLogin(),
|
||||
secureNote = secureNote?.toEncryptedNetworkSecureNote(),
|
||||
folderId = folderId,
|
||||
organizationId = organizationId,
|
||||
identity = identity?.toEncryptedNetworkIdentity(),
|
||||
name = name,
|
||||
fields = fields?.toEncryptedNetworkFieldList(),
|
||||
isFavorite = favorite,
|
||||
card = card?.toEncryptedNetworkCard(),
|
||||
)
|
||||
|
||||
/**
|
||||
* Converts a Bitwarden SDK [Card] object to a corresponding
|
||||
* [SyncResponseJson.Cipher.Card] object.
|
||||
*/
|
||||
private fun Card.toEncryptedNetworkCard(): SyncResponseJson.Cipher.Card =
|
||||
SyncResponseJson.Cipher.Card(
|
||||
number = number,
|
||||
expMonth = expMonth,
|
||||
code = code,
|
||||
expirationYear = expYear,
|
||||
cardholderName = cardholderName,
|
||||
brand = brand,
|
||||
)
|
||||
|
||||
/**
|
||||
* Converts a list of Bitwarden SDK [Field] objects to a corresponding
|
||||
* list of [SyncResponseJson.Cipher.Field] objects.
|
||||
*/
|
||||
private fun List<Field>.toEncryptedNetworkFieldList(): List<SyncResponseJson.Cipher.Field> =
|
||||
this.map { it.toEncryptedNetworkField() }
|
||||
|
||||
/**
|
||||
* Converts a Bitwarden SDK [Field] object to a corresponding
|
||||
* [SyncResponseJson.Cipher.Field] object.
|
||||
*/
|
||||
private fun Field.toEncryptedNetworkField(): SyncResponseJson.Cipher.Field =
|
||||
SyncResponseJson.Cipher.Field(
|
||||
linkedIdType = linkedId?.toNetworkLinkedIdType(),
|
||||
name = name,
|
||||
type = type.toNetworkFieldType(),
|
||||
value = value,
|
||||
)
|
||||
|
||||
private fun UInt.toNetworkLinkedIdType(): LinkedIdTypeJson =
|
||||
LinkedIdTypeJson.values().first { this == it.value }
|
||||
|
||||
/**
|
||||
* Converts a Bitwarden SDK [FieldType] object to a corresponding
|
||||
* [FieldTypeJson] object.
|
||||
*/
|
||||
private fun FieldType.toNetworkFieldType(): FieldTypeJson =
|
||||
when (this) {
|
||||
FieldType.TEXT -> FieldTypeJson.TEXT
|
||||
FieldType.HIDDEN -> FieldTypeJson.HIDDEN
|
||||
FieldType.BOOLEAN -> FieldTypeJson.BOOLEAN
|
||||
FieldType.LINKED -> FieldTypeJson.LINKED
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a Bitwarden SDK [Identity] object to a corresponding
|
||||
* [SyncResponseJson.Cipher.Identity] object.
|
||||
*/
|
||||
private fun Identity.toEncryptedNetworkIdentity(): SyncResponseJson.Cipher.Identity =
|
||||
SyncResponseJson.Cipher.Identity(
|
||||
title = title,
|
||||
middleName = middleName,
|
||||
firstName = firstName,
|
||||
lastName = lastName,
|
||||
address1 = address1,
|
||||
address2 = address2,
|
||||
address3 = address3,
|
||||
city = city,
|
||||
state = state,
|
||||
postalCode = postalCode,
|
||||
country = country,
|
||||
company = company,
|
||||
email = email,
|
||||
phone = phone,
|
||||
ssn = ssn,
|
||||
username = username,
|
||||
passportNumber = passportNumber,
|
||||
licenseNumber = licenseNumber,
|
||||
)
|
||||
|
||||
/**
|
||||
* Converts a Bitwarden SDK [SecureNote] object to a corresponding
|
||||
* [SyncResponseJson.Cipher.SecureNote] object.
|
||||
*/
|
||||
private fun SecureNote.toEncryptedNetworkSecureNote(): SyncResponseJson.Cipher.SecureNote =
|
||||
SyncResponseJson.Cipher.SecureNote(
|
||||
type = when (type) {
|
||||
SecureNoteType.GENERIC -> SecureNoteTypeJson.GENERIC
|
||||
},
|
||||
)
|
||||
|
||||
/**
|
||||
* Converts a list of Bitwarden SDK [LoginUri] objects to a corresponding
|
||||
* list of [SyncResponseJson.Cipher.Login.Uri] objects.
|
||||
*/
|
||||
private fun List<LoginUri>.toEncryptedNetworkUriList(): List<SyncResponseJson.Cipher.Login.Uri> =
|
||||
this.map { it.toEncryptedNetworkUri() }
|
||||
|
||||
/**
|
||||
* Converts a Bitwarden SDK [LoginUri] object to a corresponding
|
||||
* [SyncResponseJson.Cipher.Login.Uri] object.
|
||||
*/
|
||||
private fun LoginUri.toEncryptedNetworkUri(): SyncResponseJson.Cipher.Login.Uri =
|
||||
SyncResponseJson.Cipher.Login.Uri(
|
||||
uriMatchType = match?.toNetworkMatchType(),
|
||||
uri = uri,
|
||||
)
|
||||
|
||||
private fun UriMatchType.toNetworkMatchType(): UriMatchTypeJson =
|
||||
when (this) {
|
||||
UriMatchType.DOMAIN -> UriMatchTypeJson.DOMAIN
|
||||
UriMatchType.HOST -> UriMatchTypeJson.HOST
|
||||
UriMatchType.STARTS_WITH -> UriMatchTypeJson.STARTS_WITH
|
||||
UriMatchType.EXACT -> UriMatchTypeJson.EXACT
|
||||
UriMatchType.REGULAR_EXPRESSION -> UriMatchTypeJson.REGULAR_EXPRESSION
|
||||
UriMatchType.NEVER -> UriMatchTypeJson.NEVER
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a Bitwarden SDK [Login] object to a corresponding
|
||||
* [SyncResponseJson.Cipher.Login] object.
|
||||
*/
|
||||
private fun Login.toEncryptedNetworkLogin(): SyncResponseJson.Cipher.Login =
|
||||
SyncResponseJson.Cipher.Login(
|
||||
uris = uris?.toEncryptedNetworkUriList(),
|
||||
totp = totp,
|
||||
password = password,
|
||||
passwordRevisionDate = passwordRevisionDate?.let {
|
||||
LocalDateTime.ofInstant(it, ZoneOffset.UTC)
|
||||
},
|
||||
shouldAutofillOnPageLoad = autofillOnPageLoad,
|
||||
uri = uris?.firstOrNull()?.uri,
|
||||
username = username,
|
||||
)
|
||||
|
||||
/**
|
||||
* Converts a list of Bitwarden SDK [PasswordHistory] objects to a corresponding
|
||||
* list of [SyncResponseJson.Cipher.PasswordHistory] objects.
|
||||
*/
|
||||
@Suppress("MaxLineLength")
|
||||
private fun List<PasswordHistory>.toEncryptedNetworkPasswordHistoryList(): List<SyncResponseJson.Cipher.PasswordHistory> =
|
||||
this.map { it.toEncryptedNetworkPasswordHistory() }
|
||||
|
||||
/**
|
||||
* Converts a Bitwarden SDK [PasswordHistory] object to a corresponding
|
||||
* [SyncResponseJson.Cipher.PasswordHistory] object.
|
||||
*/
|
||||
@Suppress("MaxLineLength")
|
||||
private fun PasswordHistory.toEncryptedNetworkPasswordHistory(): SyncResponseJson.Cipher.PasswordHistory =
|
||||
SyncResponseJson.Cipher.PasswordHistory(
|
||||
password = password,
|
||||
lastUsedDate = LocalDateTime.ofInstant(lastUsedDate, ZoneOffset.UTC),
|
||||
)
|
||||
|
||||
/**
|
||||
* Converts a Bitwarden SDK [CipherRepromptType] object to a corresponding
|
||||
* [CipherRepromptTypeJson] object.
|
||||
*/
|
||||
private fun CipherRepromptType.toNetworkRepromptType(): CipherRepromptTypeJson =
|
||||
when (this) {
|
||||
CipherRepromptType.NONE -> CipherRepromptTypeJson.NONE
|
||||
CipherRepromptType.PASSWORD -> CipherRepromptTypeJson.PASSWORD
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a Bitwarden SDK [CipherType] object to a corresponding
|
||||
* [CipherTypeJson] object.
|
||||
*/
|
||||
private fun CipherType.toNetworkCipherType(): CipherTypeJson =
|
||||
when (this) {
|
||||
CipherType.LOGIN -> CipherTypeJson.LOGIN
|
||||
CipherType.SECURE_NOTE -> CipherTypeJson.SECURE_NOTE
|
||||
CipherType.CARD -> CipherTypeJson.CARD
|
||||
CipherType.IDENTITY -> CipherTypeJson.IDENTITY
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a list of [SyncResponseJson.Cipher] objects to a list of corresponding
|
||||
* Bitwarden SDK [Cipher] objects.
|
||||
@@ -31,7 +227,7 @@ fun List<SyncResponseJson.Cipher>.toEncryptedSdkCipherList(): List<Cipher> =
|
||||
map { it.toEncryptedSdkCipher() }
|
||||
|
||||
/**
|
||||
* Converts a of [SyncResponseJson.Cipher] object to a corresponding
|
||||
* Converts a [SyncResponseJson.Cipher] object to a corresponding
|
||||
* Bitwarden SDK [Cipher] object.
|
||||
*/
|
||||
fun SyncResponseJson.Cipher.toEncryptedSdkCipher(): Cipher =
|
||||
|
||||
@@ -4,10 +4,13 @@ import android.os.Parcelable
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.CreateCipherResult
|
||||
import com.x8bit.bitwarden.ui.platform.base.BaseViewModel
|
||||
import com.x8bit.bitwarden.ui.vault.feature.additem.VaultAddItemState.ItemType.Card.displayStringResId
|
||||
import com.x8bit.bitwarden.ui.vault.feature.additem.VaultAddItemState.ItemType.Identity.displayStringResId
|
||||
import com.x8bit.bitwarden.ui.vault.feature.additem.VaultAddItemState.ItemType.SecureNotes.displayStringResId
|
||||
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toCipherView
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
@@ -31,6 +34,7 @@ private const val KEY_STATE = "state"
|
||||
@Suppress("TooManyFunctions")
|
||||
class VaultAddItemViewModel @Inject constructor(
|
||||
private val savedStateHandle: SavedStateHandle,
|
||||
private val vaultRepository: VaultRepository,
|
||||
) : BaseViewModel<VaultAddItemState, VaultAddItemEvent, VaultAddItemAction>(
|
||||
initialState = savedStateHandle[KEY_STATE] ?: INITIAL_STATE,
|
||||
) {
|
||||
@@ -58,6 +62,10 @@ class VaultAddItemViewModel @Inject constructor(
|
||||
is VaultAddItemAction.ItemType.LoginType -> {
|
||||
handleAddLoginTypeAction(action)
|
||||
}
|
||||
|
||||
is VaultAddItemAction.Internal.CreateCipherResultReceive -> {
|
||||
handleCreateCipherResultReceive(action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,9 +75,11 @@ class VaultAddItemViewModel @Inject constructor(
|
||||
|
||||
private fun handleSaveClick() {
|
||||
viewModelScope.launch {
|
||||
sendEvent(
|
||||
event = VaultAddItemEvent.ShowToast(
|
||||
message = "Save Item",
|
||||
sendAction(
|
||||
action = VaultAddItemAction.Internal.CreateCipherResultReceive(
|
||||
createCipherResult = vaultRepository.createCipher(
|
||||
cipherView = stateFlow.value.selectedType.toCipherView(),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
@@ -106,6 +116,7 @@ class VaultAddItemViewModel @Inject constructor(
|
||||
|
||||
//region Add Login Item Type Handlers
|
||||
|
||||
@Suppress("LongMethod")
|
||||
private fun handleAddLoginTypeAction(
|
||||
action: VaultAddItemAction.ItemType.LoginType,
|
||||
) {
|
||||
@@ -358,6 +369,30 @@ class VaultAddItemViewModel @Inject constructor(
|
||||
|
||||
//endregion Add Login Item Type Handlers
|
||||
|
||||
//region Internal Type Handlers
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
private fun handleCreateCipherResultReceive(action: VaultAddItemAction.Internal.CreateCipherResultReceive) {
|
||||
when (action.createCipherResult) {
|
||||
is CreateCipherResult.Error -> {
|
||||
// TODO Display error dialog BIT-501
|
||||
sendEvent(
|
||||
event = VaultAddItemEvent.ShowToast(
|
||||
message = "Save Item Failure",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
is CreateCipherResult.Success -> {
|
||||
sendEvent(
|
||||
event = VaultAddItemEvent.NavigateBack,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//endregion Internal Type Handlers
|
||||
|
||||
//region Utility Functions
|
||||
|
||||
private inline fun updateLoginType(
|
||||
@@ -669,4 +704,17 @@ sealed class VaultAddItemAction {
|
||||
data object AddNewCustomFieldClick : LoginType()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Models actions that the [VaultAddItemViewModel] itself might send.
|
||||
*/
|
||||
sealed class Internal : VaultAddItemAction() {
|
||||
|
||||
/**
|
||||
* Indicates a result for creating a cipher has been received.
|
||||
*/
|
||||
data class CreateCipherResultReceive(
|
||||
val createCipherResult: CreateCipherResult,
|
||||
) : Internal()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
package com.x8bit.bitwarden.ui.vault.feature.vault.util
|
||||
|
||||
import com.bitwarden.core.CipherRepromptType
|
||||
import com.bitwarden.core.CipherType
|
||||
import com.bitwarden.core.CipherView
|
||||
import com.bitwarden.core.LoginUriView
|
||||
import com.bitwarden.core.LoginView
|
||||
import com.bitwarden.core.UriMatchType
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.VaultData
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.asText
|
||||
import com.x8bit.bitwarden.ui.vault.feature.additem.VaultAddItemState
|
||||
import com.x8bit.bitwarden.ui.vault.feature.vault.VaultState
|
||||
import java.time.Instant
|
||||
|
||||
/**
|
||||
* Transforms a [CipherView] into a [VaultState.ViewState.VaultItem].
|
||||
@@ -74,3 +80,86 @@ fun VaultData.toViewState(): VaultState.ViewState =
|
||||
trashItemsCount = 0,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a [VaultAddItemState.ItemType] into [CipherView].
|
||||
*/
|
||||
fun VaultAddItemState.ItemType.toCipherView(): CipherView =
|
||||
when (this) {
|
||||
is VaultAddItemState.ItemType.Card -> toCardCipherView()
|
||||
is VaultAddItemState.ItemType.Identity -> toIdentityCipherView()
|
||||
is VaultAddItemState.ItemType.Login -> toLoginCipherView()
|
||||
is VaultAddItemState.ItemType.SecureNotes -> toSecureNotesCipherView()
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms [VaultAddItemState.ItemType.SecureNotes] into [CipherView].
|
||||
*/
|
||||
private fun VaultAddItemState.ItemType.SecureNotes.toSecureNotesCipherView(): CipherView =
|
||||
TODO("create SecureNotes CipherView BIT-509")
|
||||
|
||||
/**
|
||||
* Transforms [VaultAddItemState.ItemType.Login] into [CipherView].
|
||||
*/
|
||||
private fun VaultAddItemState.ItemType.Login.toLoginCipherView(): CipherView =
|
||||
CipherView(
|
||||
id = null,
|
||||
// TODO use real organization id BIT-780
|
||||
organizationId = null,
|
||||
// TODO use real folder id BIT-528
|
||||
folderId = null,
|
||||
collectionIds = emptyList(),
|
||||
key = null,
|
||||
name = name,
|
||||
notes = notes,
|
||||
type = CipherType.LOGIN,
|
||||
login = LoginView(
|
||||
username = username,
|
||||
password = password,
|
||||
passwordRevisionDate = null,
|
||||
uris = listOf(
|
||||
LoginUriView(
|
||||
uri = uri,
|
||||
// TODO implement uri settings in BIT-1094
|
||||
match = UriMatchType.DOMAIN,
|
||||
),
|
||||
),
|
||||
// TODO implement totp in BIT-1066
|
||||
totp = null,
|
||||
autofillOnPageLoad = false,
|
||||
),
|
||||
identity = null,
|
||||
card = null,
|
||||
secureNote = null,
|
||||
favorite = favorite,
|
||||
reprompt = if (masterPasswordReprompt) {
|
||||
CipherRepromptType.PASSWORD
|
||||
} else {
|
||||
CipherRepromptType.NONE
|
||||
},
|
||||
organizationUseTotp = false,
|
||||
edit = true,
|
||||
viewPassword = true,
|
||||
localData = null,
|
||||
attachments = null,
|
||||
// TODO implement custom fields BIT-529
|
||||
fields = null,
|
||||
passwordHistory = null,
|
||||
creationDate = Instant.now(),
|
||||
deletedDate = null,
|
||||
// This is a throw away value.
|
||||
// The SDK will eventually remove revisionDate via encryption.
|
||||
revisionDate = Instant.now(),
|
||||
)
|
||||
|
||||
/**
|
||||
* Transforms [VaultAddItemState.ItemType.Identity] into [CipherView].
|
||||
*/
|
||||
private fun VaultAddItemState.ItemType.Identity.toIdentityCipherView(): CipherView =
|
||||
TODO("create Identity CipherView BIT-508")
|
||||
|
||||
/**
|
||||
* Transforms [VaultAddItemState.ItemType.Card] into [CipherView].
|
||||
*/
|
||||
private fun VaultAddItemState.ItemType.Card.toCardCipherView(): CipherView =
|
||||
TODO("create Card CipherView BIT-668")
|
||||
|
||||
Reference in New Issue
Block a user