Suspend API: handle verification service

This commit is contained in:
ganfra 2022-03-29 17:51:05 +02:00
parent e121007d20
commit 0590258d54
9 changed files with 214 additions and 189 deletions

View File

@ -36,7 +36,7 @@ interface VerificationService {
/**
* Mark this device as verified manually
*/
fun markedLocallyAsManuallyVerified(userId: String, deviceID: String)
suspend fun markedLocallyAsManuallyVerified(userId: String, deviceID: String)
fun getExistingTransaction(otherUserId: String, tid: String): VerificationTransaction?
@ -46,7 +46,7 @@ interface VerificationService {
fun getExistingVerificationRequestInRoom(roomId: String, tid: String?): PendingVerificationRequest?
fun beginKeyVerification(method: VerificationMethod,
suspend fun beginKeyVerification(method: VerificationMethod,
otherUserId: String,
otherDeviceId: String,
transactionId: String?): String?
@ -54,27 +54,27 @@ interface VerificationService {
/**
* Request key verification with another user via room events (instead of the to-device API)
*/
fun requestKeyVerificationInDMs(methods: List<VerificationMethod>,
suspend fun requestKeyVerificationInDMs(methods: List<VerificationMethod>,
otherUserId: String,
roomId: String,
localId: String? = LocalEcho.createLocalEchoId()): PendingVerificationRequest
fun cancelVerificationRequest(request: PendingVerificationRequest)
suspend fun cancelVerificationRequest(request: PendingVerificationRequest)
/**
* Request a key verification from another user using toDevice events.
*/
fun requestKeyVerification(methods: List<VerificationMethod>,
suspend fun requestKeyVerification(methods: List<VerificationMethod>,
otherUserId: String,
otherDevices: List<String>?): PendingVerificationRequest
fun declineVerificationRequestInDMs(otherUserId: String,
suspend fun declineVerificationRequestInDMs(otherUserId: String,
transactionId: String,
roomId: String)
// Only SAS method is supported for the moment
// TODO Parameter otherDeviceId should be removed in this case
fun beginKeyVerificationInDMs(method: VerificationMethod,
suspend fun beginKeyVerificationInDMs(method: VerificationMethod,
transactionId: String,
roomId: String,
otherUserId: String,
@ -83,7 +83,7 @@ interface VerificationService {
/**
* Returns false if the request is unknown
*/
fun readyPendingVerificationInDMs(methods: List<VerificationMethod>,
suspend fun readyPendingVerificationInDMs(methods: List<VerificationMethod>,
otherUserId: String,
roomId: String,
transactionId: String): Boolean
@ -91,7 +91,7 @@ interface VerificationService {
/**
* Returns false if the request is unknown
*/
fun readyPendingVerification(methods: List<VerificationMethod>,
suspend fun readyPendingVerification(methods: List<VerificationMethod>,
otherUserId: String,
transactionId: String): Boolean

View File

@ -18,7 +18,6 @@ package org.matrix.android.sdk.internal.crypto.verification
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import kotlinx.coroutines.runBlocking
import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificationRequest
import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
@ -162,12 +161,10 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
this.dispatcher.removeListener(listener)
}
override fun markedLocallyAsManuallyVerified(userId: String, deviceID: String) {
override suspend fun markedLocallyAsManuallyVerified(userId: String, deviceID: String) {
// TODO this doesn't seem to be used anymore?
runBlocking {
val device = olmMachine.getDevice(userId, deviceID)
device?.markAsTrusted()
}
val device = olmMachine.getDevice(userId, deviceID)
device?.markAsTrusted()
}
override fun onPotentiallyInterestingEventRoomFailToDecrypt(event: Event) {
@ -224,13 +221,13 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
return null
}
override fun requestKeyVerification(
override suspend fun requestKeyVerification(
methods: List<VerificationMethod>,
otherUserId: String,
otherDevices: List<String>?
): PendingVerificationRequest {
val verification = when (val identity = runBlocking { olmMachine.getIdentity(otherUserId) }) {
is OwnUserIdentity -> runBlocking { identity.requestVerification(methods) }
val verification = when (val identity = olmMachine.getIdentity(otherUserId)) {
is OwnUserIdentity -> identity.requestVerification(methods)
is UserIdentity -> throw IllegalArgumentException("This method doesn't support verification of other users devices")
null -> throw IllegalArgumentException("Cross signing has not been bootstrapped for our own user")
}
@ -238,15 +235,15 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
return verification.toPendingVerificationRequest()
}
override fun requestKeyVerificationInDMs(
override suspend fun requestKeyVerificationInDMs(
methods: List<VerificationMethod>,
otherUserId: String,
roomId: String,
localId: String?
): PendingVerificationRequest {
Timber.i("## SAS Requesting verification to user: $otherUserId in room $roomId")
val verification = when (val identity = runBlocking { olmMachine.getIdentity(otherUserId) }) {
is UserIdentity -> runBlocking { identity.requestVerification(methods, roomId, localId!!) }
val verification = when (val identity = olmMachine.getIdentity(otherUserId)) {
is UserIdentity -> identity.requestVerification(methods, roomId, localId!!)
is OwnUserIdentity -> throw IllegalArgumentException("This method doesn't support verification of our own user")
null -> throw IllegalArgumentException("The user that we wish to verify doesn't support cross signing")
}
@ -254,7 +251,7 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
return verification.toPendingVerificationRequest()
}
override fun readyPendingVerification(
override suspend fun readyPendingVerification(
methods: List<VerificationMethod>,
otherUserId: String,
transactionId: String
@ -262,7 +259,7 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
val request = this.olmMachine.getVerificationRequest(otherUserId, transactionId)
return if (request != null) {
runBlocking { request.acceptWithMethods(methods) }
request.acceptWithMethods(methods)
if (request.isReady()) {
val qrcode = request.startQrVerification()
@ -280,7 +277,7 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
}
}
override fun readyPendingVerificationInDMs(
override suspend fun readyPendingVerificationInDMs(
methods: List<VerificationMethod>,
otherUserId: String,
roomId: String,
@ -289,7 +286,7 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
return readyPendingVerification(methods, otherUserId, transactionId)
}
override fun beginKeyVerification(
override suspend fun beginKeyVerification(
method: VerificationMethod,
otherUserId: String,
otherDeviceId: String,
@ -299,15 +296,13 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
if (transactionId != null) {
val request = this.olmMachine.getVerificationRequest(otherUserId, transactionId)
runBlocking {
val sas = request?.startSasVerification()
val sas = request?.startSasVerification()
if (sas != null) {
dispatcher.dispatchTxAdded(sas)
sas.transactionId
} else {
null
}
if (sas != null) {
dispatcher.dispatchTxAdded(sas)
sas.transactionId
} else {
null
}
} else {
// This starts the short SAS flow, the one that doesn't start with
@ -315,14 +310,12 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
// be wise do do so as well
// DeviceListBottomSheetViewModel triggers this, interestingly the method that
// triggers this is called `manuallyVerify()`
runBlocking {
val verification = olmMachine.getDevice(otherUserId, otherDeviceId)?.startVerification()
if (verification != null) {
dispatcher.dispatchTxAdded(verification)
verification.transactionId
} else {
null
}
val verification = olmMachine.getDevice(otherUserId, otherDeviceId)?.startVerification()
if (verification != null) {
dispatcher.dispatchTxAdded(verification)
verification.transactionId
} else {
null
}
}
} else {
@ -330,7 +323,7 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
}
}
override fun beginKeyVerificationInDMs(
override suspend fun beginKeyVerificationInDMs(
method: VerificationMethod,
transactionId: String,
roomId: String,
@ -343,19 +336,19 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
return transactionId
}
override fun cancelVerificationRequest(request: PendingVerificationRequest) {
override suspend fun cancelVerificationRequest(request: PendingVerificationRequest) {
val verificationRequest = request.transactionId?.let {
this.olmMachine.getVerificationRequest(request.otherUserId, it)
}
runBlocking { verificationRequest?.cancel() }
verificationRequest?.cancel()
}
override fun declineVerificationRequestInDMs(
override suspend fun declineVerificationRequestInDMs(
otherUserId: String,
transactionId: String,
roomId: String
) {
val verificationRequest = this.olmMachine.getVerificationRequest(otherUserId, transactionId)
runBlocking { verificationRequest?.cancel() }
verificationRequest?.cancel()
}
}

View File

@ -149,10 +149,12 @@ class SharedSecureStorageViewModel @AssistedInject constructor(
// as we are going to reset, we'd better cancel all outgoing requests
// if not they could be accepted in the middle of the reset process
// and cause strange use cases
session.cryptoService().verificationService().getExistingVerificationRequests(session.myUserId).forEach {
session.cryptoService().verificationService().cancelVerificationRequest(it)
viewModelScope.launch {
session.cryptoService().verificationService().getExistingVerificationRequests(session.myUserId).forEach {
session.cryptoService().verificationService().cancelVerificationRequest(it)
}
_viewEvents.post(SharedSecureStorageViewEvent.ShowResetBottomSheet)
}
_viewEvents.post(SharedSecureStorageViewEvent.ShowResetBottomSheet)
}
private fun handleResetAll() {

View File

@ -24,6 +24,8 @@ import im.vector.app.features.home.room.detail.RoomDetailActivity
import im.vector.app.features.home.room.detail.arguments.TimelineArgs
import im.vector.app.features.popup.PopupAlertManager
import im.vector.app.features.popup.VerificationVectorAlert
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificationRequest
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
@ -42,7 +44,8 @@ import javax.inject.Singleton
class IncomingVerificationRequestHandler @Inject constructor(
private val context: Context,
private var avatarRenderer: Provider<AvatarRenderer>,
private val popupAlertManager: PopupAlertManager) : VerificationService.Listener {
private val popupAlertManager: PopupAlertManager,
private val coroutineScope: CoroutineScope) : VerificationService.Listener {
private var session: Session? = null
@ -61,7 +64,7 @@ class IncomingVerificationRequestHandler @Inject constructor(
// TODO maybe check also if
val uid = "kvr_${tx.transactionId}"
when (tx.state) {
is VerificationTxState.OnStarted -> {
is VerificationTxState.OnStarted -> {
// Add a notification for every incoming request
val user = session?.getUser(tx.otherUserId)
val name = user?.toMatrixItem()?.getBestName() ?: tx.otherUserId
@ -161,10 +164,12 @@ class IncomingVerificationRequestHandler @Inject constructor(
}
}
dismissedAction = Runnable {
session?.cryptoService()?.verificationService()?.declineVerificationRequestInDMs(pr.otherUserId,
pr.transactionId ?: "",
pr.roomId ?: ""
)
coroutineScope.launch {
session?.cryptoService()?.verificationService()?.declineVerificationRequestInDMs(pr.otherUserId,
pr.transactionId ?: "",
pr.roomId ?: ""
)
}
}
colorAttribute = R.attr.vctr_notice_secondary
// 5mn expiration

View File

@ -152,13 +152,15 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
}
if (autoReady) {
// TODO, can I be here in DM mode? in this case should test if roomID is null?
session.cryptoService().verificationService()
.readyPendingVerification(
supportedVerificationMethodsProvider.provide(),
pr!!.otherUserId,
pr.transactionId ?: ""
)
viewModelScope.launch {
// TODO, can I be here in DM mode? in this case should test if roomID is null?
session.cryptoService().verificationService()
.readyPendingVerification(
supportedVerificationMethodsProvider.provide(),
pr!!.otherUserId,
pr.transactionId ?: ""
)
}
}
}
@ -192,14 +194,16 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
}
private fun cancelAllPendingVerifications(state: VerificationBottomSheetViewState) {
session.cryptoService()
.verificationService().getExistingVerificationRequest(state.otherUserMxItem?.id ?: "", state.transactionId)?.let {
session.cryptoService().verificationService().cancelVerificationRequest(it)
}
session.cryptoService()
.verificationService()
.getExistingTransaction(state.otherUserMxItem?.id ?: "", state.transactionId ?: "")
?.cancel(CancelCode.User)
viewModelScope.launch {
session.cryptoService()
.verificationService().getExistingVerificationRequest(state.otherUserMxItem?.id ?: "", state.transactionId)?.let {
session.cryptoService().verificationService().cancelVerificationRequest(it)
}
session.cryptoService()
.verificationService()
.getExistingTransaction(state.otherUserMxItem?.id ?: "", state.transactionId ?: "")
?.cancel(CancelCode.User)
}
}
fun continueFromCancel() {
@ -232,74 +236,29 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
when (action) {
is VerificationAction.RequestVerificationByDM -> {
if (roomId == null) {
val localId = LocalEcho.createLocalEchoId()
setState {
copy(
pendingLocalId = localId,
pendingRequest = Loading()
)
}
viewModelScope.launch {
val result = runCatching { session.createDirectRoom(otherUserId) }
result.fold(
{ data ->
setState {
copy(
roomId = data,
pendingRequest = Success(
session
.cryptoService()
.verificationService()
.requestKeyVerificationInDMs(
supportedVerificationMethodsProvider.provide(),
otherUserId,
data,
pendingLocalId
)
)
)
}
},
{ failure ->
setState {
copy(pendingRequest = Fail(failure))
}
}
)
}
} else {
setState {
copy(
pendingRequest = Success(session
.cryptoService()
.verificationService()
.requestKeyVerificationInDMs(supportedVerificationMethodsProvider.provide(), otherUserId, roomId)
)
)
}
}
Unit
handleRequestVerificationByDM(roomId, otherUserId)
}
is VerificationAction.StartSASVerification -> {
val request = session.cryptoService().verificationService().getExistingVerificationRequest(otherUserId, action.pendingRequestTransactionId)
?: return@withState
val otherDevice = if (request.isIncoming) request.requestInfo?.fromDevice else request.readyInfo?.fromDevice
if (roomId == null) {
session.cryptoService().verificationService().beginKeyVerification(
VerificationMethod.SAS,
otherUserId = request.otherUserId,
otherDeviceId = otherDevice ?: "",
transactionId = action.pendingRequestTransactionId
)
} else {
session.cryptoService().verificationService().beginKeyVerificationInDMs(
VerificationMethod.SAS,
transactionId = action.pendingRequestTransactionId,
roomId = roomId,
otherUserId = request.otherUserId,
otherDeviceId = otherDevice ?: ""
)
viewModelScope.launch {
if (roomId == null) {
session.cryptoService().verificationService().beginKeyVerification(
VerificationMethod.SAS,
otherUserId = request.otherUserId,
otherDeviceId = otherDevice ?: "",
transactionId = action.pendingRequestTransactionId
)
} else {
session.cryptoService().verificationService().beginKeyVerificationInDMs(
VerificationMethod.SAS,
transactionId = action.pendingRequestTransactionId,
roomId = roomId,
otherUserId = request.otherUserId,
otherDeviceId = otherDevice ?: ""
)
}
}
Unit
}
@ -365,6 +324,50 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
}.exhaustive
}
private fun handleRequestVerificationByDM(roomId: String?, otherUserId: String) {
viewModelScope.launch {
if (roomId == null) {
val localId = LocalEcho.createLocalEchoId()
setState {
copy(
pendingLocalId = localId,
pendingRequest = Loading()
)
}
try {
val dmRoomId = session.createDirectRoom(otherUserId)
val pendingRequest = session
.cryptoService()
.verificationService()
.requestKeyVerificationInDMs(
supportedVerificationMethodsProvider.provide(),
otherUserId,
dmRoomId,
localId
)
setState {
copy(
roomId = dmRoomId,
pendingRequest = Success(pendingRequest)
)
}
} catch (failure: Throwable) {
setState {
copy(pendingRequest = Fail(failure))
}
}
} else {
val pendingRequest = session
.cryptoService()
.verificationService()
.requestKeyVerificationInDMs(supportedVerificationMethodsProvider.provide(), otherUserId, roomId)
setState {
copy(pendingRequest = Success(pendingRequest))
}
}
}
}
private fun handleSecretBackFromSSSS(action: VerificationAction.GotResultFromSsss) {
viewModelScope.launch(Dispatchers.IO) {
try {
@ -514,12 +517,14 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
if (!pr.isReady) {
// auto ready in this case, as we are waiting
// TODO, can I be here in DM mode? in this case should test if roomID is null?
session.cryptoService().verificationService()
.readyPendingVerification(
supportedVerificationMethodsProvider.provide(),
pr.otherUserId,
pr.transactionId ?: ""
)
viewModelScope.launch {
session.cryptoService().verificationService()
.readyPendingVerification(
supportedVerificationMethodsProvider.provide(),
pr.otherUserId,
pr.transactionId ?: ""
)
}
}
// Use this one!

View File

@ -994,22 +994,26 @@ class TimelineViewModel @AssistedInject constructor(
private fun handleAcceptVerification(action: RoomDetailAction.AcceptVerificationRequest) {
Timber.v("## SAS handleAcceptVerification ${action.otherUserId}, roomId:${room.roomId}, txId:${action.transactionId}")
if (session.cryptoService().verificationService().readyPendingVerificationInDMs(
supportedVerificationMethodsProvider.provide(),
action.otherUserId,
room.roomId,
action.transactionId)) {
_viewEvents.post(RoomDetailViewEvents.ActionSuccess(action))
} else {
// TODO
viewModelScope.launch {
if (session.cryptoService().verificationService().readyPendingVerificationInDMs(
supportedVerificationMethodsProvider.provide(),
action.otherUserId,
room.roomId,
action.transactionId)) {
_viewEvents.post(RoomDetailViewEvents.ActionSuccess(action))
} else {
// TODO
}
}
}
private fun handleDeclineVerification(action: RoomDetailAction.DeclineVerificationRequest) {
session.cryptoService().verificationService().declineVerificationRequestInDMs(
action.otherUserId,
action.transactionId,
room.roomId)
viewModelScope.launch {
session.cryptoService().verificationService().declineVerificationRequestInDMs(
action.otherUserId,
action.transactionId,
room.roomId)
}
}
private fun handleRequestVerification(action: RoomDetailAction.RequestVerification) {

View File

@ -100,6 +100,8 @@ import im.vector.app.features.terms.ReviewTermsActivity
import im.vector.app.features.widgets.WidgetActivity
import im.vector.app.features.widgets.WidgetArgsBuilder
import im.vector.app.space
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTransaction
import org.matrix.android.sdk.api.session.permalinks.PermalinkData
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoom
@ -116,7 +118,8 @@ class DefaultNavigator @Inject constructor(
private val widgetArgsBuilder: WidgetArgsBuilder,
private val appStateHandler: AppStateHandler,
private val supportedVerificationMethodsProvider: SupportedVerificationMethodsProvider,
private val features: VectorFeatures
private val features: VectorFeatures,
private val coroutineScope: CoroutineScope
) : Navigator {
override fun openLogin(context: Context, loginConfig: LoginConfig?, flags: Int) {
@ -210,38 +213,42 @@ class DefaultNavigator @Inject constructor(
}
override fun requestSessionVerification(context: Context, otherSessionId: String) {
val session = sessionHolder.getSafeActiveSession() ?: return
val pr = session.cryptoService().verificationService().requestKeyVerification(
supportedVerificationMethodsProvider.provide(),
session.myUserId,
listOf(otherSessionId)
)
if (context is AppCompatActivity) {
VerificationBottomSheet.withArgs(
roomId = null,
otherUserId = session.myUserId,
transactionId = pr.transactionId
).show(context.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG)
coroutineScope.launch {
val session = sessionHolder.getSafeActiveSession() ?: return@launch
val pr = session.cryptoService().verificationService().requestKeyVerification(
supportedVerificationMethodsProvider.provide(),
session.myUserId,
listOf(otherSessionId)
)
if (context is AppCompatActivity) {
VerificationBottomSheet.withArgs(
roomId = null,
otherUserId = session.myUserId,
transactionId = pr.transactionId
).show(context.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG)
}
}
}
override fun requestSelfSessionVerification(context: Context) {
val session = sessionHolder.getSafeActiveSession() ?: return
val otherSessions = session.cryptoService()
.getCryptoDeviceInfo(session.myUserId)
.filter { it.deviceId != session.sessionParams.deviceId }
.map { it.deviceId }
if (context is AppCompatActivity) {
if (otherSessions.isNotEmpty()) {
val pr = session.cryptoService().verificationService().requestKeyVerification(
supportedVerificationMethodsProvider.provide(),
session.myUserId,
otherSessions)
VerificationBottomSheet.forSelfVerification(session, pr.transactionId ?: pr.localId)
.show(context.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG)
} else {
VerificationBottomSheet.forSelfVerification(session)
.show(context.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG)
coroutineScope.launch {
val session = sessionHolder.getSafeActiveSession() ?: return@launch
val otherSessions = session.cryptoService()
.getCryptoDeviceInfo(session.myUserId)
.filter { it.deviceId != session.sessionParams.deviceId }
.map { it.deviceId }
if (context is AppCompatActivity) {
if (otherSessions.isNotEmpty()) {
val pr = session.cryptoService().verificationService().requestKeyVerification(
supportedVerificationMethodsProvider.provide(),
session.myUserId,
otherSessions)
VerificationBottomSheet.forSelfVerification(session, pr.transactionId ?: pr.localId)
.show(context.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG)
} else {
VerificationBottomSheet.forSelfVerification(session)
.show(context.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG)
}
}
}
}

View File

@ -30,6 +30,7 @@ import im.vector.app.core.di.SingletonEntryPoint
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod
@ -124,8 +125,14 @@ class DeviceListBottomSheetViewModel @AssistedInject constructor(@Assisted priva
private fun manuallyVerify(action: DeviceListAction.ManuallyVerify) {
if (!initialState.allowDeviceAction) return
session.cryptoService().verificationService().beginKeyVerification(VerificationMethod.SAS, initialState.userId, action.deviceId, null)?.let { txID ->
_viewEvents.post(DeviceListBottomSheetViewEvents.Verify(initialState.userId, txID))
viewModelScope.launch {
session.cryptoService().verificationService().beginKeyVerification(
method = VerificationMethod.SAS,
otherUserId = initialState.userId,
otherDeviceId = action.deviceId,
transactionId = null)?.let { txID ->
_viewEvents.post(DeviceListBottomSheetViewEvents.Verify(initialState.userId, txID))
}
}
}
}

View File

@ -240,13 +240,15 @@ class DevicesViewModel @AssistedInject constructor(
}
private fun handleInteractiveVerification(action: DevicesAction.VerifyMyDevice) {
val txID = session.cryptoService()
.verificationService()
.beginKeyVerification(VerificationMethod.SAS, session.myUserId, action.deviceId, null)
_viewEvents.post(DevicesViewEvents.ShowVerifyDevice(
session.myUserId,
txID
))
viewModelScope.launch {
val txID = session.cryptoService()
.verificationService()
.beginKeyVerification(VerificationMethod.SAS, session.myUserId, action.deviceId, null)
_viewEvents.post(DevicesViewEvents.ShowVerifyDevice(
session.myUserId,
txID
))
}
}
private fun handleShowDeviceCryptoInfo(action: DevicesAction.VerifyMyDeviceManually) = withState { state ->