To Device Verification Request
This commit is contained in:
parent
069bd3c258
commit
225e4e0433
|
@ -47,7 +47,10 @@ interface VerificationService {
|
||||||
|
|
||||||
fun getExistingVerificationRequestInRoom(roomId: String, tid: String?): PendingVerificationRequest?
|
fun getExistingVerificationRequestInRoom(roomId: String, tid: String?): PendingVerificationRequest?
|
||||||
|
|
||||||
fun beginKeyVerification(method: VerificationMethod, otherUserId: String, otherDeviceID: String): String?
|
fun beginKeyVerification(method: VerificationMethod,
|
||||||
|
otherUserId: String,
|
||||||
|
otherDeviceId: String,
|
||||||
|
transactionId: String?): String?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request a key verification from another user using toDevice events.
|
* Request a key verification from another user using toDevice events.
|
||||||
|
@ -62,11 +65,14 @@ interface VerificationService {
|
||||||
* 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>,
|
fun requestKeyVerification(methods: List<VerificationMethod>,
|
||||||
otherUserId: String,
|
otherUserId: String,
|
||||||
otherDevices: List<String>?
|
otherDevices: List<String>?
|
||||||
): PendingVerificationRequest
|
): PendingVerificationRequest
|
||||||
|
|
||||||
fun declineVerificationRequestInDMs(otherUserId: String, otherDeviceId: String, transactionId: String, roomId: String)
|
fun declineVerificationRequestInDMs(otherUserId: String,
|
||||||
|
otherDeviceId: String,
|
||||||
|
transactionId: String,
|
||||||
|
roomId: String)
|
||||||
|
|
||||||
// Only SAS method is supported for the moment
|
// Only SAS method is supported for the moment
|
||||||
fun beginKeyVerificationInDMs(method: VerificationMethod,
|
fun beginKeyVerificationInDMs(method: VerificationMethod,
|
||||||
|
@ -84,6 +90,13 @@ interface VerificationService {
|
||||||
roomId: String,
|
roomId: String,
|
||||||
transactionId: String): Boolean
|
transactionId: String): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns false if the request is unknown
|
||||||
|
*/
|
||||||
|
fun readyPendingVerification(methods: List<VerificationMethod>,
|
||||||
|
otherUserId: String,
|
||||||
|
transactionId: String): Boolean
|
||||||
|
|
||||||
// fun transactionUpdated(tx: SasVerificationTransaction)
|
// fun transactionUpdated(tx: SasVerificationTransaction)
|
||||||
|
|
||||||
interface VerificationListener {
|
interface VerificationListener {
|
||||||
|
|
|
@ -26,7 +26,7 @@ import im.vector.matrix.android.internal.crypto.verification.VerificationInfoReq
|
||||||
internal data class KeyVerificationRequest(
|
internal data class KeyVerificationRequest(
|
||||||
@Json(name = "from_device") override val fromDevice: String?,
|
@Json(name = "from_device") override val fromDevice: String?,
|
||||||
@Json(name = "methods") override val methods: List<String>,
|
@Json(name = "methods") override val methods: List<String>,
|
||||||
@Json(name = "methods") override val timestamp: Long?,
|
@Json(name = "timestamp") override val timestamp: Long?,
|
||||||
@Json(name = "transaction_id") override var transactionID: String? = null
|
@Json(name = "transaction_id") override var transactionID: String? = null
|
||||||
|
|
||||||
) : SendToDeviceObject, VerificationInfoRequest {
|
) : SendToDeviceObject, VerificationInfoRequest {
|
||||||
|
|
|
@ -55,6 +55,7 @@ import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationAccept
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationCancel
|
import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationCancel
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationKey
|
import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationKey
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationMac
|
import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationMac
|
||||||
|
import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationReady
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationRequest
|
import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationRequest
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationStart
|
import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationStart
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.VERIFICATION_METHOD_QR_CODE_SCAN
|
import im.vector.matrix.android.internal.crypto.model.rest.VERIFICATION_METHOD_QR_CODE_SCAN
|
||||||
|
@ -110,25 +111,28 @@ internal class DefaultVerificationService @Inject constructor(
|
||||||
fun onToDeviceEvent(event: Event) {
|
fun onToDeviceEvent(event: Event) {
|
||||||
GlobalScope.launch(coroutineDispatchers.crypto) {
|
GlobalScope.launch(coroutineDispatchers.crypto) {
|
||||||
when (event.getClearType()) {
|
when (event.getClearType()) {
|
||||||
EventType.KEY_VERIFICATION_START -> {
|
EventType.KEY_VERIFICATION_START -> {
|
||||||
onStartRequestReceived(event)
|
onStartRequestReceived(event)
|
||||||
}
|
}
|
||||||
EventType.KEY_VERIFICATION_CANCEL -> {
|
EventType.KEY_VERIFICATION_CANCEL -> {
|
||||||
onCancelReceived(event)
|
onCancelReceived(event)
|
||||||
}
|
}
|
||||||
EventType.KEY_VERIFICATION_ACCEPT -> {
|
EventType.KEY_VERIFICATION_ACCEPT -> {
|
||||||
onAcceptReceived(event)
|
onAcceptReceived(event)
|
||||||
}
|
}
|
||||||
EventType.KEY_VERIFICATION_KEY -> {
|
EventType.KEY_VERIFICATION_KEY -> {
|
||||||
onKeyReceived(event)
|
onKeyReceived(event)
|
||||||
}
|
}
|
||||||
EventType.KEY_VERIFICATION_MAC -> {
|
EventType.KEY_VERIFICATION_MAC -> {
|
||||||
onMacReceived(event)
|
onMacReceived(event)
|
||||||
}
|
}
|
||||||
MessageType.MSGTYPE_VERIFICATION_REQUEST -> {
|
EventType.KEY_VERIFICATION_READY -> {
|
||||||
|
onReadyReceived(event)
|
||||||
|
}
|
||||||
|
MessageType.MSGTYPE_VERIFICATION_REQUEST -> {
|
||||||
onRequestReceived(event)
|
onRequestReceived(event)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -263,7 +267,6 @@ internal class DefaultVerificationService @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun onRequestReceived(event: Event) {
|
private fun onRequestReceived(event: Event) {
|
||||||
val requestInfo = event.getClearContent().toModel<KeyVerificationRequest>()!!
|
val requestInfo = event.getClearContent().toModel<KeyVerificationRequest>()!!
|
||||||
|
|
||||||
|
@ -279,7 +282,7 @@ internal class DefaultVerificationService @Inject constructor(
|
||||||
|
|
||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
if (checkKeysAreDownloaded(senderId, otherDeviceId) == null) {
|
if (checkKeysAreDownloaded(senderId, otherDeviceId) == null) {
|
||||||
Timber.e("## Verification device $otherDeviceId is not knwon")
|
Timber.e("## Verification device $otherDeviceId is not known")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,14 +297,13 @@ internal class DefaultVerificationService @Inject constructor(
|
||||||
isIncoming = true,
|
isIncoming = true,
|
||||||
otherUserId = senderId, // requestInfo.toUserId,
|
otherUserId = senderId, // requestInfo.toUserId,
|
||||||
roomId = null,
|
roomId = null,
|
||||||
transactionId = event.eventId,
|
transactionId = requestInfo.transactionID,
|
||||||
requestInfo = requestInfo
|
requestInfo = requestInfo
|
||||||
)
|
)
|
||||||
requestsForUser.add(pendingVerificationRequest)
|
requestsForUser.add(pendingVerificationRequest)
|
||||||
dispatchRequestAdded(pendingVerificationRequest)
|
dispatchRequestAdded(pendingVerificationRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
suspend fun onRoomRequestReceived(event: Event) {
|
suspend fun onRoomRequestReceived(event: Event) {
|
||||||
Timber.v("## SAS Verification request from ${event.senderId} in room ${event.roomId}")
|
Timber.v("## SAS Verification request from ${event.senderId} in room ${event.roomId}")
|
||||||
val requestInfo = event.getClearContent().toModel<MessageVerificationRequestContent>()
|
val requestInfo = event.getClearContent().toModel<MessageVerificationRequestContent>()
|
||||||
|
@ -318,7 +320,7 @@ internal class DefaultVerificationService @Inject constructor(
|
||||||
// We don't want to block here
|
// We don't want to block here
|
||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
if (checkKeysAreDownloaded(senderId, fromDevice) == null) {
|
if (checkKeysAreDownloaded(senderId, fromDevice) == null) {
|
||||||
Timber.e("## SAS Verification device $fromDevice is not knwon")
|
Timber.e("## SAS Verification device $fromDevice is not known")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -677,7 +679,29 @@ internal class DefaultVerificationService @Inject constructor(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
handleReadyReceived(event.senderId, event.roomId!!, readyReq)
|
handleReadyReceived(event.senderId, readyReq) {
|
||||||
|
verificationTransportRoomMessageFactory.createTransport(event.roomId!!, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun onReadyReceived(event: Event) {
|
||||||
|
val readyReq = event.getClearContent().toModel<KeyVerificationReady>()
|
||||||
|
|
||||||
|
if (readyReq == null || readyReq.isValid().not() || event.senderId == null) {
|
||||||
|
// ignore
|
||||||
|
Timber.e("## SAS Received invalid ready request")
|
||||||
|
// TODO should we cancel?
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (checkKeysAreDownloaded(event.senderId, readyReq.fromDevice ?: "") == null) {
|
||||||
|
Timber.e("## SAS Verification device ${readyReq.fromDevice} is not known")
|
||||||
|
// TODO cancel?
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
handleReadyReceived(event.senderId, readyReq) {
|
||||||
|
verificationTransportToDeviceFactory.createTransport(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onRoomDoneReceived(event: Event) {
|
private fun onRoomDoneReceived(event: Event) {
|
||||||
|
@ -722,7 +746,9 @@ internal class DefaultVerificationService @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleReadyReceived(senderId: String, roomId: String, readyReq: VerificationInfoReady) {
|
private fun handleReadyReceived(senderId: String,
|
||||||
|
readyReq: VerificationInfoReady,
|
||||||
|
transportCreator: (DefaultVerificationTransaction) -> VerificationTransport) {
|
||||||
val existingRequest = getExistingVerificationRequest(senderId)?.find { it.transactionId == readyReq.transactionID }
|
val existingRequest = getExistingVerificationRequest(senderId)?.find { it.transactionId == readyReq.transactionID }
|
||||||
if (existingRequest == null) {
|
if (existingRequest == null) {
|
||||||
Timber.e("## SAS Received Ready for unknown request txId:${readyReq.transactionID} fromDevice ${readyReq.fromDevice}")
|
Timber.e("## SAS Received Ready for unknown request txId:${readyReq.transactionID} fromDevice ${readyReq.fromDevice}")
|
||||||
|
@ -750,7 +776,7 @@ internal class DefaultVerificationService @Inject constructor(
|
||||||
deviceId ?: "",
|
deviceId ?: "",
|
||||||
false)
|
false)
|
||||||
|
|
||||||
tx.transport = verificationTransportRoomMessageFactory.createTransport(roomId, tx)
|
tx.transport = transportCreator.invoke(tx)
|
||||||
|
|
||||||
addTransaction(tx)
|
addTransaction(tx)
|
||||||
}
|
}
|
||||||
|
@ -973,8 +999,8 @@ internal class DefaultVerificationService @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun beginKeyVerification(method: VerificationMethod, otherUserId: String, otherDeviceID: String): String? {
|
override fun beginKeyVerification(method: VerificationMethod, otherUserId: String, otherDeviceId: String, transactionId: String?): String? {
|
||||||
val txID = createUniqueIDForTransaction(otherUserId, otherDeviceID)
|
val txID = transactionId?.takeIf { it.isNotEmpty() } ?: createUniqueIDForTransaction(otherUserId, otherDeviceId)
|
||||||
// should check if already one (and cancel it)
|
// should check if already one (and cancel it)
|
||||||
if (method == VerificationMethod.SAS) {
|
if (method == VerificationMethod.SAS) {
|
||||||
val tx = DefaultOutgoingSASDefaultVerificationTransaction(
|
val tx = DefaultOutgoingSASDefaultVerificationTransaction(
|
||||||
|
@ -986,7 +1012,7 @@ internal class DefaultVerificationService @Inject constructor(
|
||||||
myDeviceInfoHolder.get().myDevice.fingerprint()!!,
|
myDeviceInfoHolder.get().myDevice.fingerprint()!!,
|
||||||
txID,
|
txID,
|
||||||
otherUserId,
|
otherUserId,
|
||||||
otherDeviceID)
|
otherDeviceId)
|
||||||
tx.transport = verificationTransportToDeviceFactory.createTransport(tx)
|
tx.transport = verificationTransportToDeviceFactory.createTransport(tx)
|
||||||
addTransaction(tx)
|
addTransaction(tx)
|
||||||
|
|
||||||
|
@ -1190,9 +1216,10 @@ internal class DefaultVerificationService @Inject constructor(
|
||||||
transactionId,
|
transactionId,
|
||||||
otherUserId,
|
otherUserId,
|
||||||
existingRequest.requestInfo?.fromDevice ?: "",
|
existingRequest.requestInfo?.fromDevice ?: "",
|
||||||
roomId,
|
|
||||||
existingRequest.requestInfo?.methods,
|
existingRequest.requestInfo?.methods,
|
||||||
methods)
|
methods) {
|
||||||
|
verificationTransportRoomMessageFactory.createTransport(roomId, it)
|
||||||
|
}
|
||||||
if (methods.isNullOrEmpty()) {
|
if (methods.isNullOrEmpty()) {
|
||||||
Timber.i("Cannot ready this request, no common methods found txId:$transactionId")
|
Timber.i("Cannot ready this request, no common methods found txId:$transactionId")
|
||||||
// TODO buttons should not be shown in this case?
|
// TODO buttons should not be shown in this case?
|
||||||
|
@ -1215,13 +1242,52 @@ internal class DefaultVerificationService @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun readyPendingVerification(methods: List<VerificationMethod>,
|
||||||
|
otherUserId: String,
|
||||||
|
transactionId: String): Boolean {
|
||||||
|
Timber.v("## SAS readyPendingVerification $otherUserId tx:$transactionId")
|
||||||
|
// Let's find the related request
|
||||||
|
val existingRequest = getExistingVerificationRequest(otherUserId, transactionId)
|
||||||
|
if (existingRequest != null) {
|
||||||
|
// we need to send a ready event, with matching methods
|
||||||
|
val transport = verificationTransportToDeviceFactory.createTransport(null)
|
||||||
|
val computedMethods = computeReadyMethods(
|
||||||
|
transactionId,
|
||||||
|
otherUserId,
|
||||||
|
existingRequest.requestInfo?.fromDevice ?: "",
|
||||||
|
existingRequest.requestInfo?.methods,
|
||||||
|
methods) {
|
||||||
|
verificationTransportToDeviceFactory.createTransport(it)
|
||||||
|
}
|
||||||
|
if (methods.isNullOrEmpty()) {
|
||||||
|
Timber.i("Cannot ready this request, no common methods found txId:$transactionId")
|
||||||
|
// TODO buttons should not be shown in this case?
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// TODO this is not yet related to a transaction, maybe we should use another method like for cancel?
|
||||||
|
val readyMsg = transport.createReady(transactionId, deviceId ?: "", computedMethods)
|
||||||
|
transport.sendVerificationReady(
|
||||||
|
readyMsg,
|
||||||
|
otherUserId,
|
||||||
|
existingRequest.requestInfo?.fromDevice ?: "",
|
||||||
|
null // TODO handle error?
|
||||||
|
)
|
||||||
|
updatePendingRequest(existingRequest.copy(readyInfo = readyMsg))
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
Timber.e("## SAS readyPendingVerification Verification not found")
|
||||||
|
// :/ should not be possible... unless live observer very slow
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun computeReadyMethods(
|
private fun computeReadyMethods(
|
||||||
transactionId: String,
|
transactionId: String,
|
||||||
otherUserId: String,
|
otherUserId: String,
|
||||||
otherDeviceId: String,
|
otherDeviceId: String,
|
||||||
roomId: String,
|
|
||||||
otherUserMethods: List<String>?,
|
otherUserMethods: List<String>?,
|
||||||
methods: List<VerificationMethod>): List<String> {
|
methods: List<VerificationMethod>,
|
||||||
|
transportCreator: (DefaultVerificationTransaction) -> VerificationTransport): List<String> {
|
||||||
if (otherUserMethods.isNullOrEmpty()) {
|
if (otherUserMethods.isNullOrEmpty()) {
|
||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
|
@ -1264,7 +1330,7 @@ internal class DefaultVerificationService @Inject constructor(
|
||||||
deviceId ?: "",
|
deviceId ?: "",
|
||||||
false)
|
false)
|
||||||
|
|
||||||
tx.transport = verificationTransportRoomMessageFactory.createTransport(roomId, tx)
|
tx.transport = transportCreator.invoke(tx)
|
||||||
|
|
||||||
addTransaction(tx)
|
addTransaction(tx)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ package im.vector.matrix.android.internal.crypto.verification
|
||||||
|
|
||||||
import im.vector.matrix.android.api.session.crypto.sas.CancelCode
|
import im.vector.matrix.android.api.session.crypto.sas.CancelCode
|
||||||
import im.vector.matrix.android.api.session.crypto.sas.VerificationMethod
|
import im.vector.matrix.android.api.session.crypto.sas.VerificationMethod
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageVerificationRequestContent
|
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.VERIFICATION_METHOD_QR_CODE_SCAN
|
import im.vector.matrix.android.internal.crypto.model.rest.VERIFICATION_METHOD_QR_CODE_SCAN
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.VERIFICATION_METHOD_QR_CODE_SHOW
|
import im.vector.matrix.android.internal.crypto.model.rest.VERIFICATION_METHOD_QR_CODE_SHOW
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.VERIFICATION_METHOD_SAS
|
import im.vector.matrix.android.internal.crypto.model.rest.VERIFICATION_METHOD_SAS
|
||||||
|
@ -40,7 +39,7 @@ data class PendingVerificationRequest(
|
||||||
val isSuccessful: Boolean = false,
|
val isSuccessful: Boolean = false,
|
||||||
val handledByOtherSession: Boolean = false,
|
val handledByOtherSession: Boolean = false,
|
||||||
// In case of to device it is sent to a list of devices
|
// In case of to device it is sent to a list of devices
|
||||||
val targetDevices: List<String> ? = null
|
val targetDevices: List<String>? = null
|
||||||
) {
|
) {
|
||||||
val isReady: Boolean = readyInfo != null
|
val isReady: Boolean = readyInfo != null
|
||||||
val isSent: Boolean = transactionId != null
|
val isSent: Boolean = transactionId != null
|
||||||
|
|
|
@ -80,4 +80,10 @@ internal interface VerificationTransport {
|
||||||
fun createMac(tid: String, mac: Map<String, String>, keys: String): VerificationInfoMac
|
fun createMac(tid: String, mac: Map<String, String>, keys: String): VerificationInfoMac
|
||||||
|
|
||||||
fun createReady(tid: String, fromDevice: String, methods: List<String>): VerificationInfoReady
|
fun createReady(tid: String, fromDevice: String, methods: List<String>): VerificationInfoReady
|
||||||
|
|
||||||
|
// TODO Refactor
|
||||||
|
fun sendVerificationReady(keyReq: VerificationInfoReady,
|
||||||
|
otherUserId: String,
|
||||||
|
otherDeviceId: String,
|
||||||
|
callback: (() -> Unit)?)
|
||||||
}
|
}
|
||||||
|
|
|
@ -332,6 +332,13 @@ internal class VerificationTransportRoomMessage(
|
||||||
localEchoEventFactory.saveLocalEcho(monarchy, it)
|
localEchoEventFactory.saveLocalEcho(monarchy, it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun sendVerificationReady(keyReq: VerificationInfoReady,
|
||||||
|
otherUserId: String,
|
||||||
|
otherDeviceId: String,
|
||||||
|
callback: (() -> Unit)?) {
|
||||||
|
// Not applicable
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class VerificationTransportRoomMessageFactory @Inject constructor(
|
internal class VerificationTransportRoomMessageFactory @Inject constructor(
|
||||||
|
|
|
@ -77,6 +77,30 @@ internal class VerificationTransportToDevice(
|
||||||
.executeBy(taskExecutor)
|
.executeBy(taskExecutor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun sendVerificationReady(keyReq: VerificationInfoReady,
|
||||||
|
otherUserId: String,
|
||||||
|
otherDeviceId: String,
|
||||||
|
callback: (() -> Unit)?) {
|
||||||
|
val contentMap = MXUsersDevicesMap<Any>()
|
||||||
|
|
||||||
|
contentMap.setObject(otherUserId, otherDeviceId, keyReq)
|
||||||
|
|
||||||
|
sendToDeviceTask
|
||||||
|
.configureWith(SendToDeviceTask.Params(EventType.KEY_VERIFICATION_READY, contentMap)) {
|
||||||
|
this.callback = object : MatrixCallback<Unit> {
|
||||||
|
override fun onSuccess(data: Unit) {
|
||||||
|
Timber.v("## verification [$tx.transactionId] send toDevice request success")
|
||||||
|
callback?.invoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(failure: Throwable) {
|
||||||
|
Timber.e("## verification [$tx.transactionId] failed to send toDevice request")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.executeBy(taskExecutor)
|
||||||
|
}
|
||||||
|
|
||||||
override fun sendToOther(type: String,
|
override fun sendToOther(type: String,
|
||||||
verificationInfo: VerificationInfo,
|
verificationInfo: VerificationInfo,
|
||||||
nextState: VerificationTxState,
|
nextState: VerificationTxState,
|
||||||
|
|
|
@ -135,7 +135,16 @@ class IncomingVerificationRequestHandler @Inject constructor(private val context
|
||||||
.apply {
|
.apply {
|
||||||
contentAction = Runnable {
|
contentAction = Runnable {
|
||||||
(weakCurrentActivity?.get() as? VectorBaseActivity)?.let {
|
(weakCurrentActivity?.get() as? VectorBaseActivity)?.let {
|
||||||
it.navigator.openRoom(it, pr.roomId ?: "", pr.transactionId)
|
val roomId = pr.roomId
|
||||||
|
if (roomId.isNullOrBlank()) {
|
||||||
|
session?.getVerificationService()
|
||||||
|
?.readyPendingVerification(supportedVerificationMethods,
|
||||||
|
pr.otherUserId,
|
||||||
|
pr.transactionId ?: "")
|
||||||
|
it.navigator.waitSessionVerification(it)
|
||||||
|
} else {
|
||||||
|
it.navigator.openRoom(it, roomId, pr.transactionId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dismissedAction = Runnable {
|
dismissedAction = Runnable {
|
||||||
|
|
|
@ -47,7 +47,6 @@ import im.vector.riotx.core.extensions.exhaustive
|
||||||
import im.vector.riotx.core.platform.EmptyViewEvents
|
import im.vector.riotx.core.platform.EmptyViewEvents
|
||||||
import im.vector.riotx.core.platform.VectorViewModel
|
import im.vector.riotx.core.platform.VectorViewModel
|
||||||
import im.vector.riotx.core.utils.LiveEvent
|
import im.vector.riotx.core.utils.LiveEvent
|
||||||
import timber.log.Timber
|
|
||||||
|
|
||||||
data class VerificationBottomSheetViewState(
|
data class VerificationBottomSheetViewState(
|
||||||
val otherUserMxItem: MatrixItem? = null,
|
val otherUserMxItem: MatrixItem? = null,
|
||||||
|
@ -95,7 +94,15 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(@Assisted ini
|
||||||
|
|
||||||
val userItem = session.getUser(args.otherUserId)
|
val userItem = session.getUser(args.otherUserId)
|
||||||
|
|
||||||
val pr = session.getVerificationService().getExistingVerificationRequest(args.otherUserId, args.verificationId)
|
val isWaitingForOtherMode = args.waitForIncomingRequest
|
||||||
|
|
||||||
|
val pr = if (isWaitingForOtherMode) {
|
||||||
|
// See if active tx for this user and take it
|
||||||
|
session.getVerificationService().getExistingVerificationRequest(args.otherUserId)
|
||||||
|
?.firstOrNull { !it.isFinished }
|
||||||
|
} else {
|
||||||
|
session.getVerificationService().getExistingVerificationRequest(args.otherUserId, args.verificationId)
|
||||||
|
}
|
||||||
|
|
||||||
val sasTx = (pr?.transactionId ?: args.verificationId)?.let {
|
val sasTx = (pr?.transactionId ?: args.verificationId)?.let {
|
||||||
session.getVerificationService().getExistingTransaction(args.otherUserId, it) as? SasVerificationTransaction
|
session.getVerificationService().getExistingTransaction(args.otherUserId, it) as? SasVerificationTransaction
|
||||||
|
@ -105,9 +112,6 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(@Assisted ini
|
||||||
session.getVerificationService().getExistingTransaction(args.otherUserId, it) as? QrCodeVerificationTransaction
|
session.getVerificationService().getExistingTransaction(args.otherUserId, it) as? QrCodeVerificationTransaction
|
||||||
}
|
}
|
||||||
|
|
||||||
val isWaitingForOtherMode = args.waitForIncomingRequest
|
|
||||||
// TODO see if active tx for this user and take it
|
|
||||||
|
|
||||||
return fragment.verificationViewModelFactory.create(VerificationBottomSheetViewState(
|
return fragment.verificationViewModelFactory.create(VerificationBottomSheetViewState(
|
||||||
otherUserMxItem = userItem?.toMatrixItem(),
|
otherUserMxItem = userItem?.toMatrixItem(),
|
||||||
sasTransactionState = sasTx?.state,
|
sasTransactionState = sasTx?.state,
|
||||||
|
@ -177,16 +181,24 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(@Assisted ini
|
||||||
is VerificationAction.StartSASVerification -> {
|
is VerificationAction.StartSASVerification -> {
|
||||||
val request = session.getVerificationService().getExistingVerificationRequest(otherUserId, action.pendingRequestTransactionId)
|
val request = session.getVerificationService().getExistingVerificationRequest(otherUserId, action.pendingRequestTransactionId)
|
||||||
?: return@withState
|
?: return@withState
|
||||||
if (roomId == null) 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
|
||||||
session.getVerificationService().beginKeyVerificationInDMs(
|
if (roomId == null) {
|
||||||
VerificationMethod.SAS,
|
session.getVerificationService().beginKeyVerification(
|
||||||
transactionId = action.pendingRequestTransactionId,
|
VerificationMethod.SAS,
|
||||||
roomId = roomId,
|
otherUserId = request.otherUserId,
|
||||||
otherUserId = request.otherUserId,
|
otherDeviceId = otherDevice ?: "",
|
||||||
otherDeviceId = otherDevice ?: "",
|
transactionId = action.pendingRequestTransactionId
|
||||||
callback = null
|
)
|
||||||
)
|
} else {
|
||||||
|
session.getVerificationService().beginKeyVerificationInDMs(
|
||||||
|
VerificationMethod.SAS,
|
||||||
|
transactionId = action.pendingRequestTransactionId,
|
||||||
|
roomId = roomId,
|
||||||
|
otherUserId = request.otherUserId,
|
||||||
|
otherDeviceId = otherDevice ?: "",
|
||||||
|
callback = null
|
||||||
|
)
|
||||||
|
}
|
||||||
Unit
|
Unit
|
||||||
}
|
}
|
||||||
is VerificationAction.RemoteQrCodeScanned -> {
|
is VerificationAction.RemoteQrCodeScanned -> {
|
||||||
|
@ -194,11 +206,6 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(@Assisted ini
|
||||||
.getExistingTransaction(action.otherUserId, action.transactionId) as? QrCodeVerificationTransaction
|
.getExistingTransaction(action.otherUserId, action.transactionId) as? QrCodeVerificationTransaction
|
||||||
existingTransaction
|
existingTransaction
|
||||||
?.userHasScannedOtherQrCode(action.scannedData)
|
?.userHasScannedOtherQrCode(action.scannedData)
|
||||||
?.let { cancelCode ->
|
|
||||||
// Something went wrong
|
|
||||||
Timber.w("## Something is not right: $cancelCode")
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
is VerificationAction.OtherUserScannedSuccessfully -> {
|
is VerificationAction.OtherUserScannedSuccessfully -> {
|
||||||
val transactionId = state.transactionId ?: return@withState
|
val transactionId = state.transactionId ?: return@withState
|
||||||
|
|
|
@ -100,7 +100,7 @@ class DeviceListBottomSheetViewModel @AssistedInject constructor(@Assisted priva
|
||||||
}
|
}
|
||||||
|
|
||||||
fun manuallyVerify(device: CryptoDeviceInfo) {
|
fun manuallyVerify(device: CryptoDeviceInfo) {
|
||||||
session.getVerificationService().beginKeyVerification(VerificationMethod.SAS, userId, device.deviceId)?.let { txID ->
|
session.getVerificationService().beginKeyVerification(VerificationMethod.SAS, userId, device.deviceId, null)?.let { txID ->
|
||||||
_requestLiveData.postValue(LiveEvent(Success(VerificationAction.StartSASVerification(userId, txID))))
|
_requestLiveData.postValue(LiveEvent(Success(VerificationAction.StartSASVerification(userId, txID))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,9 +33,8 @@ import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.failure.Failure
|
import im.vector.matrix.android.api.failure.Failure
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
import im.vector.matrix.android.api.session.crypto.sas.VerificationService
|
import im.vector.matrix.android.api.session.crypto.sas.VerificationService
|
||||||
import im.vector.matrix.android.api.session.crypto.sas.VerificationTxState
|
|
||||||
import im.vector.matrix.android.api.session.crypto.sas.VerificationMethod
|
|
||||||
import im.vector.matrix.android.api.session.crypto.sas.VerificationTransaction
|
import im.vector.matrix.android.api.session.crypto.sas.VerificationTransaction
|
||||||
|
import im.vector.matrix.android.api.session.crypto.sas.VerificationTxState
|
||||||
import im.vector.matrix.android.internal.auth.data.LoginFlowTypes
|
import im.vector.matrix.android.internal.auth.data.LoginFlowTypes
|
||||||
import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo
|
import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo
|
||||||
import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
|
import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
|
||||||
|
@ -44,6 +43,7 @@ import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse
|
||||||
import im.vector.riotx.core.extensions.postLiveEvent
|
import im.vector.riotx.core.extensions.postLiveEvent
|
||||||
import im.vector.riotx.core.platform.VectorViewModel
|
import im.vector.riotx.core.platform.VectorViewModel
|
||||||
import im.vector.riotx.core.utils.LiveEvent
|
import im.vector.riotx.core.utils.LiveEvent
|
||||||
|
import im.vector.riotx.features.crypto.verification.supportedVerificationMethods
|
||||||
|
|
||||||
data class DevicesViewState(
|
data class DevicesViewState(
|
||||||
val myDeviceId: String = "",
|
val myDeviceId: String = "",
|
||||||
|
@ -96,9 +96,9 @@ class DevicesViewModel @AssistedInject constructor(@Assisted initialState: Devic
|
||||||
|
|
||||||
override fun transactionCreated(tx: VerificationTransaction) {}
|
override fun transactionCreated(tx: VerificationTransaction) {}
|
||||||
override fun transactionUpdated(tx: VerificationTransaction) {
|
override fun transactionUpdated(tx: VerificationTransaction) {
|
||||||
if (tx.state == VerificationTxState.Verified) {
|
if (tx.state == VerificationTxState.Verified) {
|
||||||
refreshDevicesList()
|
refreshDevicesList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -168,16 +168,13 @@ class DevicesViewModel @AssistedInject constructor(@Assisted initialState: Devic
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleVerify(action: DevicesAction.VerifyMyDevice) {
|
private fun handleVerify(action: DevicesAction.VerifyMyDevice) {
|
||||||
// TODO Implement request in to DEVICE!!!
|
val txID = session.getVerificationService().requestKeyVerification(supportedVerificationMethods, session.myUserId, listOf(action.deviceId))
|
||||||
val txID = session.getVerificationService().beginKeyVerification(VerificationMethod.SAS, session.myUserId, action.deviceId)
|
_requestLiveData.postValue(LiveEvent(Success(
|
||||||
if (txID != null) {
|
action.copy(
|
||||||
_requestLiveData.postValue(LiveEvent(Success(
|
userId = session.myUserId,
|
||||||
action.copy(
|
transactionId = txID.transactionId
|
||||||
userId = session.myUserId,
|
)
|
||||||
transactionId = txID
|
)))
|
||||||
)
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handlePromptRename(action: DevicesAction.PromptRename) = withState { state ->
|
private fun handlePromptRename(action: DevicesAction.PromptRename) = withState { state ->
|
||||||
|
|
Loading…
Reference in New Issue