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 * 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? fun getExistingTransaction(otherUserId: String, tid: String): VerificationTransaction?
@ -46,7 +46,7 @@ interface VerificationService {
fun getExistingVerificationRequestInRoom(roomId: String, tid: String?): PendingVerificationRequest? fun getExistingVerificationRequestInRoom(roomId: String, tid: String?): PendingVerificationRequest?
fun beginKeyVerification(method: VerificationMethod, suspend fun beginKeyVerification(method: VerificationMethod,
otherUserId: String, otherUserId: String,
otherDeviceId: String, otherDeviceId: String,
transactionId: String?): 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) * 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, otherUserId: String,
roomId: String, roomId: String,
localId: String? = LocalEcho.createLocalEchoId()): PendingVerificationRequest localId: String? = LocalEcho.createLocalEchoId()): PendingVerificationRequest
fun cancelVerificationRequest(request: PendingVerificationRequest) suspend fun cancelVerificationRequest(request: PendingVerificationRequest)
/** /**
* Request a key verification from another user using toDevice events. * Request a key verification from another user using toDevice events.
*/ */
fun requestKeyVerification(methods: List<VerificationMethod>, suspend fun requestKeyVerification(methods: List<VerificationMethod>,
otherUserId: String, otherUserId: String,
otherDevices: List<String>?): PendingVerificationRequest otherDevices: List<String>?): PendingVerificationRequest
fun declineVerificationRequestInDMs(otherUserId: String, suspend fun declineVerificationRequestInDMs(otherUserId: String,
transactionId: String, transactionId: String,
roomId: String) roomId: String)
// Only SAS method is supported for the moment // Only SAS method is supported for the moment
// TODO Parameter otherDeviceId should be removed in this case // TODO Parameter otherDeviceId should be removed in this case
fun beginKeyVerificationInDMs(method: VerificationMethod, suspend fun beginKeyVerificationInDMs(method: VerificationMethod,
transactionId: String, transactionId: String,
roomId: String, roomId: String,
otherUserId: String, otherUserId: String,
@ -83,7 +83,7 @@ interface VerificationService {
/** /**
* Returns false if the request is unknown * Returns false if the request is unknown
*/ */
fun readyPendingVerificationInDMs(methods: List<VerificationMethod>, suspend fun readyPendingVerificationInDMs(methods: List<VerificationMethod>,
otherUserId: String, otherUserId: String,
roomId: String, roomId: String,
transactionId: String): Boolean transactionId: String): Boolean
@ -91,7 +91,7 @@ interface VerificationService {
/** /**
* Returns false if the request is unknown * Returns false if the request is unknown
*/ */
fun readyPendingVerification(methods: List<VerificationMethod>, suspend fun readyPendingVerification(methods: List<VerificationMethod>,
otherUserId: String, otherUserId: String,
transactionId: String): Boolean 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.Json
import com.squareup.moshi.JsonClass 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.PendingVerificationRequest
import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService 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) 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? // TODO this doesn't seem to be used anymore?
runBlocking { val device = olmMachine.getDevice(userId, deviceID)
val device = olmMachine.getDevice(userId, deviceID) device?.markAsTrusted()
device?.markAsTrusted()
}
} }
override fun onPotentiallyInterestingEventRoomFailToDecrypt(event: Event) { override fun onPotentiallyInterestingEventRoomFailToDecrypt(event: Event) {
@ -224,13 +221,13 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
return null return null
} }
override fun requestKeyVerification( override suspend fun requestKeyVerification(
methods: List<VerificationMethod>, methods: List<VerificationMethod>,
otherUserId: String, otherUserId: String,
otherDevices: List<String>? otherDevices: List<String>?
): PendingVerificationRequest { ): PendingVerificationRequest {
val verification = when (val identity = runBlocking { olmMachine.getIdentity(otherUserId) }) { val verification = when (val identity = olmMachine.getIdentity(otherUserId)) {
is OwnUserIdentity -> runBlocking { identity.requestVerification(methods) } is OwnUserIdentity -> identity.requestVerification(methods)
is UserIdentity -> throw IllegalArgumentException("This method doesn't support verification of other users devices") 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") 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() return verification.toPendingVerificationRequest()
} }
override fun requestKeyVerificationInDMs( override suspend fun requestKeyVerificationInDMs(
methods: List<VerificationMethod>, methods: List<VerificationMethod>,
otherUserId: String, otherUserId: String,
roomId: String, roomId: String,
localId: String? localId: String?
): PendingVerificationRequest { ): PendingVerificationRequest {
Timber.i("## SAS Requesting verification to user: $otherUserId in room $roomId") Timber.i("## SAS Requesting verification to user: $otherUserId in room $roomId")
val verification = when (val identity = runBlocking { olmMachine.getIdentity(otherUserId) }) { val verification = when (val identity = olmMachine.getIdentity(otherUserId)) {
is UserIdentity -> runBlocking { identity.requestVerification(methods, roomId, localId!!) } is UserIdentity -> identity.requestVerification(methods, roomId, localId!!)
is OwnUserIdentity -> throw IllegalArgumentException("This method doesn't support verification of our own user") 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") 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() return verification.toPendingVerificationRequest()
} }
override fun readyPendingVerification( override suspend fun readyPendingVerification(
methods: List<VerificationMethod>, methods: List<VerificationMethod>,
otherUserId: String, otherUserId: String,
transactionId: String transactionId: String
@ -262,7 +259,7 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
val request = this.olmMachine.getVerificationRequest(otherUserId, transactionId) val request = this.olmMachine.getVerificationRequest(otherUserId, transactionId)
return if (request != null) { return if (request != null) {
runBlocking { request.acceptWithMethods(methods) } request.acceptWithMethods(methods)
if (request.isReady()) { if (request.isReady()) {
val qrcode = request.startQrVerification() 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>, methods: List<VerificationMethod>,
otherUserId: String, otherUserId: String,
roomId: String, roomId: String,
@ -289,7 +286,7 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
return readyPendingVerification(methods, otherUserId, transactionId) return readyPendingVerification(methods, otherUserId, transactionId)
} }
override fun beginKeyVerification( override suspend fun beginKeyVerification(
method: VerificationMethod, method: VerificationMethod,
otherUserId: String, otherUserId: String,
otherDeviceId: String, otherDeviceId: String,
@ -299,15 +296,13 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
if (transactionId != null) { if (transactionId != null) {
val request = this.olmMachine.getVerificationRequest(otherUserId, transactionId) val request = this.olmMachine.getVerificationRequest(otherUserId, transactionId)
runBlocking { val sas = request?.startSasVerification()
val sas = request?.startSasVerification()
if (sas != null) { if (sas != null) {
dispatcher.dispatchTxAdded(sas) dispatcher.dispatchTxAdded(sas)
sas.transactionId sas.transactionId
} else { } else {
null null
}
} }
} else { } else {
// This starts the short SAS flow, the one that doesn't start with // 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 // be wise do do so as well
// DeviceListBottomSheetViewModel triggers this, interestingly the method that // DeviceListBottomSheetViewModel triggers this, interestingly the method that
// triggers this is called `manuallyVerify()` // triggers this is called `manuallyVerify()`
runBlocking { val verification = olmMachine.getDevice(otherUserId, otherDeviceId)?.startVerification()
val verification = olmMachine.getDevice(otherUserId, otherDeviceId)?.startVerification() if (verification != null) {
if (verification != null) { dispatcher.dispatchTxAdded(verification)
dispatcher.dispatchTxAdded(verification) verification.transactionId
verification.transactionId } else {
} else { null
null
}
} }
} }
} else { } else {
@ -330,7 +323,7 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
} }
} }
override fun beginKeyVerificationInDMs( override suspend fun beginKeyVerificationInDMs(
method: VerificationMethod, method: VerificationMethod,
transactionId: String, transactionId: String,
roomId: String, roomId: String,
@ -343,19 +336,19 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
return transactionId return transactionId
} }
override fun cancelVerificationRequest(request: PendingVerificationRequest) { override suspend fun cancelVerificationRequest(request: PendingVerificationRequest) {
val verificationRequest = request.transactionId?.let { val verificationRequest = request.transactionId?.let {
this.olmMachine.getVerificationRequest(request.otherUserId, it) this.olmMachine.getVerificationRequest(request.otherUserId, it)
} }
runBlocking { verificationRequest?.cancel() } verificationRequest?.cancel()
} }
override fun declineVerificationRequestInDMs( override suspend fun declineVerificationRequestInDMs(
otherUserId: String, otherUserId: String,
transactionId: String, transactionId: String,
roomId: String roomId: String
) { ) {
val verificationRequest = this.olmMachine.getVerificationRequest(otherUserId, transactionId) 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 // 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 // if not they could be accepted in the middle of the reset process
// and cause strange use cases // and cause strange use cases
session.cryptoService().verificationService().getExistingVerificationRequests(session.myUserId).forEach { viewModelScope.launch {
session.cryptoService().verificationService().cancelVerificationRequest(it) session.cryptoService().verificationService().getExistingVerificationRequests(session.myUserId).forEach {
session.cryptoService().verificationService().cancelVerificationRequest(it)
}
_viewEvents.post(SharedSecureStorageViewEvent.ShowResetBottomSheet)
} }
_viewEvents.post(SharedSecureStorageViewEvent.ShowResetBottomSheet)
} }
private fun handleResetAll() { 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.home.room.detail.arguments.TimelineArgs
import im.vector.app.features.popup.PopupAlertManager import im.vector.app.features.popup.PopupAlertManager
import im.vector.app.features.popup.VerificationVectorAlert 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.Session
import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificationRequest import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificationRequest
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
@ -42,7 +44,8 @@ import javax.inject.Singleton
class IncomingVerificationRequestHandler @Inject constructor( class IncomingVerificationRequestHandler @Inject constructor(
private val context: Context, private val context: Context,
private var avatarRenderer: Provider<AvatarRenderer>, 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 private var session: Session? = null
@ -61,7 +64,7 @@ class IncomingVerificationRequestHandler @Inject constructor(
// TODO maybe check also if // TODO maybe check also if
val uid = "kvr_${tx.transactionId}" val uid = "kvr_${tx.transactionId}"
when (tx.state) { when (tx.state) {
is VerificationTxState.OnStarted -> { is VerificationTxState.OnStarted -> {
// Add a notification for every incoming request // Add a notification for every incoming request
val user = session?.getUser(tx.otherUserId) val user = session?.getUser(tx.otherUserId)
val name = user?.toMatrixItem()?.getBestName() ?: tx.otherUserId val name = user?.toMatrixItem()?.getBestName() ?: tx.otherUserId
@ -161,10 +164,12 @@ class IncomingVerificationRequestHandler @Inject constructor(
} }
} }
dismissedAction = Runnable { dismissedAction = Runnable {
session?.cryptoService()?.verificationService()?.declineVerificationRequestInDMs(pr.otherUserId, coroutineScope.launch {
pr.transactionId ?: "", session?.cryptoService()?.verificationService()?.declineVerificationRequestInDMs(pr.otherUserId,
pr.roomId ?: "" pr.transactionId ?: "",
) pr.roomId ?: ""
)
}
} }
colorAttribute = R.attr.vctr_notice_secondary colorAttribute = R.attr.vctr_notice_secondary
// 5mn expiration // 5mn expiration

View File

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

View File

@ -994,22 +994,26 @@ class TimelineViewModel @AssistedInject constructor(
private fun handleAcceptVerification(action: RoomDetailAction.AcceptVerificationRequest) { private fun handleAcceptVerification(action: RoomDetailAction.AcceptVerificationRequest) {
Timber.v("## SAS handleAcceptVerification ${action.otherUserId}, roomId:${room.roomId}, txId:${action.transactionId}") Timber.v("## SAS handleAcceptVerification ${action.otherUserId}, roomId:${room.roomId}, txId:${action.transactionId}")
if (session.cryptoService().verificationService().readyPendingVerificationInDMs( viewModelScope.launch {
supportedVerificationMethodsProvider.provide(), if (session.cryptoService().verificationService().readyPendingVerificationInDMs(
action.otherUserId, supportedVerificationMethodsProvider.provide(),
room.roomId, action.otherUserId,
action.transactionId)) { room.roomId,
_viewEvents.post(RoomDetailViewEvents.ActionSuccess(action)) action.transactionId)) {
} else { _viewEvents.post(RoomDetailViewEvents.ActionSuccess(action))
// TODO } else {
// TODO
}
} }
} }
private fun handleDeclineVerification(action: RoomDetailAction.DeclineVerificationRequest) { private fun handleDeclineVerification(action: RoomDetailAction.DeclineVerificationRequest) {
session.cryptoService().verificationService().declineVerificationRequestInDMs( viewModelScope.launch {
action.otherUserId, session.cryptoService().verificationService().declineVerificationRequestInDMs(
action.transactionId, action.otherUserId,
room.roomId) action.transactionId,
room.roomId)
}
} }
private fun handleRequestVerification(action: RoomDetailAction.RequestVerification) { 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.WidgetActivity
import im.vector.app.features.widgets.WidgetArgsBuilder import im.vector.app.features.widgets.WidgetArgsBuilder
import im.vector.app.space 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.crypto.verification.SasVerificationTransaction
import org.matrix.android.sdk.api.session.permalinks.PermalinkData import org.matrix.android.sdk.api.session.permalinks.PermalinkData
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoom 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 widgetArgsBuilder: WidgetArgsBuilder,
private val appStateHandler: AppStateHandler, private val appStateHandler: AppStateHandler,
private val supportedVerificationMethodsProvider: SupportedVerificationMethodsProvider, private val supportedVerificationMethodsProvider: SupportedVerificationMethodsProvider,
private val features: VectorFeatures private val features: VectorFeatures,
private val coroutineScope: CoroutineScope
) : Navigator { ) : Navigator {
override fun openLogin(context: Context, loginConfig: LoginConfig?, flags: Int) { override fun openLogin(context: Context, loginConfig: LoginConfig?, flags: Int) {
@ -210,38 +213,42 @@ class DefaultNavigator @Inject constructor(
} }
override fun requestSessionVerification(context: Context, otherSessionId: String) { override fun requestSessionVerification(context: Context, otherSessionId: String) {
val session = sessionHolder.getSafeActiveSession() ?: return coroutineScope.launch {
val pr = session.cryptoService().verificationService().requestKeyVerification( val session = sessionHolder.getSafeActiveSession() ?: return@launch
supportedVerificationMethodsProvider.provide(), val pr = session.cryptoService().verificationService().requestKeyVerification(
session.myUserId, supportedVerificationMethodsProvider.provide(),
listOf(otherSessionId) session.myUserId,
) listOf(otherSessionId)
if (context is AppCompatActivity) { )
VerificationBottomSheet.withArgs( if (context is AppCompatActivity) {
roomId = null, VerificationBottomSheet.withArgs(
otherUserId = session.myUserId, roomId = null,
transactionId = pr.transactionId otherUserId = session.myUserId,
).show(context.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG) transactionId = pr.transactionId
).show(context.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG)
}
} }
} }
override fun requestSelfSessionVerification(context: Context) { override fun requestSelfSessionVerification(context: Context) {
val session = sessionHolder.getSafeActiveSession() ?: return coroutineScope.launch {
val otherSessions = session.cryptoService() val session = sessionHolder.getSafeActiveSession() ?: return@launch
.getCryptoDeviceInfo(session.myUserId) val otherSessions = session.cryptoService()
.filter { it.deviceId != session.sessionParams.deviceId } .getCryptoDeviceInfo(session.myUserId)
.map { it.deviceId } .filter { it.deviceId != session.sessionParams.deviceId }
if (context is AppCompatActivity) { .map { it.deviceId }
if (otherSessions.isNotEmpty()) { if (context is AppCompatActivity) {
val pr = session.cryptoService().verificationService().requestKeyVerification( if (otherSessions.isNotEmpty()) {
supportedVerificationMethodsProvider.provide(), val pr = session.cryptoService().verificationService().requestKeyVerification(
session.myUserId, supportedVerificationMethodsProvider.provide(),
otherSessions) session.myUserId,
VerificationBottomSheet.forSelfVerification(session, pr.transactionId ?: pr.localId) otherSessions)
.show(context.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG) VerificationBottomSheet.forSelfVerification(session, pr.transactionId ?: pr.localId)
} else { .show(context.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG)
VerificationBottomSheet.forSelfVerification(session) } else {
.show(context.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG) 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.di.hiltMavericksViewModelFactory
import im.vector.app.core.extensions.exhaustive import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel 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.Session
import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod 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) { private fun manuallyVerify(action: DeviceListAction.ManuallyVerify) {
if (!initialState.allowDeviceAction) return if (!initialState.allowDeviceAction) return
session.cryptoService().verificationService().beginKeyVerification(VerificationMethod.SAS, initialState.userId, action.deviceId, null)?.let { txID -> viewModelScope.launch {
_viewEvents.post(DeviceListBottomSheetViewEvents.Verify(initialState.userId, txID)) 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) { private fun handleInteractiveVerification(action: DevicesAction.VerifyMyDevice) {
val txID = session.cryptoService() viewModelScope.launch {
.verificationService() val txID = session.cryptoService()
.beginKeyVerification(VerificationMethod.SAS, session.myUserId, action.deviceId, null) .verificationService()
_viewEvents.post(DevicesViewEvents.ShowVerifyDevice( .beginKeyVerification(VerificationMethod.SAS, session.myUserId, action.deviceId, null)
session.myUserId, _viewEvents.post(DevicesViewEvents.ShowVerifyDevice(
txID session.myUserId,
)) txID
))
}
} }
private fun handleShowDeviceCryptoInfo(action: DevicesAction.VerifyMyDeviceManually) = withState { state -> private fun handleShowDeviceCryptoInfo(action: DevicesAction.VerifyMyDeviceManually) = withState { state ->