From a5ee4faef4867c54d26d8ba136ae9f084f7b087c Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Thu, 1 Sep 2022 09:25:11 +0200 Subject: [PATCH] Introducing some reusable usecases --- .../devices/CurrentSessionCrossSigningInfo.kt | 26 ++++++++++ .../settings/devices/DevicesViewModel.kt | 28 +++-------- ...etCurrentSessionCrossSigningInfoUseCase.kt | 37 ++++++++++++++ ...yptionTrustLevelForCurrentDeviceUseCase.kt | 38 ++++++++++++++ ...GetEncryptionTrustLevelForDeviceUseCase.kt | 40 +++++++++++++++ ...cryptionTrustLevelForOtherDeviceUseCase.kt | 49 +++++++++++++++++++ .../features/settings/devices/TrustUtils.kt | 1 + .../v2/overview/GetDeviceFullInfoUseCase.kt | 10 +++- 8 files changed, 206 insertions(+), 23 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/CurrentSessionCrossSigningInfo.kt create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/GetCurrentSessionCrossSigningInfoUseCase.kt create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/GetEncryptionTrustLevelForCurrentDeviceUseCase.kt create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/GetEncryptionTrustLevelForDeviceUseCase.kt create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/GetEncryptionTrustLevelForOtherDeviceUseCase.kt diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/CurrentSessionCrossSigningInfo.kt b/vector/src/main/java/im/vector/app/features/settings/devices/CurrentSessionCrossSigningInfo.kt new file mode 100644 index 0000000000..790de08823 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/CurrentSessionCrossSigningInfo.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.settings.devices + +/** + * Used to hold some info about the cross signing of the current Session. + */ +data class CurrentSessionCrossSigningInfo( + val deviceId: String?, + val isCrossSigningInitialized: Boolean, + val isCrossSigningVerified: Boolean, +) diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt index 3b5bcb61d9..82c346b09c 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt @@ -101,6 +101,8 @@ class DevicesViewModel @AssistedInject constructor( private val stringProvider: StringProvider, private val matrix: Matrix, private val checkIfSessionIsInactiveUseCase: CheckIfSessionIsInactiveUseCase, + getCurrentSessionCrossSigningInfoUseCase: GetCurrentSessionCrossSigningInfoUseCase, + private val getEncryptionTrustLevelForDeviceUseCase: GetEncryptionTrustLevelForDeviceUseCase, ) : VectorViewModel(initialState), VerificationService.Listener { var uiaContinuation: Continuation? = null @@ -116,8 +118,9 @@ class DevicesViewModel @AssistedInject constructor( private val refreshSource = PublishDataSource() init { - val hasAccountCrossSigning = session.cryptoService().crossSigningService().isCrossSigningInitialized() - val accountCrossSigningIsTrusted = session.cryptoService().crossSigningService().isCrossSigningVerified() + val currentSessionCrossSigningInfo = getCurrentSessionCrossSigningInfoUseCase.execute() + val hasAccountCrossSigning = currentSessionCrossSigningInfo.isCrossSigningInitialized + val accountCrossSigningIsTrusted = currentSessionCrossSigningInfo.isCrossSigningVerified setState { copy( @@ -143,12 +146,7 @@ class DevicesViewModel @AssistedInject constructor( .sortedByDescending { it.lastSeenTs } .map { deviceInfo -> val cryptoDeviceInfo = cryptoList.firstOrNull { it.deviceId == deviceInfo.deviceId } - val trustLevelForShield = computeTrustLevelForShield( - currentSessionCrossTrusted = accountCrossSigningIsTrusted, - legacyMode = !hasAccountCrossSigning, - deviceTrustLevel = cryptoDeviceInfo?.trustLevel, - isCurrentDevice = deviceInfo.deviceId == session.sessionParams.deviceId - ) + val trustLevelForShield = getEncryptionTrustLevelForDeviceUseCase.execute(currentSessionCrossSigningInfo, cryptoDeviceInfo) val isInactive = checkIfSessionIsInactiveUseCase.execute(deviceInfo.lastSeenTs ?: 0) DeviceFullInfo(deviceInfo, cryptoDeviceInfo, trustLevelForShield, isInactive) } @@ -268,20 +266,6 @@ class DevicesViewModel @AssistedInject constructor( } } - private fun computeTrustLevelForShield( - currentSessionCrossTrusted: Boolean, - legacyMode: Boolean, - deviceTrustLevel: DeviceTrustLevel?, - isCurrentDevice: Boolean, - ): RoomEncryptionTrustLevel { - return TrustUtils.shieldForTrust( - currentDevice = isCurrentDevice, - trustMSK = currentSessionCrossTrusted, - legacyMode = legacyMode, - deviceTrustLevel = deviceTrustLevel - ) - } - private fun handleInteractiveVerification(action: DevicesAction.VerifyMyDevice) { val txID = session.cryptoService() .verificationService() diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/GetCurrentSessionCrossSigningInfoUseCase.kt b/vector/src/main/java/im/vector/app/features/settings/devices/GetCurrentSessionCrossSigningInfoUseCase.kt new file mode 100644 index 0000000000..aa0de9ddf1 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/GetCurrentSessionCrossSigningInfoUseCase.kt @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.settings.devices + +import im.vector.app.core.di.ActiveSessionHolder +import javax.inject.Inject + +// TODO add unit tests +class GetCurrentSessionCrossSigningInfoUseCase @Inject constructor( + private val activeSessionHolder: ActiveSessionHolder, +) { + + fun execute(): CurrentSessionCrossSigningInfo { + val session = activeSessionHolder.getActiveSession() + val isCrossSigningInitialized = session.cryptoService().crossSigningService().isCrossSigningInitialized() + val isCrossSigningVerified = session.cryptoService().crossSigningService().isCrossSigningVerified() + return CurrentSessionCrossSigningInfo( + deviceId = session.sessionParams.deviceId, + isCrossSigningInitialized = isCrossSigningInitialized, + isCrossSigningVerified = isCrossSigningVerified + ) + } +} diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/GetEncryptionTrustLevelForCurrentDeviceUseCase.kt b/vector/src/main/java/im/vector/app/features/settings/devices/GetEncryptionTrustLevelForCurrentDeviceUseCase.kt new file mode 100644 index 0000000000..eaa72b424a --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/GetEncryptionTrustLevelForCurrentDeviceUseCase.kt @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.settings.devices + +import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel +import javax.inject.Inject + +// TODO add unit tests +class GetEncryptionTrustLevelForCurrentDeviceUseCase @Inject constructor() { + + fun execute(trustMSK: Boolean, legacyMode: Boolean): RoomEncryptionTrustLevel { + return if (legacyMode) { + // In legacy, current session is always trusted + RoomEncryptionTrustLevel.Trusted + } else { + // If current session doesn't trust MSK, show red shield for current device + if (trustMSK) { + RoomEncryptionTrustLevel.Trusted + } else { + RoomEncryptionTrustLevel.Warning + } + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/GetEncryptionTrustLevelForDeviceUseCase.kt b/vector/src/main/java/im/vector/app/features/settings/devices/GetEncryptionTrustLevelForDeviceUseCase.kt new file mode 100644 index 0000000000..d988f728ae --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/GetEncryptionTrustLevelForDeviceUseCase.kt @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.settings.devices + +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel +import javax.inject.Inject + +// TODO add unit tests +class GetEncryptionTrustLevelForDeviceUseCase @Inject constructor( + private val getEncryptionTrustLevelForCurrentDeviceUseCase: GetEncryptionTrustLevelForCurrentDeviceUseCase, + private val getEncryptionTrustLevelForOtherDeviceUseCase: GetEncryptionTrustLevelForOtherDeviceUseCase, +) { + + fun execute(currentSessionCrossSigningInfo: CurrentSessionCrossSigningInfo, cryptoDeviceInfo: CryptoDeviceInfo?): RoomEncryptionTrustLevel { + val legacyMode = !currentSessionCrossSigningInfo.isCrossSigningInitialized + val trustMSK = currentSessionCrossSigningInfo.isCrossSigningVerified + val isCurrentDevice = !cryptoDeviceInfo?.deviceId.isNullOrEmpty() && cryptoDeviceInfo?.deviceId == currentSessionCrossSigningInfo.deviceId + val deviceTrustLevel = cryptoDeviceInfo?.trustLevel + + return when { + isCurrentDevice -> getEncryptionTrustLevelForCurrentDeviceUseCase.execute(trustMSK, legacyMode) + else -> getEncryptionTrustLevelForOtherDeviceUseCase.execute(trustMSK, legacyMode, deviceTrustLevel) + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/GetEncryptionTrustLevelForOtherDeviceUseCase.kt b/vector/src/main/java/im/vector/app/features/settings/devices/GetEncryptionTrustLevelForOtherDeviceUseCase.kt new file mode 100644 index 0000000000..41cdae23a4 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/GetEncryptionTrustLevelForOtherDeviceUseCase.kt @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.settings.devices + +import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel +import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel +import javax.inject.Inject + +// TODO add unit tests +class GetEncryptionTrustLevelForOtherDeviceUseCase @Inject constructor() { + + fun execute(trustMSK: Boolean, legacyMode: Boolean, deviceTrustLevel: DeviceTrustLevel?): RoomEncryptionTrustLevel { + return if (legacyMode) { + // use local trust + if (deviceTrustLevel?.locallyVerified == true) { + RoomEncryptionTrustLevel.Trusted + } else { + RoomEncryptionTrustLevel.Warning + } + } else { + if (trustMSK) { + // use cross sign trust, put locally trusted in black + when { + deviceTrustLevel?.crossSigningVerified == true -> RoomEncryptionTrustLevel.Trusted + deviceTrustLevel?.locallyVerified == true -> RoomEncryptionTrustLevel.Default + else -> RoomEncryptionTrustLevel.Warning + } + } else { + // The current session is untrusted, so displays others in black + // as we can't know the cross-signing state + RoomEncryptionTrustLevel.Default + } + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/TrustUtils.kt b/vector/src/main/java/im/vector/app/features/settings/devices/TrustUtils.kt index da18154ea1..7709a63344 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/TrustUtils.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/TrustUtils.kt @@ -19,6 +19,7 @@ package im.vector.app.features.settings.devices import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel +// TODO Replace usage by the use case GetEncryptionTrustLevelForDeviceUseCase object TrustUtils { fun shieldForTrust( diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/GetDeviceFullInfoUseCase.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/GetDeviceFullInfoUseCase.kt index d20ca17471..51252de34a 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/GetDeviceFullInfoUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/GetDeviceFullInfoUseCase.kt @@ -19,6 +19,8 @@ package im.vector.app.features.settings.devices.v2.overview import androidx.lifecycle.asFlow import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.features.settings.devices.DeviceFullInfo +import im.vector.app.features.settings.devices.GetCurrentSessionCrossSigningInfoUseCase +import im.vector.app.features.settings.devices.GetEncryptionTrustLevelForDeviceUseCase import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.emptyFlow @@ -26,12 +28,16 @@ import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.toOptional import javax.inject.Inject +// TODO update unit test class GetDeviceFullInfoUseCase @Inject constructor( private val activeSessionHolder: ActiveSessionHolder, + private val getCurrentSessionCrossSigningInfoUseCase: GetCurrentSessionCrossSigningInfoUseCase, + private val getEncryptionTrustLevelForDeviceUseCase: GetEncryptionTrustLevelForDeviceUseCase, ) { fun execute(deviceId: String): Flow> { return activeSessionHolder.getSafeActiveSession()?.let { session -> + val currentSessionCrossSigningInfo = getCurrentSessionCrossSigningInfoUseCase.execute() combine( session.cryptoService().getMyDevicesInfoLive(deviceId).asFlow(), session.cryptoService().getLiveCryptoDeviceInfoWithId(deviceId).asFlow() @@ -39,9 +45,11 @@ class GetDeviceFullInfoUseCase @Inject constructor( val info = deviceInfo.getOrNull() val cryptoInfo = cryptoDeviceInfo.getOrNull() val fullInfo = if (info != null && cryptoInfo != null) { + val roomEncryptionTrustLevel = getEncryptionTrustLevelForDeviceUseCase.execute(currentSessionCrossSigningInfo, cryptoInfo) DeviceFullInfo( deviceInfo = info, - cryptoDeviceInfo = cryptoInfo + cryptoDeviceInfo = cryptoInfo, + trustLevelForShield = roomEncryptionTrustLevel ) } else { null