mirror of
https://github.com/bitwarden/android.git
synced 2024-11-25 02:46:00 +03:00
BIT-2201: Handle URI checksum validation (#1231)
This commit is contained in:
parent
1a12a91a74
commit
04eba5828b
19 changed files with 104 additions and 37 deletions
|
@ -753,6 +753,9 @@ data class SyncResponseJson(
|
|||
|
||||
@SerialName("uri")
|
||||
val uri: String?,
|
||||
|
||||
@SerialName("uriChecksum")
|
||||
val uriChecksum: String?,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -184,6 +184,7 @@ private fun LoginUri.toEncryptedNetworkUri(): SyncResponseJson.Cipher.Login.Uri
|
|||
SyncResponseJson.Cipher.Login.Uri(
|
||||
uriMatchType = match?.toNetworkMatchType(),
|
||||
uri = uri,
|
||||
uriChecksum = uriChecksum,
|
||||
)
|
||||
|
||||
private fun UriMatchType.toNetworkMatchType(): UriMatchTypeJson =
|
||||
|
@ -432,7 +433,7 @@ fun SyncResponseJson.Cipher.Login.Uri.toSdkLoginUri(): LoginUri =
|
|||
LoginUri(
|
||||
uri = uri,
|
||||
match = uriMatchType?.toSdkMatchType(),
|
||||
uriChecksum = null,
|
||||
uriChecksum = uriChecksum,
|
||||
)
|
||||
|
||||
/**
|
||||
|
|
|
@ -126,6 +126,7 @@ class VaultAddEditViewModel @Inject constructor(
|
|||
type = vaultAddEditType.vaultItemCipherType.toItemType(),
|
||||
)
|
||||
}
|
||||
|
||||
is VaultAddEditType.EditItem -> VaultAddEditState.ViewState.Loading
|
||||
is VaultAddEditType.CloneItem -> VaultAddEditState.ViewState.Loading
|
||||
},
|
||||
|
@ -718,6 +719,7 @@ class VaultAddEditViewModel @Inject constructor(
|
|||
id = UUID.randomUUID().toString(),
|
||||
uri = "",
|
||||
match = null,
|
||||
checksum = null,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -1571,7 +1573,12 @@ data class VaultAddEditState(
|
|||
val totp: String? = null,
|
||||
val canViewPassword: Boolean = true,
|
||||
val uriList: List<UriItem> = listOf(
|
||||
UriItem(id = UUID.randomUUID().toString(), uri = "", match = null),
|
||||
UriItem(
|
||||
id = UUID.randomUUID().toString(),
|
||||
uri = "",
|
||||
match = null,
|
||||
checksum = null,
|
||||
),
|
||||
),
|
||||
val fido2CredentialCreationDateTime: Text? = null,
|
||||
) : ItemType() {
|
||||
|
|
|
@ -12,4 +12,5 @@ data class UriItem(
|
|||
val id: String,
|
||||
val uri: String?,
|
||||
val match: UriMatchType?,
|
||||
val checksum: String?,
|
||||
) : Parcelable
|
||||
|
|
|
@ -47,6 +47,7 @@ fun AutofillSaveItem.toDefaultAddTypeContent(
|
|||
id = UUID.randomUUID().toString(),
|
||||
uri = uri,
|
||||
match = null,
|
||||
checksum = null,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -27,6 +27,7 @@ fun AutofillSelectionData.toDefaultAddTypeContent(
|
|||
id = UUID.randomUUID().toString(),
|
||||
uri = uri,
|
||||
match = null,
|
||||
checksum = null,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
@ -272,6 +272,7 @@ private fun List<LoginUriView>?.toUriItems(): List<UriItem> =
|
|||
id = UUID.randomUUID().toString(),
|
||||
uri = "",
|
||||
match = null,
|
||||
checksum = null,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
|
@ -280,6 +281,7 @@ private fun List<LoginUriView>?.toUriItems(): List<UriItem> =
|
|||
id = UUID.randomUUID().toString(),
|
||||
uri = loginUriView.uri,
|
||||
match = loginUriView.match,
|
||||
checksum = loginUriView.uriChecksum,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -329,7 +329,8 @@ private const val CIPHER_JSON = """
|
|||
"uris": [
|
||||
{
|
||||
"match": 1,
|
||||
"uri": "mockUri-1"
|
||||
"uri": "mockUri-1",
|
||||
"uriChecksum": "mockUriChecksum-1"
|
||||
}
|
||||
],
|
||||
"totp": "mockTotp-1",
|
||||
|
|
|
@ -154,4 +154,5 @@ fun createMockUri(number: Int): SyncResponseJson.Cipher.Login.Uri =
|
|||
SyncResponseJson.Cipher.Login.Uri(
|
||||
uri = "mockUri-$number",
|
||||
uriMatchType = UriMatchTypeJson.HOST,
|
||||
uriChecksum = "mockUriChecksum-$number",
|
||||
)
|
||||
|
|
|
@ -306,7 +306,8 @@ private const val CREATE_ATTACHMENT_SUCCESS_JSON = """
|
|||
"uris": [
|
||||
{
|
||||
"match": 1,
|
||||
"uri": "mockUri-1"
|
||||
"uri": "mockUri-1",
|
||||
"uriChecksum": "mockUriChecksum-1"
|
||||
}
|
||||
],
|
||||
"totp": "mockTotp-1",
|
||||
|
@ -416,7 +417,8 @@ private const val CREATE_UPDATE_CIPHER_SUCCESS_JSON = """
|
|||
"uris": [
|
||||
{
|
||||
"match": 1,
|
||||
"uri": "mockUri-1"
|
||||
"uri": "mockUri-1",
|
||||
"uriChecksum": "mockUriChecksum-1"
|
||||
}
|
||||
],
|
||||
"totp": "mockTotp-1",
|
||||
|
|
|
@ -222,7 +222,8 @@ private const val SYNC_SUCCESS_JSON = """
|
|||
"uris": [
|
||||
{
|
||||
"match": 1,
|
||||
"uri": "mockUri-1"
|
||||
"uri": "mockUri-1",
|
||||
"uriChecksum": "mockUriChecksum-1"
|
||||
}
|
||||
],
|
||||
"totp": "mockTotp-1",
|
||||
|
|
|
@ -130,7 +130,7 @@ fun createMockUriView(number: Int): LoginUriView =
|
|||
LoginUriView(
|
||||
uri = "www.mockuri$number.com",
|
||||
match = UriMatchType.HOST,
|
||||
uriChecksum = null,
|
||||
uriChecksum = "mockUriChecksum-$number",
|
||||
)
|
||||
|
||||
/**
|
||||
|
|
|
@ -159,5 +159,5 @@ fun createMockSdkUri(number: Int): LoginUri =
|
|||
LoginUri(
|
||||
uri = "mockUri-$number",
|
||||
match = UriMatchType.HOST,
|
||||
uriChecksum = null,
|
||||
uriChecksum = "mockUriChecksum-$number",
|
||||
)
|
||||
|
|
|
@ -808,7 +808,11 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
|||
fun `in ItemType_Login state changing URI text field should trigger UriValueChange`() {
|
||||
mutableStateFlow.update { currentState ->
|
||||
updateLoginType(currentState) {
|
||||
copy(uriList = listOf(UriItem("TestId", "URI", null)))
|
||||
copy(
|
||||
uriList = listOf(
|
||||
UriItem(id = "TestId", uri = "URI", match = null, checksum = null),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -819,7 +823,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
|||
verify {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LoginType.UriValueChange(
|
||||
UriItem("TestId", "TestURI", null),
|
||||
UriItem(id = "TestId", uri = "TestURI", match = null, checksum = null),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -833,7 +837,11 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
|||
|
||||
mutableStateFlow.update { currentState ->
|
||||
updateLoginType(currentState) {
|
||||
copy(uriList = listOf(UriItem("TestId", "NewURI", null)))
|
||||
copy(
|
||||
uriList = listOf(
|
||||
UriItem(id = "TestId", uri = "NewURI", match = null, checksum = null),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -863,7 +871,11 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
|||
fun `in ItemType_Login Uri settings dialog should send RemoveUriClick action if remove is clicked`() {
|
||||
mutableStateFlow.update { currentState ->
|
||||
updateLoginType(currentState) {
|
||||
copy(uriList = listOf(UriItem("TestId", null, null)))
|
||||
copy(
|
||||
uriList = listOf(
|
||||
UriItem(id = "TestId", uri = null, match = null, checksum = null),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -883,11 +895,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
|||
verify {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LoginType.RemoveUriClick(
|
||||
UriItem(
|
||||
"TestId",
|
||||
null,
|
||||
null,
|
||||
),
|
||||
UriItem(id = "TestId", uri = null, match = null, checksum = null),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -948,7 +956,11 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
|||
fun `in ItemType_Login on URI settings click and on match detection click and option click should emit UriValueChange action`() {
|
||||
mutableStateFlow.update { currentState ->
|
||||
updateLoginType(currentState) {
|
||||
copy(uriList = listOf(UriItem("TestId", null, null)))
|
||||
copy(
|
||||
uriList = listOf(
|
||||
UriItem(id = "TestId", uri = null, match = null, checksum = null),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -978,11 +990,7 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
|||
verify {
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LoginType.UriValueChange(
|
||||
UriItem(
|
||||
"TestId",
|
||||
null,
|
||||
UriMatchType.EXACT,
|
||||
),
|
||||
UriItem(id = "TestId", uri = null, match = UriMatchType.EXACT, checksum = null),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -993,7 +1001,11 @@ class VaultAddEditScreenTest : BaseComposeTest() {
|
|||
fun `in ItemType_Login on URI settings click and on match detection click and cancel click should dismiss the dialog`() {
|
||||
mutableStateFlow.update { currentState ->
|
||||
updateLoginType(currentState) {
|
||||
copy(uriList = listOf(UriItem("TestId", null, null)))
|
||||
copy(
|
||||
uriList = listOf(
|
||||
UriItem(id = "TestId", uri = null, match = null, checksum = null),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -482,7 +482,14 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
|||
typeContentViewState = createLoginTypeContentViewState(
|
||||
username = "mockUsername-1",
|
||||
password = "mockPassword-1",
|
||||
uri = listOf(UriItem("testId", "www.mockuri1.com", UriMatchType.HOST)),
|
||||
uri = listOf(
|
||||
UriItem(
|
||||
id = "testId",
|
||||
uri = "www.mockuri1.com",
|
||||
match = UriMatchType.HOST,
|
||||
checksum = "mockUriChecksum-1",
|
||||
),
|
||||
),
|
||||
totpCode = "mockTotp-1",
|
||||
canViewPassword = true,
|
||||
fido2CredentialCreationDateTime = R.string.created_xy.asText(
|
||||
|
@ -1354,14 +1361,15 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `UriValueChange should update URI value in state`() = runTest {
|
||||
val viewModel = createAddVaultItemViewModel(
|
||||
savedStateHandle = createSavedStateHandleWithState(
|
||||
state = createVaultAddItemState(
|
||||
typeContentViewState = createLoginTypeContentViewState(
|
||||
uri = listOf(UriItem("testID", null, null)),
|
||||
uri = listOf(
|
||||
UriItem(id = "testID", uri = null, match = null, checksum = null),
|
||||
),
|
||||
),
|
||||
),
|
||||
vaultAddEditType = VaultAddEditType.EditItem(DEFAULT_EDIT_ITEM_ID),
|
||||
|
@ -1372,28 +1380,31 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
|||
common = createCommonContentViewState(),
|
||||
isIndividualVaultDisabled = false,
|
||||
type = createLoginTypeContentViewState(
|
||||
uri = listOf(UriItem("testID", "Test", null)),
|
||||
uri = listOf(
|
||||
UriItem(id = "testID", uri = "Test", match = null, checksum = null),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LoginType.UriValueChange(
|
||||
uriItem = UriItem("testID", "Test", null),
|
||||
uriItem = UriItem(id = "testID", uri = "Test", match = null, checksum = null),
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(expectedState, viewModel.stateFlow.value)
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `RemoveUriClick should remove URI value in state`() = runTest {
|
||||
val viewModel = createAddVaultItemViewModel(
|
||||
savedStateHandle = createSavedStateHandleWithState(
|
||||
state = createVaultAddItemState(
|
||||
typeContentViewState = createLoginTypeContentViewState(
|
||||
uri = listOf(UriItem("testID", null, null)),
|
||||
uri = listOf(
|
||||
UriItem(id = "testID", uri = null, match = null, checksum = null),
|
||||
),
|
||||
),
|
||||
),
|
||||
vaultAddEditType = VaultAddEditType.EditItem(DEFAULT_EDIT_ITEM_ID),
|
||||
|
@ -1412,7 +1423,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
|||
|
||||
viewModel.trySendAction(
|
||||
VaultAddEditAction.ItemType.LoginType.RemoveUriClick(
|
||||
uriItem = UriItem("testID", null, null),
|
||||
uriItem = UriItem(id = "testID", uri = null, match = null, checksum = null),
|
||||
),
|
||||
)
|
||||
|
||||
|
@ -1428,7 +1439,10 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
|||
|
||||
val expectedState = createVaultAddItemState(
|
||||
typeContentViewState = createLoginTypeContentViewState().copy(
|
||||
uriList = listOf(UriItem("testId", "", null), UriItem("testId2", "", null)),
|
||||
uriList = listOf(
|
||||
UriItem(id = "testId", uri = "", match = null, checksum = null),
|
||||
UriItem(id = "testId2", uri = "", match = null, checksum = null),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
|
@ -2391,7 +2405,9 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
|||
private fun createLoginTypeContentViewState(
|
||||
username: String = "",
|
||||
password: String = "",
|
||||
uri: List<UriItem> = listOf(UriItem("testId", "", null)),
|
||||
uri: List<UriItem> = listOf(
|
||||
UriItem(id = "testId", uri = "", match = null, checksum = null),
|
||||
),
|
||||
totpCode: String? = null,
|
||||
canViewPassword: Boolean = true,
|
||||
fido2CredentialCreationDateTime: Text? = null,
|
||||
|
|
|
@ -63,6 +63,7 @@ class AutofillSaveItemExtensionsTest {
|
|||
id = "uuid",
|
||||
uri = "https://www.test.com",
|
||||
match = null,
|
||||
checksum = null,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -53,6 +53,7 @@ class AutofillSelectionDataExtensionsTest {
|
|||
id = "uuid",
|
||||
uri = "https://www.test.com",
|
||||
match = null,
|
||||
checksum = null,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -192,7 +192,14 @@ class CipherViewExtensionsTest {
|
|||
type = VaultAddEditState.ViewState.Content.ItemType.Login(
|
||||
username = "username",
|
||||
password = "password",
|
||||
uriList = listOf(UriItem(TEST_ID, "www.example.com", null)),
|
||||
uriList = listOf(
|
||||
UriItem(
|
||||
id = TEST_ID,
|
||||
uri = "www.example.com",
|
||||
match = null,
|
||||
checksum = null,
|
||||
),
|
||||
),
|
||||
totp = "otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example",
|
||||
canViewPassword = false,
|
||||
fido2CredentialCreationDateTime = R.string.created_xy.asText(
|
||||
|
|
|
@ -55,7 +55,14 @@ class VaultAddItemStateExtensionsTest {
|
|||
type = VaultAddEditState.ViewState.Content.ItemType.Login(
|
||||
username = "mockUsername-1",
|
||||
password = "mockPassword-1",
|
||||
uriList = listOf(UriItem("testId", "mockUri-1", UriMatchType.DOMAIN)),
|
||||
uriList = listOf(
|
||||
UriItem(
|
||||
id = "testId",
|
||||
uri = "mockUri-1",
|
||||
match = UriMatchType.DOMAIN,
|
||||
checksum = null,
|
||||
),
|
||||
),
|
||||
totp = "otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example",
|
||||
fido2CredentialCreationDateTime = null,
|
||||
),
|
||||
|
@ -138,7 +145,9 @@ class VaultAddItemStateExtensionsTest {
|
|||
type = VaultAddEditState.ViewState.Content.ItemType.Login(
|
||||
username = "mockUsername-1",
|
||||
password = "mockPassword-1",
|
||||
uriList = listOf(UriItem("TestId", "mockUri-1", null)),
|
||||
uriList = listOf(
|
||||
UriItem(id = "TestId", uri = "mockUri-1", match = null, checksum = null),
|
||||
),
|
||||
totp = "otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example",
|
||||
),
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue