mirror of
https://github.com/bitwarden/android.git
synced 2025-03-15 02:38:50 +03:00
Merge branch 'main' into main
This commit is contained in:
commit
be5c301938
19 changed files with 115 additions and 102 deletions
|
@ -731,13 +731,13 @@ data class SyncResponseJson(
|
|||
@Serializable
|
||||
data class SshKey(
|
||||
@SerialName("publicKey")
|
||||
val publicKey: String?,
|
||||
val publicKey: String,
|
||||
|
||||
@SerialName("privateKey")
|
||||
val privateKey: String?,
|
||||
val privateKey: String,
|
||||
|
||||
@SerialName("keyFingerprint")
|
||||
val keyFingerprint: String?,
|
||||
val keyFingerprint: String,
|
||||
)
|
||||
|
||||
/**
|
||||
|
|
|
@ -300,7 +300,7 @@ fun LazyListScope.vaultAddEditCardItems(
|
|||
)
|
||||
}
|
||||
|
||||
if (isAddItemMode) {
|
||||
if (isAddItemMode && commonState.hasOrganizations) {
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
BitwardenListHeaderText(
|
||||
|
|
|
@ -414,7 +414,7 @@ fun LazyListScope.vaultAddEditIdentityItems(
|
|||
)
|
||||
}
|
||||
|
||||
if (isAddItemMode) {
|
||||
if (isAddItemMode && commonState.hasOrganizations) {
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
BitwardenListHeaderText(
|
||||
|
|
|
@ -317,7 +317,7 @@ fun LazyListScope.vaultAddEditLoginItems(
|
|||
)
|
||||
}
|
||||
|
||||
if (isAddItemMode) {
|
||||
if (isAddItemMode && commonState.hasOrganizations) {
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
BitwardenListHeaderText(
|
||||
|
|
|
@ -176,7 +176,7 @@ fun LazyListScope.vaultAddEditSecureNotesItems(
|
|||
)
|
||||
}
|
||||
|
||||
if (isAddItemMode) {
|
||||
if (isAddItemMode && commonState.hasOrganizations) {
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
BitwardenListHeaderText(
|
||||
|
|
|
@ -2114,6 +2114,7 @@ data class VaultAddEditState(
|
|||
* @property availableFolders The list of folders that this item could be added too.
|
||||
* @property selectedOwnerId The ID of the owner associated with the item.
|
||||
* @property availableOwners A list of available owners.
|
||||
* @property hasOrganizations Indicates if the user is part of any organizations.
|
||||
*/
|
||||
@Parcelize
|
||||
data class Common(
|
||||
|
@ -2129,6 +2130,7 @@ data class VaultAddEditState(
|
|||
val availableFolders: List<Folder> = emptyList(),
|
||||
val selectedOwnerId: String? = null,
|
||||
val availableOwners: List<Owner> = emptyList(),
|
||||
val hasOrganizations: Boolean = false,
|
||||
) : Parcelable {
|
||||
|
||||
/**
|
||||
|
|
|
@ -106,6 +106,7 @@ fun CipherView.toViewState(
|
|||
masterPasswordReprompt = this.reprompt == CipherRepromptType.PASSWORD,
|
||||
notes = this.notes.orEmpty(),
|
||||
availableOwners = emptyList(),
|
||||
hasOrganizations = false,
|
||||
customFieldData = this.fields.orEmpty().map { it.toCustomField() },
|
||||
),
|
||||
isIndividualVaultDisabled = isIndividualVaultDisabled,
|
||||
|
@ -139,6 +140,7 @@ fun VaultAddEditState.ViewState.appendFolderAndOwnerData(
|
|||
isIndividualVaultDisabled = isIndividualVaultDisabled,
|
||||
),
|
||||
isUnlockWithPasswordEnabled = activeAccount.hasMasterPassword,
|
||||
hasOrganizations = activeAccount.organizations.isNotEmpty(),
|
||||
),
|
||||
)
|
||||
} ?: this
|
||||
|
|
|
@ -53,58 +53,52 @@ fun VaultItemSshKeyContent(
|
|||
)
|
||||
}
|
||||
|
||||
sshKeyItemState.publicKey?.let { publicKey ->
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
BitwardenTextField(
|
||||
label = stringResource(id = R.string.public_key),
|
||||
value = publicKey,
|
||||
onValueChange = { },
|
||||
singleLine = false,
|
||||
readOnly = true,
|
||||
modifier = Modifier
|
||||
.testTag("SshKeyItemPublicKeyEntry")
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
)
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
BitwardenTextField(
|
||||
label = stringResource(id = R.string.public_key),
|
||||
value = sshKeyItemState.publicKey,
|
||||
onValueChange = { },
|
||||
singleLine = false,
|
||||
readOnly = true,
|
||||
modifier = Modifier
|
||||
.testTag("SshKeyItemPublicKeyEntry")
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
)
|
||||
}
|
||||
|
||||
sshKeyItemState.privateKey?.let { privateKey ->
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
BitwardenPasswordField(
|
||||
label = stringResource(id = R.string.private_key),
|
||||
value = privateKey,
|
||||
onValueChange = { },
|
||||
singleLine = false,
|
||||
readOnly = true,
|
||||
showPassword = sshKeyItemState.showPrivateKey,
|
||||
showPasswordTestTag = "ViewPrivateKeyButton",
|
||||
showPasswordChange = vaultSshKeyItemTypeHandlers.onShowPrivateKeyClick,
|
||||
modifier = Modifier
|
||||
.testTag("SshKeyItemPrivateKeyEntry")
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
)
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
BitwardenPasswordField(
|
||||
label = stringResource(id = R.string.private_key),
|
||||
value = sshKeyItemState.privateKey,
|
||||
onValueChange = { },
|
||||
singleLine = false,
|
||||
readOnly = true,
|
||||
showPassword = sshKeyItemState.showPrivateKey,
|
||||
showPasswordTestTag = "ViewPrivateKeyButton",
|
||||
showPasswordChange = vaultSshKeyItemTypeHandlers.onShowPrivateKeyClick,
|
||||
modifier = Modifier
|
||||
.testTag("SshKeyItemPrivateKeyEntry")
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
)
|
||||
}
|
||||
|
||||
sshKeyItemState.fingerprint?.let { fingerprint ->
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
BitwardenTextField(
|
||||
label = stringResource(id = R.string.fingerprint),
|
||||
value = fingerprint,
|
||||
onValueChange = { },
|
||||
singleLine = false,
|
||||
readOnly = true,
|
||||
modifier = Modifier
|
||||
.testTag("SshKeyItemFingerprintEntry")
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
)
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
BitwardenTextField(
|
||||
label = stringResource(id = R.string.fingerprint),
|
||||
value = sshKeyItemState.fingerprint,
|
||||
onValueChange = { },
|
||||
singleLine = false,
|
||||
readOnly = true,
|
||||
modifier = Modifier
|
||||
.testTag("SshKeyItemFingerprintEntry")
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
|
|
|
@ -1410,9 +1410,9 @@ data class VaultItemState(
|
|||
*/
|
||||
data class SshKey(
|
||||
val name: String?,
|
||||
val publicKey: String?,
|
||||
val privateKey: String?,
|
||||
val fingerprint: String?,
|
||||
val publicKey: String,
|
||||
val privateKey: String,
|
||||
val fingerprint: String,
|
||||
val showPrivateKey: Boolean,
|
||||
) : ItemType()
|
||||
}
|
||||
|
|
|
@ -995,9 +995,9 @@ data class VaultState(
|
|||
override val extraIconList: List<IconRes> = emptyList(),
|
||||
override val overflowOptions: List<ListingItemOverflowAction.VaultAction>,
|
||||
override val shouldShowMasterPasswordReprompt: Boolean,
|
||||
val publicKey: Text?,
|
||||
val privateKey: Text?,
|
||||
val fingerprint: Text?,
|
||||
val publicKey: Text,
|
||||
val privateKey: Text,
|
||||
val fingerprint: Text,
|
||||
) : VaultItem() {
|
||||
override val supportingLabel: Text? get() = null
|
||||
}
|
||||
|
|
|
@ -74,9 +74,9 @@ private fun VaultAddEditState.ViewState.Content.ItemType.toCipherType(): CipherT
|
|||
private fun VaultAddEditState.ViewState.Content.ItemType.toSshKeyView(): SshKeyView? =
|
||||
(this as? VaultAddEditState.ViewState.Content.ItemType.SshKey)?.let {
|
||||
SshKeyView(
|
||||
publicKey = it.publicKey.orNullIfBlank(),
|
||||
privateKey = it.privateKey.orNullIfBlank(),
|
||||
fingerprint = it.fingerprint.orNullIfBlank(),
|
||||
publicKey = it.publicKey,
|
||||
privateKey = it.privateKey,
|
||||
fingerprint = it.fingerprint,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -276,13 +276,16 @@ private fun CipherView.toVaultItemOrNull(
|
|||
name = name.asText(),
|
||||
publicKey = sshKey
|
||||
?.publicKey
|
||||
?.asText(),
|
||||
.orEmpty()
|
||||
.asText(),
|
||||
privateKey = sshKey
|
||||
?.privateKey
|
||||
?.asText(),
|
||||
.orEmpty()
|
||||
.asText(),
|
||||
fingerprint = sshKey
|
||||
?.fingerprint
|
||||
?.asText(),
|
||||
.orEmpty()
|
||||
.asText(),
|
||||
overflowOptions = toOverflowActions(
|
||||
hasMasterPassword = hasMasterPassword,
|
||||
isPremiumUser = isPremiumUser,
|
||||
|
|
|
@ -2361,6 +2361,31 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ownership section should not be displayed when no organizations present`() {
|
||||
updateStateWithOwners(selectedOwnerId = "mockOwnerId-2")
|
||||
|
||||
composeTestRule
|
||||
.onNodeWithTextAfterScroll(text = "mockCollectionName-2")
|
||||
.assertIsDisplayed()
|
||||
|
||||
updateStateWithOwners(
|
||||
selectedOwnerId = null,
|
||||
availableOwners = listOf(
|
||||
VaultAddEditState.Owner(
|
||||
id = null,
|
||||
name = "placeholder@email.com",
|
||||
collections = DEFAULT_COLLECTIONS,
|
||||
),
|
||||
),
|
||||
hasOrganizations = false,
|
||||
)
|
||||
|
||||
composeTestRule
|
||||
.onNodeWithText(text = "mockCollectionName-2")
|
||||
.assertDoesNotExist()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Collection list should display according to state`() {
|
||||
updateStateWithOwners(selectedOwnerId = "mockOwnerId-2")
|
||||
|
@ -3482,12 +3507,14 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
|||
private fun updateStateWithOwners(
|
||||
selectedOwnerId: String? = null,
|
||||
availableOwners: List<VaultAddEditState.Owner> = DEFAULT_OWNERS,
|
||||
hasOrganizations: Boolean = true,
|
||||
) {
|
||||
mutableStateFlow.update { currentState ->
|
||||
updateCommonContent(currentState) {
|
||||
copy(
|
||||
selectedOwnerId = selectedOwnerId,
|
||||
availableOwners = availableOwners,
|
||||
hasOrganizations = hasOrganizations,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4026,6 +4026,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
|||
),
|
||||
availableOwners: List<VaultAddEditState.Owner> = createOwnerList(),
|
||||
selectedOwnerId: String? = null,
|
||||
hasOrganizations: Boolean = true,
|
||||
): VaultAddEditState.ViewState.Content.Common =
|
||||
VaultAddEditState.ViewState.Content.Common(
|
||||
name = name,
|
||||
|
@ -4038,6 +4039,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
|||
originalCipher = originalCipher,
|
||||
availableFolders = availableFolders,
|
||||
availableOwners = availableOwners,
|
||||
hasOrganizations = hasOrganizations,
|
||||
)
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
|
|
|
@ -505,6 +505,7 @@ class CipherViewExtensionsTest {
|
|||
name = "mockName-1",
|
||||
),
|
||||
),
|
||||
hasOrganizations = true,
|
||||
availableOwners = listOf(
|
||||
VaultAddEditState.Owner(
|
||||
id = null,
|
||||
|
|
|
@ -2151,12 +2151,6 @@ class VaultItemScreenTest : BaseComposeTest() {
|
|||
val publicKey = "the public key"
|
||||
mutableStateFlow.update { it.copy(viewState = DEFAULT_SSH_KEY_VIEW_STATE) }
|
||||
composeTestRule.onNodeWithTextAfterScroll(publicKey).assertIsDisplayed()
|
||||
|
||||
mutableStateFlow.update { currentState ->
|
||||
updateSshKeyType(currentState) { copy(publicKey = null) }
|
||||
}
|
||||
|
||||
composeTestRule.assertScrollableNodeDoesNotExist(publicKey)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -2173,12 +2167,6 @@ class VaultItemScreenTest : BaseComposeTest() {
|
|||
composeTestRule
|
||||
.onNodeWithText(privateKey)
|
||||
.assertIsDisplayed()
|
||||
|
||||
mutableStateFlow.update { currentState ->
|
||||
updateSshKeyType(currentState) { copy(privateKey = null) }
|
||||
}
|
||||
|
||||
composeTestRule.assertScrollableNodeDoesNotExist(privateKey)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -2205,12 +2193,6 @@ class VaultItemScreenTest : BaseComposeTest() {
|
|||
val fingerprint = "the fingerprint"
|
||||
mutableStateFlow.update { it.copy(viewState = DEFAULT_SSH_KEY_VIEW_STATE) }
|
||||
composeTestRule.onNodeWithTextAfterScroll(fingerprint).assertIsDisplayed()
|
||||
|
||||
mutableStateFlow.update { currentState ->
|
||||
updateSshKeyType(currentState) { copy(fingerprint = null) }
|
||||
}
|
||||
|
||||
composeTestRule.assertScrollableNodeDoesNotExist(fingerprint)
|
||||
}
|
||||
|
||||
//endregion ssh key
|
||||
|
|
|
@ -75,9 +75,9 @@ fun createIdentityView(isEmpty: Boolean): IdentityView =
|
|||
|
||||
fun createSshKeyView(isEmpty: Boolean): SshKeyView =
|
||||
SshKeyView(
|
||||
privateKey = "privateKey".takeUnless { isEmpty },
|
||||
publicKey = "publicKey".takeUnless { isEmpty },
|
||||
fingerprint = "fingerprint".takeUnless { isEmpty },
|
||||
privateKey = "privateKey".takeUnless { isEmpty }.orEmpty(),
|
||||
publicKey = "publicKey".takeUnless { isEmpty }.orEmpty(),
|
||||
fingerprint = "fingerprint".takeUnless { isEmpty }.orEmpty(),
|
||||
)
|
||||
|
||||
fun createCipherView(type: CipherType, isEmpty: Boolean): CipherView =
|
||||
|
@ -154,7 +154,7 @@ fun createCipherView(type: CipherType, isEmpty: Boolean): CipherView =
|
|||
creationDate = Instant.ofEpochSecond(1_000L),
|
||||
deletedDate = null,
|
||||
revisionDate = Instant.ofEpochSecond(1_000L),
|
||||
sshKey = createSshKeyView(isEmpty = isEmpty),
|
||||
sshKey = createSshKeyView(isEmpty),
|
||||
)
|
||||
|
||||
fun createCommonContent(
|
||||
|
@ -272,8 +272,8 @@ fun createIdentityContent(
|
|||
fun createSshKeyContent(isEmpty: Boolean): VaultItemState.ViewState.Content.ItemType.SshKey =
|
||||
VaultItemState.ViewState.Content.ItemType.SshKey(
|
||||
name = "mockName".takeUnless { isEmpty },
|
||||
privateKey = "privateKey".takeUnless { isEmpty },
|
||||
publicKey = "publicKey".takeUnless { isEmpty },
|
||||
fingerprint = "fingerprint".takeUnless { isEmpty },
|
||||
privateKey = "privateKey".takeUnless { isEmpty }.orEmpty(),
|
||||
publicKey = "publicKey".takeUnless { isEmpty }.orEmpty(),
|
||||
fingerprint = "fingerprint".takeUnless { isEmpty }.orEmpty(),
|
||||
showPrivateKey = false,
|
||||
)
|
||||
|
|
|
@ -906,9 +906,9 @@ class VaultDataExtensionsTest {
|
|||
folderId = null,
|
||||
sshKey = createMockSshKeyView(number = 1)
|
||||
.copy(
|
||||
publicKey = null,
|
||||
privateKey = null,
|
||||
fingerprint = null,
|
||||
publicKey = "publicKey",
|
||||
privateKey = "privateKey",
|
||||
fingerprint = "fingerprint",
|
||||
),
|
||||
),
|
||||
createMockCipherView(
|
||||
|
@ -945,16 +945,16 @@ class VaultDataExtensionsTest {
|
|||
createMockSshKeyVaultItem(number = 1),
|
||||
createMockSshKeyVaultItem(number = 2)
|
||||
.copy(
|
||||
publicKey = null,
|
||||
privateKey = null,
|
||||
fingerprint = null,
|
||||
publicKey = "publicKey".asText(),
|
||||
privateKey = "privateKey".asText(),
|
||||
fingerprint = "fingerprint".asText(),
|
||||
shouldShowMasterPasswordReprompt = true,
|
||||
),
|
||||
createMockSshKeyVaultItem(number = 3)
|
||||
.copy(
|
||||
publicKey = null,
|
||||
privateKey = null,
|
||||
fingerprint = null,
|
||||
publicKey = "".asText(),
|
||||
privateKey = "".asText(),
|
||||
fingerprint = "".asText(),
|
||||
),
|
||||
),
|
||||
trashItemsCount = 0,
|
||||
|
|
|
@ -24,7 +24,7 @@ androidxSplash = "1.1.0-rc01"
|
|||
androidXAppCompat = "1.7.0"
|
||||
androdixAutofill = "1.1.0"
|
||||
androidxWork = "2.9.1"
|
||||
bitwardenSdk = "1.0.0-20241024.173753-4"
|
||||
bitwardenSdk = "1.0.0-20241030.101847-8"
|
||||
crashlytics = "3.0.2"
|
||||
detekt = "1.23.7"
|
||||
firebaseBom = "33.5.1"
|
||||
|
|
Loading…
Add table
Reference in a new issue