Introducing some reusable usecases
This commit is contained in:
parent
b995f798f9
commit
a5ee4faef4
|
@ -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,
|
||||||
|
)
|
|
@ -101,6 +101,8 @@ class DevicesViewModel @AssistedInject constructor(
|
||||||
private val stringProvider: StringProvider,
|
private val stringProvider: StringProvider,
|
||||||
private val matrix: Matrix,
|
private val matrix: Matrix,
|
||||||
private val checkIfSessionIsInactiveUseCase: CheckIfSessionIsInactiveUseCase,
|
private val checkIfSessionIsInactiveUseCase: CheckIfSessionIsInactiveUseCase,
|
||||||
|
getCurrentSessionCrossSigningInfoUseCase: GetCurrentSessionCrossSigningInfoUseCase,
|
||||||
|
private val getEncryptionTrustLevelForDeviceUseCase: GetEncryptionTrustLevelForDeviceUseCase,
|
||||||
) : VectorViewModel<DevicesViewState, DevicesAction, DevicesViewEvents>(initialState), VerificationService.Listener {
|
) : VectorViewModel<DevicesViewState, DevicesAction, DevicesViewEvents>(initialState), VerificationService.Listener {
|
||||||
|
|
||||||
var uiaContinuation: Continuation<UIABaseAuth>? = null
|
var uiaContinuation: Continuation<UIABaseAuth>? = null
|
||||||
|
@ -116,8 +118,9 @@ class DevicesViewModel @AssistedInject constructor(
|
||||||
private val refreshSource = PublishDataSource<Unit>()
|
private val refreshSource = PublishDataSource<Unit>()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val hasAccountCrossSigning = session.cryptoService().crossSigningService().isCrossSigningInitialized()
|
val currentSessionCrossSigningInfo = getCurrentSessionCrossSigningInfoUseCase.execute()
|
||||||
val accountCrossSigningIsTrusted = session.cryptoService().crossSigningService().isCrossSigningVerified()
|
val hasAccountCrossSigning = currentSessionCrossSigningInfo.isCrossSigningInitialized
|
||||||
|
val accountCrossSigningIsTrusted = currentSessionCrossSigningInfo.isCrossSigningVerified
|
||||||
|
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
|
@ -143,12 +146,7 @@ class DevicesViewModel @AssistedInject constructor(
|
||||||
.sortedByDescending { it.lastSeenTs }
|
.sortedByDescending { it.lastSeenTs }
|
||||||
.map { deviceInfo ->
|
.map { deviceInfo ->
|
||||||
val cryptoDeviceInfo = cryptoList.firstOrNull { it.deviceId == deviceInfo.deviceId }
|
val cryptoDeviceInfo = cryptoList.firstOrNull { it.deviceId == deviceInfo.deviceId }
|
||||||
val trustLevelForShield = computeTrustLevelForShield(
|
val trustLevelForShield = getEncryptionTrustLevelForDeviceUseCase.execute(currentSessionCrossSigningInfo, cryptoDeviceInfo)
|
||||||
currentSessionCrossTrusted = accountCrossSigningIsTrusted,
|
|
||||||
legacyMode = !hasAccountCrossSigning,
|
|
||||||
deviceTrustLevel = cryptoDeviceInfo?.trustLevel,
|
|
||||||
isCurrentDevice = deviceInfo.deviceId == session.sessionParams.deviceId
|
|
||||||
)
|
|
||||||
val isInactive = checkIfSessionIsInactiveUseCase.execute(deviceInfo.lastSeenTs ?: 0)
|
val isInactive = checkIfSessionIsInactiveUseCase.execute(deviceInfo.lastSeenTs ?: 0)
|
||||||
DeviceFullInfo(deviceInfo, cryptoDeviceInfo, trustLevelForShield, isInactive)
|
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) {
|
private fun handleInteractiveVerification(action: DevicesAction.VerifyMyDevice) {
|
||||||
val txID = session.cryptoService()
|
val txID = session.cryptoService()
|
||||||
.verificationService()
|
.verificationService()
|
||||||
|
|
|
@ -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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.crosssigning.DeviceTrustLevel
|
||||||
import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
|
import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
|
||||||
|
|
||||||
|
// TODO Replace usage by the use case GetEncryptionTrustLevelForDeviceUseCase
|
||||||
object TrustUtils {
|
object TrustUtils {
|
||||||
|
|
||||||
fun shieldForTrust(
|
fun shieldForTrust(
|
||||||
|
|
|
@ -19,6 +19,8 @@ package im.vector.app.features.settings.devices.v2.overview
|
||||||
import androidx.lifecycle.asFlow
|
import androidx.lifecycle.asFlow
|
||||||
import im.vector.app.core.di.ActiveSessionHolder
|
import im.vector.app.core.di.ActiveSessionHolder
|
||||||
import im.vector.app.features.settings.devices.DeviceFullInfo
|
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.Flow
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.emptyFlow
|
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 org.matrix.android.sdk.api.util.toOptional
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
// TODO update unit test
|
||||||
class GetDeviceFullInfoUseCase @Inject constructor(
|
class GetDeviceFullInfoUseCase @Inject constructor(
|
||||||
private val activeSessionHolder: ActiveSessionHolder,
|
private val activeSessionHolder: ActiveSessionHolder,
|
||||||
|
private val getCurrentSessionCrossSigningInfoUseCase: GetCurrentSessionCrossSigningInfoUseCase,
|
||||||
|
private val getEncryptionTrustLevelForDeviceUseCase: GetEncryptionTrustLevelForDeviceUseCase,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun execute(deviceId: String): Flow<Optional<DeviceFullInfo>> {
|
fun execute(deviceId: String): Flow<Optional<DeviceFullInfo>> {
|
||||||
return activeSessionHolder.getSafeActiveSession()?.let { session ->
|
return activeSessionHolder.getSafeActiveSession()?.let { session ->
|
||||||
|
val currentSessionCrossSigningInfo = getCurrentSessionCrossSigningInfoUseCase.execute()
|
||||||
combine(
|
combine(
|
||||||
session.cryptoService().getMyDevicesInfoLive(deviceId).asFlow(),
|
session.cryptoService().getMyDevicesInfoLive(deviceId).asFlow(),
|
||||||
session.cryptoService().getLiveCryptoDeviceInfoWithId(deviceId).asFlow()
|
session.cryptoService().getLiveCryptoDeviceInfoWithId(deviceId).asFlow()
|
||||||
|
@ -39,9 +45,11 @@ class GetDeviceFullInfoUseCase @Inject constructor(
|
||||||
val info = deviceInfo.getOrNull()
|
val info = deviceInfo.getOrNull()
|
||||||
val cryptoInfo = cryptoDeviceInfo.getOrNull()
|
val cryptoInfo = cryptoDeviceInfo.getOrNull()
|
||||||
val fullInfo = if (info != null && cryptoInfo != null) {
|
val fullInfo = if (info != null && cryptoInfo != null) {
|
||||||
|
val roomEncryptionTrustLevel = getEncryptionTrustLevelForDeviceUseCase.execute(currentSessionCrossSigningInfo, cryptoInfo)
|
||||||
DeviceFullInfo(
|
DeviceFullInfo(
|
||||||
deviceInfo = info,
|
deviceInfo = info,
|
||||||
cryptoDeviceInfo = cryptoInfo
|
cryptoDeviceInfo = cryptoInfo,
|
||||||
|
trustLevelForShield = roomEncryptionTrustLevel
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
|
|
Loading…
Reference in New Issue