From 1a33371623b8fd693e767051e6e03ad68109efe6 Mon Sep 17 00:00:00 2001 From: Boris Safonov Date: Mon, 27 May 2024 15:16:57 +0300 Subject: [PATCH 1/6] fix: OtherUser devices: wrong MLS data --- .../ui/authentication/devices/DeviceItem.kt | 11 ++++---- .../ui/authentication/devices/model/Device.kt | 16 +++++------- .../settings/devices/DeviceDetailsScreen.kt | 26 ++++++++++--------- .../devices/DeviceDetailsViewModel.kt | 2 +- .../EndToEndIdentityCertificateItem.kt | 2 ++ .../settings/devices/SelfDevicesViewModel.kt | 4 +-- .../other/OtherUserDevicesScreen.kt | 2 +- .../other/OtherUserProfileScreenViewModel.kt | 2 +- 8 files changed, 33 insertions(+), 32 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/authentication/devices/DeviceItem.kt b/app/src/main/kotlin/com/wire/android/ui/authentication/devices/DeviceItem.kt index 2b19ebb5c43..993d1f187b2 100644 --- a/app/src/main/kotlin/com/wire/android/ui/authentication/devices/DeviceItem.kt +++ b/app/src/main/kotlin/com/wire/android/ui/authentication/devices/DeviceItem.kt @@ -183,13 +183,12 @@ private fun DeviceItemTexts( ) if (shouldShowVerifyLabel) { if (shouldShowE2EIInfo) { - MLSVerificationIcon(device.e2eiCertificateStatus) + MLSVerificationIcon(device.e2eiCertificate?.status) } Spacer(modifier = Modifier.width(MaterialTheme.wireDimensions.spacing8x)) if (device.isVerifiedProteus && !isCurrentClient) ProteusVerifiedIcon( - Modifier - .wrapContentWidth() - .align(Alignment.CenterVertically)) + Modifier.wrapContentWidth().align(Alignment.CenterVertically) + ) } } @@ -206,7 +205,7 @@ private fun DeviceItemTexts( Spacer(modifier = Modifier.height(MaterialTheme.wireDimensions.removeDeviceItemTitleVerticalPadding)) - device.mlsPublicKeys?.values?.firstOrNull()?.let { mlsThumbprint -> + device.e2eiCertificate?.let { certificate -> Text( style = MaterialTheme.wireTypography.subline01, color = MaterialTheme.wireColorScheme.labelText, @@ -214,7 +213,7 @@ private fun DeviceItemTexts( overflow = TextOverflow.Ellipsis, text = stringResource( R.string.remove_device_mls_thumbprint_label, - mlsThumbprint.formatAsFingerPrint() + certificate.thumbprint.formatAsFingerPrint() ), modifier = Modifier .fillMaxWidth() diff --git a/app/src/main/kotlin/com/wire/android/ui/authentication/devices/model/Device.kt b/app/src/main/kotlin/com/wire/android/ui/authentication/devices/model/Device.kt index 4f5e3911eb0..435d8443803 100644 --- a/app/src/main/kotlin/com/wire/android/ui/authentication/devices/model/Device.kt +++ b/app/src/main/kotlin/com/wire/android/ui/authentication/devices/model/Device.kt @@ -26,7 +26,7 @@ import com.wire.android.R import com.wire.android.util.ui.UIText import com.wire.kalium.logic.data.client.Client import com.wire.kalium.logic.data.conversation.ClientId -import com.wire.kalium.logic.feature.e2ei.CertificateStatus +import com.wire.kalium.logic.feature.e2ei.E2eiCertificate import com.wire.kalium.logic.util.inWholeWeeks import com.wire.kalium.util.DateTimeUtil.toIsoDateTimeString import kotlinx.datetime.Clock @@ -38,18 +38,16 @@ data class Device( val lastActiveInWholeWeeks: Int? = null, val isValid: Boolean = true, val isVerifiedProteus: Boolean = false, - val mlsPublicKeys: Map? = null, - val e2eiCertificateStatus: CertificateStatus? = null + val e2eiCertificate: E2eiCertificate? = null ) { - constructor(client: Client, e2eiCertificateStatus: CertificateStatus? = null) : this( + constructor(client: Client, e2eiCertificate: E2eiCertificate? = null) : this( name = client.displayName(), clientId = client.id, registrationTime = client.registrationTime?.toIsoDateTimeString(), lastActiveInWholeWeeks = client.lastActiveInWholeWeeks(), isValid = client.isValid, isVerifiedProteus = client.isVerified, - mlsPublicKeys = client.mlsPublicKeys, - e2eiCertificateStatus = e2eiCertificateStatus + e2eiCertificate = e2eiCertificate ) fun updateFromClient(client: Client): Device = copy( @@ -59,11 +57,11 @@ data class Device( lastActiveInWholeWeeks = client.lastActiveInWholeWeeks(), isValid = client.isValid, isVerifiedProteus = client.isVerified, - mlsPublicKeys = client.mlsPublicKeys, + e2eiCertificate = null, ) - fun updateE2EICertificateStatus(e2eiCertificateStatus: CertificateStatus): Device = copy( - e2eiCertificateStatus = e2eiCertificateStatus + fun updateE2EICertificate(e2eiCertificate: E2eiCertificate): Device = copy( + e2eiCertificate = e2eiCertificate ) } diff --git a/app/src/main/kotlin/com/wire/android/ui/settings/devices/DeviceDetailsScreen.kt b/app/src/main/kotlin/com/wire/android/ui/settings/devices/DeviceDetailsScreen.kt index 7f0cd3a8c02..9a65836a5eb 100644 --- a/app/src/main/kotlin/com/wire/android/ui/settings/devices/DeviceDetailsScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/settings/devices/DeviceDetailsScreen.kt @@ -91,9 +91,11 @@ import com.wire.android.util.extension.formatAsString import com.wire.android.util.ui.UIText import com.wire.kalium.logic.CoreFailure import com.wire.kalium.logic.data.conversation.ClientId +import com.wire.kalium.logic.feature.e2ei.CertificateStatus import com.wire.kalium.logic.feature.e2ei.E2eiCertificate import com.wire.kalium.logic.feature.e2ei.usecase.E2EIEnrollmentResult import com.wire.kalium.logic.functional.Either +import kotlinx.datetime.Instant @RootNavGraph @Destination( @@ -127,6 +129,7 @@ fun DeviceDetailsScreen( ) } } + @Suppress("ComplexMethod") @Composable fun DeviceDetailsContent( @@ -187,9 +190,9 @@ fun DeviceDetailsContent( .background(MaterialTheme.wireColorScheme.surface) ) { - state.device.mlsPublicKeys?.forEach { (mlsProtocolType, mlsThumbprint) -> + state.device.e2eiCertificate?.let { certificate -> item { - DeviceMLSSignatureItem(mlsThumbprint, mlsProtocolType, screenState::copyMessage) + DeviceMLSSignatureItem(certificate.thumbprint, screenState::copyMessage) Divider(color = MaterialTheme.wireColorScheme.background) } } @@ -323,7 +326,7 @@ private fun DeviceDetailsTopBar( ) if (shouldShowE2EIInfo) { - MLSVerificationIcon(device.e2eiCertificateStatus) + MLSVerificationIcon(device.e2eiCertificate?.status) } if (!isCurrentDevice && device.isVerifiedProteus) { @@ -373,17 +376,9 @@ fun DeviceKeyFingerprintItem( @Composable fun DeviceMLSSignatureItem( mlsThumbprint: String, - mlsProtocolType: String, onCopy: (String) -> Unit ) { - FolderHeader( - name = stringResource(id = R.string.label_mls_signature, mlsProtocolType).uppercase(), - modifier = Modifier - .background(MaterialTheme.wireColorScheme.background) - .fillMaxWidth() - ) - DeviceDetailSectionContent( stringResource(id = R.string.label_mls_thumbprint), sectionText = mlsThumbprint.formatAsFingerPrint(), @@ -578,7 +573,14 @@ fun PreviewDeviceDetailsScreen() { clientId = ClientId(""), name = UIText.DynamicString("My Device"), registrationTime = "2022-03-24T18:02:30.360Z", - mlsPublicKeys = mapOf("Ed25519" to "lekvmrlkgvnrelkmvrlgkvlknrgb0348gi34t09gj34v034ithjoievw") + e2eiCertificate = E2eiCertificate( + "handler", + CertificateStatus.VALID, + "serial", + "date", + "Thumbprint", + Instant.DISTANT_FUTURE + ) ), isCurrentDevice = false ), diff --git a/app/src/main/kotlin/com/wire/android/ui/settings/devices/DeviceDetailsViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/settings/devices/DeviceDetailsViewModel.kt index af5297be976..6cc9a38333d 100644 --- a/app/src/main/kotlin/com/wire/android/ui/settings/devices/DeviceDetailsViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/settings/devices/DeviceDetailsViewModel.kt @@ -119,7 +119,7 @@ class DeviceDetailsViewModel @Inject constructor( isE2eiCertificateActivated = true, e2eiCertificate = certificate.certificate, isLoadingCertificate = false, - device = state.device.updateE2EICertificateStatus(certificate.certificate.status) + device = state.device.updateE2EICertificate(certificate.certificate) ) } else { state.copy(isE2eiCertificateActivated = false, isLoadingCertificate = false) diff --git a/app/src/main/kotlin/com/wire/android/ui/settings/devices/EndToEndIdentityCertificateItem.kt b/app/src/main/kotlin/com/wire/android/ui/settings/devices/EndToEndIdentityCertificateItem.kt index d21dd51ceae..67996859fad 100644 --- a/app/src/main/kotlin/com/wire/android/ui/settings/devices/EndToEndIdentityCertificateItem.kt +++ b/app/src/main/kotlin/com/wire/android/ui/settings/devices/EndToEndIdentityCertificateItem.kt @@ -104,6 +104,8 @@ fun EndToEndIdentityCertificateItem( } } + // Show cyka data here + CertificateStatus.VALID -> { E2EIStatusRow( label = stringResource(id = R.string.e2ei_certificat_status_valid), diff --git a/app/src/main/kotlin/com/wire/android/ui/settings/devices/SelfDevicesViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/settings/devices/SelfDevicesViewModel.kt index 6a57ced5b92..572d963cde7 100644 --- a/app/src/main/kotlin/com/wire/android/ui/settings/devices/SelfDevicesViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/settings/devices/SelfDevicesViewModel.kt @@ -70,10 +70,10 @@ class SelfDevicesViewModel @Inject constructor( isLoadingClientsList = false, currentDevice = result.clients .firstOrNull { it.id == currentClientId } - ?.let { Device(it, e2eiCertificates[it.id.value]?.status) }, + ?.let { Device(it, e2eiCertificates[it.id.value]) }, deviceList = result.clients .filter { it.id != currentClientId } - .map { Device(it, e2eiCertificates[it.id.value]?.status) } + .map { Device(it, e2eiCertificates[it.id.value]) } ) } } diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserDevicesScreen.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserDevicesScreen.kt index bc219253d2c..4b5d91f6a30 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserDevicesScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserDevicesScreen.kt @@ -123,7 +123,7 @@ private fun OtherUserDevicesContent( onClickAction = onDeviceClick, icon = Icons.Filled.ChevronRight.Icon(), shouldShowVerifyLabel = true, - shouldShowE2EIInfo = item.e2eiCertificateStatus != null + shouldShowE2EIInfo = item.e2eiCertificate != null ) if (index < otherUserDevices.lastIndex) WireDivider() } diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreenViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreenViewModel.kt index 5a990572c02..c84956a0cbd 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreenViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreenViewModel.kt @@ -166,7 +166,7 @@ class OtherUserProfileScreenViewModel @Inject constructor( is ObserveClientsByUserIdUseCase.Result.Success -> { state = state.copy(otherUserDevices = it.clients.map { item -> - Device(item, e2eiCertificates[item.id.value]?.status) + Device(item, e2eiCertificates[item.id.value]) }) } } From b8cd5d95c1746ae09fd48b1c9c222919540099f5 Mon Sep 17 00:00:00 2001 From: Boris Safonov Date: Mon, 27 May 2024 16:42:32 +0300 Subject: [PATCH 2/6] Removed comments --- .../ui/settings/devices/EndToEndIdentityCertificateItem.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/settings/devices/EndToEndIdentityCertificateItem.kt b/app/src/main/kotlin/com/wire/android/ui/settings/devices/EndToEndIdentityCertificateItem.kt index 67996859fad..d21dd51ceae 100644 --- a/app/src/main/kotlin/com/wire/android/ui/settings/devices/EndToEndIdentityCertificateItem.kt +++ b/app/src/main/kotlin/com/wire/android/ui/settings/devices/EndToEndIdentityCertificateItem.kt @@ -104,8 +104,6 @@ fun EndToEndIdentityCertificateItem( } } - // Show cyka data here - CertificateStatus.VALID -> { E2EIStatusRow( label = stringResource(id = R.string.e2ei_certificat_status_valid), From 1b90bbf12ceffb634171a57f71603bf9bacaf941 Mon Sep 17 00:00:00 2001 From: Boris Safonov Date: Tue, 28 May 2024 17:08:46 +0300 Subject: [PATCH 3/6] Added test --- .../devices/DeviceDetailsViewModelTest.kt | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/app/src/test/kotlin/com/wire/android/ui/settings/devices/DeviceDetailsViewModelTest.kt b/app/src/test/kotlin/com/wire/android/ui/settings/devices/DeviceDetailsViewModelTest.kt index 38b7d5ceaf6..dce6a17b673 100644 --- a/app/src/test/kotlin/com/wire/android/ui/settings/devices/DeviceDetailsViewModelTest.kt +++ b/app/src/test/kotlin/com/wire/android/ui/settings/devices/DeviceDetailsViewModelTest.kt @@ -37,12 +37,15 @@ import com.wire.kalium.logic.feature.client.GetClientDetailsResult import com.wire.kalium.logic.feature.client.ObserveClientDetailsUseCase import com.wire.kalium.logic.feature.client.Result import com.wire.kalium.logic.feature.client.UpdateClientVerificationStatusUseCase +import com.wire.kalium.logic.feature.e2ei.CertificateStatus +import com.wire.kalium.logic.feature.e2ei.E2eiCertificate import com.wire.kalium.logic.feature.e2ei.usecase.GetE2EICertificateUseCaseResult import com.wire.kalium.logic.feature.e2ei.usecase.GetE2eiCertificateUseCase import com.wire.kalium.logic.feature.user.GetUserInfoResult import com.wire.kalium.logic.feature.user.IsE2EIEnabledUseCase import com.wire.kalium.logic.feature.user.IsPasswordRequiredUseCase import com.wire.kalium.logic.feature.user.ObserveUserInfoUseCase +import com.wire.kalium.util.DateTimeUtil import io.mockk.Called import io.mockk.MockKAnnotations import io.mockk.coEvery @@ -60,6 +63,7 @@ import org.junit.jupiter.api.Assertions.assertFalse import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith +import kotlin.time.Duration.Companion.days @OptIn(ExperimentalCoroutinesApi::class) @ExtendWith(CoroutineTestExtension::class) @@ -281,6 +285,30 @@ class DeviceDetailsViewModelTest { assertTrue(viewModel.state.startGettingE2EICertificate) } + + @Test + fun `given a client with E2EI certificate, when fetching details, then returns device information`() { + val certificate = E2eiCertificate( + userHandle = "userHandle", + serialNumber = "serialNumber", + certificateDetail = "certificateDetail", + status = CertificateStatus.VALID, + thumbprint = "thumbprint", + endAt = DateTimeUtil.currentInstant().plus(1.days) + ) + runTest { + // given + val (_, viewModel) = Arrangement() + .withRequiredMockSetup() + .withClientDetailsResult(GetClientDetailsResult.Success(TestClient.CLIENT, true)) + .withE2eiCertificate(GetE2EICertificateUseCaseResult.Success(certificate)) + .arrange() + + // then + assertEquals(certificate, viewModel.state.device.e2eiCertificate) + } + } + private class Arrangement { @MockK @@ -370,6 +398,10 @@ class DeviceDetailsViewModelTest { ) } + fun withE2eiCertificate(result: GetE2EICertificateUseCaseResult) = apply { + coEvery { getE2eiCertificate(any()) } returns result + } + fun arrange() = this to viewModel companion object { From 8d075fb144719721d48d4d1d1bb18e8301e3aafe Mon Sep 17 00:00:00 2001 From: Boris Safonov Date: Wed, 29 May 2024 11:03:52 +0300 Subject: [PATCH 4/6] Fixed codestyle --- .../android/ui/settings/devices/SelfDevicesViewModelTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/test/kotlin/com/wire/android/ui/settings/devices/SelfDevicesViewModelTest.kt b/app/src/test/kotlin/com/wire/android/ui/settings/devices/SelfDevicesViewModelTest.kt index bb88aabdc6a..295d6c05eca 100644 --- a/app/src/test/kotlin/com/wire/android/ui/settings/devices/SelfDevicesViewModelTest.kt +++ b/app/src/test/kotlin/com/wire/android/ui/settings/devices/SelfDevicesViewModelTest.kt @@ -30,8 +30,8 @@ import com.wire.kalium.logic.feature.client.ObserveCurrentClientIdUseCase import com.wire.kalium.logic.feature.client.SelfClientsResult import com.wire.kalium.logic.feature.e2ei.usecase.GetUserE2eiCertificatesUseCase import com.wire.kalium.logic.feature.user.IsE2EIEnabledUseCase -import io.mockk.coEvery import io.mockk.MockKAnnotations +import io.mockk.coEvery import io.mockk.impl.annotations.MockK import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.flowOf From 497a8b9d01957fdef36a4761d11c5feac92970e0 Mon Sep 17 00:00:00 2001 From: Boris Safonov Date: Wed, 29 May 2024 11:23:20 +0300 Subject: [PATCH 5/6] Fixed style again --- .../android/ui/settings/devices/DeviceDetailsViewModelTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/test/kotlin/com/wire/android/ui/settings/devices/DeviceDetailsViewModelTest.kt b/app/src/test/kotlin/com/wire/android/ui/settings/devices/DeviceDetailsViewModelTest.kt index dce6a17b673..652a9d5962c 100644 --- a/app/src/test/kotlin/com/wire/android/ui/settings/devices/DeviceDetailsViewModelTest.kt +++ b/app/src/test/kotlin/com/wire/android/ui/settings/devices/DeviceDetailsViewModelTest.kt @@ -285,7 +285,6 @@ class DeviceDetailsViewModelTest { assertTrue(viewModel.state.startGettingE2EICertificate) } - @Test fun `given a client with E2EI certificate, when fetching details, then returns device information`() { val certificate = E2eiCertificate( From 601c95e2b60547ddd569ad39f6d6d7cfa949041d Mon Sep 17 00:00:00 2001 From: Boris Safonov Date: Tue, 4 Jun 2024 16:21:37 +0300 Subject: [PATCH 6/6] Commit just to trigger re-build PR --- .../com/wire/android/ui/settings/devices/DeviceDetailsScreen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/settings/devices/DeviceDetailsScreen.kt b/app/src/main/kotlin/com/wire/android/ui/settings/devices/DeviceDetailsScreen.kt index 9a65836a5eb..db997257640 100644 --- a/app/src/main/kotlin/com/wire/android/ui/settings/devices/DeviceDetailsScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/settings/devices/DeviceDetailsScreen.kt @@ -577,7 +577,7 @@ fun PreviewDeviceDetailsScreen() { "handler", CertificateStatus.VALID, "serial", - "date", + "Details", "Thumbprint", Instant.DISTANT_FUTURE )