Merge pull request #9 from poljar/feature/fga/device_verification
Feature/fga/device verification
This commit is contained in:
commit
e519561edf
|
@ -503,7 +503,6 @@ class E2eeSanityTests : InstrumentedTest {
|
||||||
|
|
||||||
// now let new session request
|
// now let new session request
|
||||||
newBobSession.cryptoService().reRequestRoomKeyForEvent(firstEventNewBobPov.root)
|
newBobSession.cryptoService().reRequestRoomKeyForEvent(firstEventNewBobPov.root)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to wait for the key request to be sent out and then a reply to be received
|
// We need to wait for the key request to be sent out and then a reply to be received
|
||||||
|
|
|
@ -140,13 +140,13 @@ class KeyShareTests : InstrumentedTest {
|
||||||
Log.v("TEST", "Incoming request Session 1 (looking for $outGoingRequestId)")
|
Log.v("TEST", "Incoming request Session 1 (looking for $outGoingRequestId)")
|
||||||
Log.v("TEST", "=========================")
|
Log.v("TEST", "=========================")
|
||||||
it.forEach { keyRequest ->
|
it.forEach { keyRequest ->
|
||||||
//Log.v("TEST", "[ts${keyRequest.localCreationTimestamp}] requestId ${keyRequest.requestId}, for sessionId ${keyRequest.requestBody?.sessionId} is ${keyRequest.state}")
|
// Log.v("TEST", "[ts${keyRequest.localCreationTimestamp}] requestId ${keyRequest.requestId}, for sessionId ${keyRequest.requestBody?.sessionId} is ${keyRequest.state}")
|
||||||
}
|
}
|
||||||
Log.v("TEST", "=========================")
|
Log.v("TEST", "=========================")
|
||||||
}
|
}
|
||||||
|
|
||||||
//val incoming = aliceSession.cryptoService().getIncomingRoomKeyRequests().firstOrNull { it.requestId == outGoingRequestId }
|
// val incoming = aliceSession.cryptoService().getIncomingRoomKeyRequests().firstOrNull { it.requestId == outGoingRequestId }
|
||||||
//incoming?.state == GossipingRequestState.REJECTED
|
// incoming?.state == GossipingRequestState.REJECTED
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -175,7 +175,7 @@ class KeyShareTests : InstrumentedTest {
|
||||||
Log.v("TEST", "Incoming request Session 1")
|
Log.v("TEST", "Incoming request Session 1")
|
||||||
Log.v("TEST", "=========================")
|
Log.v("TEST", "=========================")
|
||||||
it.forEach {
|
it.forEach {
|
||||||
//Log.v("TEST", "requestId ${it.requestId}, for sessionId ${it.requestBody?.sessionId} is ${it.state}")
|
// Log.v("TEST", "requestId ${it.requestId}, for sessionId ${it.requestBody?.sessionId} is ${it.state}")
|
||||||
}
|
}
|
||||||
Log.v("TEST", "=========================")
|
Log.v("TEST", "=========================")
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ class KeyShareTests : InstrumentedTest {
|
||||||
commonTestHelper.waitWithLatch { latch ->
|
commonTestHelper.waitWithLatch { latch ->
|
||||||
commonTestHelper.retryPeriodicallyWithLatch(latch) {
|
commonTestHelper.retryPeriodicallyWithLatch(latch) {
|
||||||
aliceSession2.cryptoService().getOutgoingRoomKeyRequests().let {
|
aliceSession2.cryptoService().getOutgoingRoomKeyRequests().let {
|
||||||
true//it.any { it.requestBody?.sessionId == eventMegolmSessionId && it.state == OutgoingGossipingRequestState.CANCELLED }
|
true // it.any { it.requestBody?.sessionId == eventMegolmSessionId && it.state == OutgoingGossipingRequestState.CANCELLED }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,7 +140,7 @@ class WithHeldTests : InstrumentedTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore("This test will be ignored until it is fixed")
|
@Ignore("This test will be ignored until it is fixed")
|
||||||
fun test_WithHeldNoOlm() {
|
fun test_WithHeldNoOlm() {
|
||||||
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
||||||
val aliceSession = testData.firstSession
|
val aliceSession = testData.firstSession
|
||||||
val bobSession = testData.secondSession!!
|
val bobSession = testData.secondSession!!
|
||||||
|
|
|
@ -41,7 +41,6 @@ import org.matrix.android.sdk.api.session.crypto.verification.VerificationServic
|
||||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction
|
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction
|
||||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState
|
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState
|
||||||
import org.matrix.android.sdk.api.session.events.model.Event
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
import org.matrix.android.sdk.api.session.getRoom
|
|
||||||
import org.matrix.android.sdk.common.CommonTestHelper
|
import org.matrix.android.sdk.common.CommonTestHelper
|
||||||
import org.matrix.android.sdk.common.CryptoTestHelper
|
import org.matrix.android.sdk.common.CryptoTestHelper
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
@ -325,6 +324,7 @@ class SASTest : InstrumentedTest {
|
||||||
// any two devices may only have at most one key verification in flight at a time.
|
// any two devices may only have at most one key verification in flight at a time.
|
||||||
// If a device has two verifications in progress with the same device, then it should cancel both verifications.
|
// If a device has two verifications in progress with the same device, then it should cancel both verifications.
|
||||||
@Test
|
@Test
|
||||||
|
@Ignore("verifications are not canceled when sending new events")
|
||||||
fun test_aliceStartTwoRequests() {
|
fun test_aliceStartTwoRequests() {
|
||||||
val testHelper = CommonTestHelper(context())
|
val testHelper = CommonTestHelper(context())
|
||||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
||||||
|
@ -570,8 +570,11 @@ class SASTest : InstrumentedTest {
|
||||||
val aliceSession = cryptoTestData.firstSession
|
val aliceSession = cryptoTestData.firstSession
|
||||||
val bobSession = cryptoTestData.secondSession
|
val bobSession = cryptoTestData.secondSession
|
||||||
|
|
||||||
|
cryptoTestHelper.initializeCrossSigning(aliceSession)
|
||||||
|
cryptoTestHelper.initializeCrossSigning(bobSession!!)
|
||||||
|
|
||||||
val aliceVerificationService = aliceSession.cryptoService().verificationService()
|
val aliceVerificationService = aliceSession.cryptoService().verificationService()
|
||||||
val bobVerificationService = bobSession!!.cryptoService().verificationService()
|
val bobVerificationService = bobSession.cryptoService().verificationService()
|
||||||
|
|
||||||
val req = testHelper.runBlockingTest {
|
val req = testHelper.runBlockingTest {
|
||||||
aliceVerificationService.requestKeyVerificationInDMs(
|
aliceVerificationService.requestKeyVerificationInDMs(
|
||||||
|
@ -621,16 +624,16 @@ class SASTest : InstrumentedTest {
|
||||||
|
|
||||||
// Start concurrent!
|
// Start concurrent!
|
||||||
testHelper.runBlockingTest {
|
testHelper.runBlockingTest {
|
||||||
aliceVerificationService.requestKeyVerificationInDMs(
|
aliceVerificationService.beginKeyVerification(
|
||||||
methods = listOf(VerificationMethod.SAS),
|
method = VerificationMethod.SAS,
|
||||||
otherUserId = bobSession.myUserId,
|
otherUserId = bobSession.myUserId,
|
||||||
roomId = cryptoTestData.roomId
|
transactionId = requestID!!,
|
||||||
)
|
)
|
||||||
|
|
||||||
bobVerificationService.requestKeyVerificationInDMs(
|
bobVerificationService.beginKeyVerification(
|
||||||
methods = listOf(VerificationMethod.SAS),
|
method = VerificationMethod.SAS,
|
||||||
otherUserId = aliceSession.myUserId,
|
otherUserId = aliceSession.myUserId,
|
||||||
roomId = cryptoTestData.roomId
|
transactionId = requestID!!,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,6 @@ class SasVerificationTestHelper(private val testHelper: CommonTestHelper, privat
|
||||||
}
|
}
|
||||||
|
|
||||||
fun requestSelfKeyAndWaitForReadyState(session1: Session, session2: Session, supportedMethods: List<VerificationMethod>): String {
|
fun requestSelfKeyAndWaitForReadyState(session1: Session, session2: Session, supportedMethods: List<VerificationMethod>): String {
|
||||||
|
|
||||||
val session1VerificationService = session1.cryptoService().verificationService()
|
val session1VerificationService = session1.cryptoService().verificationService()
|
||||||
val session2VerificationService = session2.cryptoService().verificationService()
|
val session2VerificationService = session2.cryptoService().verificationService()
|
||||||
var bobReadyPendingVerificationRequest: PendingVerificationRequest? = null
|
var bobReadyPendingVerificationRequest: PendingVerificationRequest? = null
|
||||||
|
|
|
@ -108,7 +108,6 @@ class MXUsersDevicesMap<E> {
|
||||||
map.putAll(other)
|
map.putAll(other)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add entries from another MXUsersDevicesMap
|
* Add entries from another MXUsersDevicesMap
|
||||||
*
|
*
|
||||||
|
|
|
@ -45,6 +45,17 @@ interface VerificationService {
|
||||||
|
|
||||||
fun getExistingVerificationRequestInRoom(roomId: String, tid: String?): PendingVerificationRequest?
|
fun getExistingVerificationRequestInRoom(roomId: String, tid: String?): PendingVerificationRequest?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request an interactive verification to begin
|
||||||
|
*
|
||||||
|
* This sends out a m.key.verification.request event over to-device messaging to
|
||||||
|
* to this device.
|
||||||
|
*
|
||||||
|
* If no specific device should be verified, but we would like to request
|
||||||
|
* verification from all our devices, use [requestSelfKeyVerification] instead.
|
||||||
|
*/
|
||||||
|
suspend fun requestDeviceVerification(methods: List<VerificationMethod>, otherUserId: String, otherDeviceId: String): PendingVerificationRequest?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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).
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -30,5 +30,4 @@ internal data class MessageVerificationAcceptContent(
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val transactionId: String? = relatesTo?.eventId
|
val transactionId: String? = relatesTo?.eventId
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ package org.matrix.android.sdk.api.session.room.model.message
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
import org.matrix.android.sdk.api.session.events.model.Content
|
import org.matrix.android.sdk.api.session.events.model.Content
|
||||||
import org.matrix.android.sdk.api.session.events.model.toContent
|
|
||||||
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
|
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
|
||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
|
@ -36,4 +35,3 @@ data class MessageVerificationRequestContent(
|
||||||
// Not parsed, but set after, using the eventId
|
// Not parsed, but set after, using the eventId
|
||||||
val transactionId: String? = null
|
val transactionId: String? = null
|
||||||
) : MessageContent
|
) : MessageContent
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022 New Vector Ltd
|
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
|
@ -759,7 +759,7 @@ internal class DefaultCryptoService @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun manuallyAcceptRoomKeyRequest(request: IncomingRoomKeyRequest) {
|
override suspend fun manuallyAcceptRoomKeyRequest(request: IncomingRoomKeyRequest) {
|
||||||
//TODO rust?
|
// TODO rust?
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getIncomingRoomKeyRequests(): List<IncomingRoomKeyRequest> {
|
override fun getIncomingRoomKeyRequests(): List<IncomingRoomKeyRequest> {
|
||||||
|
|
|
@ -24,11 +24,13 @@ import org.matrix.android.sdk.api.session.crypto.model.UnsignedDeviceInfo
|
||||||
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
|
||||||
import org.matrix.android.sdk.internal.crypto.network.RequestSender
|
import org.matrix.android.sdk.internal.crypto.network.RequestSender
|
||||||
|
import org.matrix.android.sdk.internal.crypto.verification.SasVerification
|
||||||
|
import org.matrix.android.sdk.internal.crypto.verification.VerificationRequest
|
||||||
|
import org.matrix.android.sdk.internal.crypto.verification.VerificationRequestFactory
|
||||||
import org.matrix.android.sdk.internal.crypto.verification.prepareMethods
|
import org.matrix.android.sdk.internal.crypto.verification.prepareMethods
|
||||||
import uniffi.olm.CryptoStoreException
|
import uniffi.olm.CryptoStoreException
|
||||||
import uniffi.olm.OlmMachine
|
import uniffi.olm.OlmMachine
|
||||||
import uniffi.olm.SignatureException
|
import uniffi.olm.SignatureException
|
||||||
import uniffi.olm.VerificationRequest
|
|
||||||
import uniffi.olm.Device as InnerDevice
|
import uniffi.olm.Device as InnerDevice
|
||||||
|
|
||||||
/** Class representing a device that supports E2EE in the Matrix world
|
/** Class representing a device that supports E2EE in the Matrix world
|
||||||
|
@ -37,20 +39,21 @@ import uniffi.olm.Device as InnerDevice
|
||||||
* or to manually verify the device.
|
* or to manually verify the device.
|
||||||
*/
|
*/
|
||||||
internal class Device(
|
internal class Device(
|
||||||
private val machine: OlmMachine,
|
private val innerMachine: OlmMachine,
|
||||||
private var inner: InnerDevice,
|
private var innerDevice: InnerDevice,
|
||||||
private val sender: RequestSender,
|
private val requestSender: RequestSender,
|
||||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||||
private val listeners: ArrayList<VerificationService.Listener>
|
private val listeners: ArrayList<VerificationService.Listener>,
|
||||||
|
private val verificationRequestFactory: VerificationRequestFactory,
|
||||||
) {
|
) {
|
||||||
@Throws(CryptoStoreException::class)
|
@Throws(CryptoStoreException::class)
|
||||||
private suspend fun refreshData() {
|
private suspend fun refreshData() {
|
||||||
val device = withContext(coroutineDispatchers.io) {
|
val device = withContext(coroutineDispatchers.io) {
|
||||||
machine.getDevice(inner.userId, inner.deviceId)
|
innerMachine.getDevice(innerDevice.userId, innerDevice.deviceId)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device != null) {
|
if (device != null) {
|
||||||
inner = device
|
innerDevice = device
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,12 +72,11 @@ internal class Device(
|
||||||
suspend fun requestVerification(methods: List<VerificationMethod>): VerificationRequest? {
|
suspend fun requestVerification(methods: List<VerificationMethod>): VerificationRequest? {
|
||||||
val stringMethods = prepareMethods(methods)
|
val stringMethods = prepareMethods(methods)
|
||||||
val result = withContext(coroutineDispatchers.io) {
|
val result = withContext(coroutineDispatchers.io) {
|
||||||
machine.requestVerificationWithDevice(inner.userId, inner.deviceId, stringMethods)
|
innerMachine.requestVerificationWithDevice(innerDevice.userId, innerDevice.deviceId, stringMethods)
|
||||||
}
|
}
|
||||||
|
|
||||||
return if (result != null) {
|
return if (result != null) {
|
||||||
sender.sendVerificationRequest(result.request)
|
requestSender.sendVerificationRequest(result.request)
|
||||||
result.verification
|
verificationRequestFactory.create(result.verification)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
@ -92,15 +94,15 @@ internal class Device(
|
||||||
@Throws(CryptoStoreException::class)
|
@Throws(CryptoStoreException::class)
|
||||||
suspend fun startVerification(): SasVerification? {
|
suspend fun startVerification(): SasVerification? {
|
||||||
val result = withContext(coroutineDispatchers.io) {
|
val result = withContext(coroutineDispatchers.io) {
|
||||||
machine.startSasWithDevice(inner.userId, inner.deviceId)
|
innerMachine.startSasWithDevice(innerDevice.userId, innerDevice.deviceId)
|
||||||
}
|
}
|
||||||
|
|
||||||
return if (result != null) {
|
return if (result != null) {
|
||||||
sender.sendVerificationRequest(result.request)
|
requestSender.sendVerificationRequest(result.request)
|
||||||
SasVerification(
|
SasVerification(
|
||||||
machine = machine,
|
machine = innerMachine,
|
||||||
inner = result.sas,
|
inner = result.sas,
|
||||||
sender = sender,
|
sender = requestSender,
|
||||||
coroutineDispatchers = coroutineDispatchers,
|
coroutineDispatchers = coroutineDispatchers,
|
||||||
listeners = listeners
|
listeners = listeners
|
||||||
)
|
)
|
||||||
|
@ -118,7 +120,7 @@ internal class Device(
|
||||||
@Throws(CryptoStoreException::class)
|
@Throws(CryptoStoreException::class)
|
||||||
suspend fun markAsTrusted() {
|
suspend fun markAsTrusted() {
|
||||||
withContext(coroutineDispatchers.io) {
|
withContext(coroutineDispatchers.io) {
|
||||||
machine.markDeviceAsTrusted(inner.userId, inner.deviceId)
|
innerMachine.markDeviceAsTrusted(innerDevice.userId, innerDevice.deviceId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,10 +136,10 @@ internal class Device(
|
||||||
@Throws(SignatureException::class)
|
@Throws(SignatureException::class)
|
||||||
suspend fun verify(): Boolean {
|
suspend fun verify(): Boolean {
|
||||||
val request = withContext(coroutineDispatchers.io) {
|
val request = withContext(coroutineDispatchers.io) {
|
||||||
machine.verifyDevice(inner.userId, inner.deviceId)
|
innerMachine.verifyDevice(innerDevice.userId, innerDevice.deviceId)
|
||||||
}
|
}
|
||||||
|
|
||||||
sender.sendSignatureUpload(request)
|
requestSender.sendSignatureUpload(request)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -148,7 +150,7 @@ internal class Device(
|
||||||
@Throws(CryptoStoreException::class)
|
@Throws(CryptoStoreException::class)
|
||||||
suspend fun trustLevel(): DeviceTrustLevel {
|
suspend fun trustLevel(): DeviceTrustLevel {
|
||||||
refreshData()
|
refreshData()
|
||||||
return DeviceTrustLevel(crossSigningVerified = inner.crossSigningTrusted, locallyVerified = inner.locallyTrusted)
|
return DeviceTrustLevel(crossSigningVerified = innerDevice.crossSigningTrusted, locallyVerified = innerDevice.locallyTrusted)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -157,19 +159,19 @@ internal class Device(
|
||||||
* This will not fetch out fresh data from the Rust side.
|
* This will not fetch out fresh data from the Rust side.
|
||||||
**/
|
**/
|
||||||
internal fun toCryptoDeviceInfo(): CryptoDeviceInfo {
|
internal fun toCryptoDeviceInfo(): CryptoDeviceInfo {
|
||||||
val keys = inner.keys.map { (keyId, key) -> "$keyId:$inner.deviceId" to key }.toMap()
|
val keys = innerDevice.keys.map { (keyId, key) -> "$keyId:$innerDevice.deviceId" to key }.toMap()
|
||||||
|
|
||||||
return CryptoDeviceInfo(
|
return CryptoDeviceInfo(
|
||||||
deviceId = inner.deviceId,
|
deviceId = innerDevice.deviceId,
|
||||||
userId = inner.userId,
|
userId = innerDevice.userId,
|
||||||
algorithms = inner.algorithms,
|
algorithms = innerDevice.algorithms,
|
||||||
keys = keys,
|
keys = keys,
|
||||||
// The Kotlin side doesn't need to care about signatures,
|
// The Kotlin side doesn't need to care about signatures,
|
||||||
// so we're not filling this out
|
// so we're not filling this out
|
||||||
signatures = mapOf(),
|
signatures = mapOf(),
|
||||||
unsigned = UnsignedDeviceInfo(inner.displayName),
|
unsigned = UnsignedDeviceInfo(innerDevice.displayName),
|
||||||
trustLevel = DeviceTrustLevel(crossSigningVerified = inner.crossSigningTrusted, locallyVerified = inner.locallyTrusted),
|
trustLevel = DeviceTrustLevel(crossSigningVerified = innerDevice.crossSigningTrusted, locallyVerified = innerDevice.locallyTrusted),
|
||||||
isBlocked = inner.isBlocked,
|
isBlocked = innerDevice.isBlocked,
|
||||||
// TODO
|
// TODO
|
||||||
firstTimeSeenLocalTs = null)
|
firstTimeSeenLocalTs = null)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022 New Vector Ltd
|
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022 New Vector Ltd
|
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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 org.matrix.android.sdk.internal.crypto
|
||||||
|
|
||||||
|
import com.squareup.moshi.Moshi
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
||||||
|
import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel
|
||||||
|
import org.matrix.android.sdk.internal.crypto.model.rest.RestKeyInfo
|
||||||
|
import org.matrix.android.sdk.internal.crypto.network.RequestSender
|
||||||
|
import org.matrix.android.sdk.internal.crypto.verification.VerificationRequestFactory
|
||||||
|
import uniffi.olm.CryptoStoreException
|
||||||
|
import uniffi.olm.OlmMachine
|
||||||
|
|
||||||
|
internal class GetUserIdentityUseCase(
|
||||||
|
private val innerMachine: OlmMachine,
|
||||||
|
private val requestSender: RequestSender,
|
||||||
|
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||||
|
private val moshi: Moshi,
|
||||||
|
private val verificationRequestFactory: VerificationRequestFactory
|
||||||
|
) {
|
||||||
|
|
||||||
|
@Throws(CryptoStoreException::class)
|
||||||
|
suspend operator fun invoke(userId: String): UserIdentities? {
|
||||||
|
val identity = withContext(coroutineDispatchers.io) {
|
||||||
|
innerMachine.getIdentity(userId)
|
||||||
|
}
|
||||||
|
val adapter = moshi.adapter(RestKeyInfo::class.java)
|
||||||
|
|
||||||
|
return when (identity) {
|
||||||
|
is uniffi.olm.UserIdentity.Other -> {
|
||||||
|
val verified = innerMachine.isIdentityVerified(userId)
|
||||||
|
val masterKey = adapter.fromJson(identity.masterKey)!!.toCryptoModel().apply {
|
||||||
|
trustLevel = DeviceTrustLevel(verified, verified)
|
||||||
|
}
|
||||||
|
val selfSigningKey = adapter.fromJson(identity.selfSigningKey)!!.toCryptoModel().apply {
|
||||||
|
trustLevel = DeviceTrustLevel(verified, verified)
|
||||||
|
}
|
||||||
|
UserIdentity(
|
||||||
|
userId = identity.userId,
|
||||||
|
masterKey = masterKey,
|
||||||
|
selfSigningKey = selfSigningKey,
|
||||||
|
innerMachine = innerMachine,
|
||||||
|
requestSender = requestSender,
|
||||||
|
coroutineDispatchers = coroutineDispatchers,
|
||||||
|
verificationRequestFactory = verificationRequestFactory
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is uniffi.olm.UserIdentity.Own -> {
|
||||||
|
val verified = innerMachine.isIdentityVerified(userId)
|
||||||
|
|
||||||
|
val masterKey = adapter.fromJson(identity.masterKey)!!.toCryptoModel().apply {
|
||||||
|
trustLevel = DeviceTrustLevel(verified, verified)
|
||||||
|
}
|
||||||
|
val selfSigningKey = adapter.fromJson(identity.selfSigningKey)!!.toCryptoModel().apply {
|
||||||
|
trustLevel = DeviceTrustLevel(verified, verified)
|
||||||
|
}
|
||||||
|
val userSigningKey = adapter.fromJson(identity.userSigningKey)!!.toCryptoModel()
|
||||||
|
|
||||||
|
OwnUserIdentity(
|
||||||
|
userId = identity.userId,
|
||||||
|
masterKey = masterKey,
|
||||||
|
selfSigningKey = selfSigningKey,
|
||||||
|
userSigningKey = userSigningKey,
|
||||||
|
trustsOurOwnDevice = identity.trustsOurOwnDevice,
|
||||||
|
innerMachine = innerMachine,
|
||||||
|
requestSender = requestSender,
|
||||||
|
coroutineDispatchers = coroutineDispatchers,
|
||||||
|
verificationRequestFactory = verificationRequestFactory
|
||||||
|
)
|
||||||
|
}
|
||||||
|
null -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -49,9 +49,13 @@ import org.matrix.android.sdk.api.util.JsonDict
|
||||||
import org.matrix.android.sdk.api.util.Optional
|
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 org.matrix.android.sdk.internal.coroutines.builder.safeInvokeOnClose
|
import org.matrix.android.sdk.internal.coroutines.builder.safeInvokeOnClose
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.RestKeyInfo
|
|
||||||
import org.matrix.android.sdk.internal.crypto.network.RequestSender
|
import org.matrix.android.sdk.internal.crypto.network.RequestSender
|
||||||
|
import org.matrix.android.sdk.internal.crypto.verification.SasVerification
|
||||||
|
import org.matrix.android.sdk.internal.crypto.verification.VerificationRequest
|
||||||
|
import org.matrix.android.sdk.internal.crypto.verification.VerificationRequestFactory
|
||||||
|
import org.matrix.android.sdk.internal.crypto.verification.qrcode.QrCodeVerification
|
||||||
import org.matrix.android.sdk.internal.network.parsing.CheckNumberType
|
import org.matrix.android.sdk.internal.network.parsing.CheckNumberType
|
||||||
|
import org.matrix.android.sdk.internal.util.time.Clock
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import uniffi.olm.BackupKeys
|
import uniffi.olm.BackupKeys
|
||||||
import uniffi.olm.CrossSigningKeyExport
|
import uniffi.olm.CrossSigningKeyExport
|
||||||
|
@ -71,7 +75,6 @@ import java.nio.charset.Charset
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import uniffi.olm.OlmMachine as InnerMachine
|
import uniffi.olm.OlmMachine as InnerMachine
|
||||||
import uniffi.olm.ProgressListener as RustProgressListener
|
import uniffi.olm.ProgressListener as RustProgressListener
|
||||||
import uniffi.olm.UserIdentity as RustUserIdentity
|
|
||||||
|
|
||||||
class CryptoLogger : Logger {
|
class CryptoLogger : Logger {
|
||||||
override fun log(logLine: String) {
|
override fun log(logLine: String) {
|
||||||
|
@ -85,10 +88,11 @@ private class CryptoProgressListener(private val listener: ProgressListener?) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class UserIdentityCollector(val userId: String, val collector: SendChannel<Optional<MXCrossSigningInfo>>)
|
private data class UserIdentityCollector(val userId: String, val collector: SendChannel<Optional<MXCrossSigningInfo>>) :
|
||||||
: SendChannel<Optional<MXCrossSigningInfo>> by collector
|
SendChannel<Optional<MXCrossSigningInfo>> by collector
|
||||||
private data class DevicesCollector(val userIds: List<String>, val collector: SendChannel<List<CryptoDeviceInfo>>)
|
|
||||||
: SendChannel<List<CryptoDeviceInfo>> by collector
|
private data class DevicesCollector(val userIds: List<String>, val collector: SendChannel<List<CryptoDeviceInfo>>) :
|
||||||
|
SendChannel<List<CryptoDeviceInfo>> by collector
|
||||||
private typealias PrivateKeysCollector = SendChannel<Optional<PrivateKeysInfo>>
|
private typealias PrivateKeysCollector = SendChannel<Optional<PrivateKeysInfo>>
|
||||||
|
|
||||||
private class FlowCollectors {
|
private class FlowCollectors {
|
||||||
|
@ -105,12 +109,16 @@ internal class OlmMachine(
|
||||||
user_id: String,
|
user_id: String,
|
||||||
device_id: String,
|
device_id: String,
|
||||||
path: File,
|
path: File,
|
||||||
|
clock: Clock,
|
||||||
private val requestSender: RequestSender,
|
private val requestSender: RequestSender,
|
||||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||||
private val moshi: Moshi
|
private val moshi: Moshi,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private val inner: InnerMachine = InnerMachine(user_id, device_id, path.toString(), null)
|
private val inner: InnerMachine = InnerMachine(user_id, device_id, path.toString(), null)
|
||||||
internal val verificationListeners = ArrayList<VerificationService.Listener>()
|
val verificationListeners = ArrayList<VerificationService.Listener>()
|
||||||
|
private val verificationRequestFactory = VerificationRequestFactory(inner, requestSender, coroutineDispatchers, verificationListeners, clock)
|
||||||
|
private val getUserIdentity = GetUserIdentityUseCase(inner, requestSender, coroutineDispatchers, moshi, verificationRequestFactory)
|
||||||
private val flowCollectors = FlowCollectors()
|
private val flowCollectors = FlowCollectors()
|
||||||
|
|
||||||
/** Get our own user ID. */
|
/** Get our own user ID. */
|
||||||
|
@ -176,7 +184,8 @@ internal class OlmMachine(
|
||||||
UnsignedDeviceInfo(),
|
UnsignedDeviceInfo(),
|
||||||
DeviceTrustLevel(crossSigningVerified, locallyVerified = true),
|
DeviceTrustLevel(crossSigningVerified, locallyVerified = true),
|
||||||
false,
|
false,
|
||||||
null)
|
null
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -389,13 +398,15 @@ internal class OlmMachine(
|
||||||
clearEvent,
|
clearEvent,
|
||||||
decrypted.senderCurve25519Key,
|
decrypted.senderCurve25519Key,
|
||||||
decrypted.claimedEd25519Key,
|
decrypted.claimedEd25519Key,
|
||||||
decrypted.forwardingCurve25519Chain)
|
decrypted.forwardingCurve25519Chain
|
||||||
|
)
|
||||||
} catch (throwable: Throwable) {
|
} catch (throwable: Throwable) {
|
||||||
val reason =
|
val reason =
|
||||||
String.format(
|
String.format(
|
||||||
MXCryptoError.UNABLE_TO_DECRYPT_REASON,
|
MXCryptoError.UNABLE_TO_DECRYPT_REASON,
|
||||||
throwable.message,
|
throwable.message,
|
||||||
"m.megolm.v1.aes-sha2")
|
"m.megolm.v1.aes-sha2"
|
||||||
|
)
|
||||||
throw MXCryptoError.Base(MXCryptoError.ErrorType.UNABLE_TO_DECRYPT, reason)
|
throw MXCryptoError.Base(MXCryptoError.ErrorType.UNABLE_TO_DECRYPT, reason)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -491,55 +502,7 @@ internal class OlmMachine(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(CryptoStoreException::class)
|
@Throws(CryptoStoreException::class)
|
||||||
suspend fun getIdentity(userId: String): UserIdentities? {
|
suspend fun getIdentity(userId: String): UserIdentities? = getUserIdentity(userId)
|
||||||
val identity = withContext(coroutineDispatchers.io) {
|
|
||||||
inner.getIdentity(userId)
|
|
||||||
}
|
|
||||||
val adapter = moshi.adapter(RestKeyInfo::class.java)
|
|
||||||
|
|
||||||
return when (identity) {
|
|
||||||
is RustUserIdentity.Other -> {
|
|
||||||
val verified = inner().isIdentityVerified(userId)
|
|
||||||
val masterKey = adapter.fromJson(identity.masterKey)!!.toCryptoModel().apply {
|
|
||||||
trustLevel = DeviceTrustLevel(verified, verified)
|
|
||||||
}
|
|
||||||
val selfSigningKey = adapter.fromJson(identity.selfSigningKey)!!.toCryptoModel().apply {
|
|
||||||
trustLevel = DeviceTrustLevel(verified, verified)
|
|
||||||
}
|
|
||||||
UserIdentity(
|
|
||||||
userId = identity.userId,
|
|
||||||
masterKey = masterKey,
|
|
||||||
selfSigningKey = selfSigningKey,
|
|
||||||
olmMachine = this,
|
|
||||||
requestSender = requestSender,
|
|
||||||
coroutineDispatchers = coroutineDispatchers
|
|
||||||
)
|
|
||||||
}
|
|
||||||
is RustUserIdentity.Own -> {
|
|
||||||
val verified = inner().isIdentityVerified(userId)
|
|
||||||
|
|
||||||
val masterKey = adapter.fromJson(identity.masterKey)!!.toCryptoModel().apply {
|
|
||||||
trustLevel = DeviceTrustLevel(verified, verified)
|
|
||||||
}
|
|
||||||
val selfSigningKey = adapter.fromJson(identity.selfSigningKey)!!.toCryptoModel().apply {
|
|
||||||
trustLevel = DeviceTrustLevel(verified, verified)
|
|
||||||
}
|
|
||||||
val userSigningKey = adapter.fromJson(identity.userSigningKey)!!.toCryptoModel()
|
|
||||||
|
|
||||||
OwnUserIdentity(
|
|
||||||
userId = identity.userId,
|
|
||||||
masterKey = masterKey,
|
|
||||||
selfSigningKey = selfSigningKey,
|
|
||||||
userSigningKey = userSigningKey,
|
|
||||||
trustsOurOwnDevice = identity.trustsOurOwnDevice,
|
|
||||||
olmMachine = this,
|
|
||||||
requestSender = requestSender,
|
|
||||||
coroutineDispatchers = coroutineDispatchers
|
|
||||||
)
|
|
||||||
}
|
|
||||||
null -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a `Device` from the store.
|
* Get a `Device` from the store.
|
||||||
|
@ -559,30 +522,16 @@ internal class OlmMachine(
|
||||||
|
|
||||||
@Throws(CryptoStoreException::class)
|
@Throws(CryptoStoreException::class)
|
||||||
suspend fun getDevice(userId: String, deviceId: String): Device? {
|
suspend fun getDevice(userId: String, deviceId: String): Device? {
|
||||||
val device = withContext(coroutineDispatchers.io) {
|
val innerDevice = withContext(coroutineDispatchers.io) {
|
||||||
inner.getDevice(userId, deviceId)
|
inner.getDevice(userId, deviceId)
|
||||||
} ?: return null
|
} ?: return null
|
||||||
|
|
||||||
return Device(
|
return innerDevice.wrap()
|
||||||
machine = inner,
|
|
||||||
inner = device,
|
|
||||||
sender = requestSender,
|
|
||||||
coroutineDispatchers = coroutineDispatchers,
|
|
||||||
listeners = verificationListeners
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getUserDevices(userId: String): List<Device> {
|
suspend fun getUserDevices(userId: String): List<Device> {
|
||||||
return withContext(coroutineDispatchers.io) {
|
return withContext(coroutineDispatchers.io) {
|
||||||
inner.getUserDevices(userId).map {
|
inner.getUserDevices(userId).map { innerDevice -> innerDevice.wrap() }
|
||||||
Device(
|
|
||||||
machine = inner,
|
|
||||||
inner = it,
|
|
||||||
sender = requestSender,
|
|
||||||
coroutineDispatchers = coroutineDispatchers,
|
|
||||||
listeners = verificationListeners
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -743,30 +692,13 @@ internal class OlmMachine(
|
||||||
* @return The list of [VerificationRequest] that we share with the given user
|
* @return The list of [VerificationRequest] that we share with the given user
|
||||||
*/
|
*/
|
||||||
fun getVerificationRequests(userId: String): List<VerificationRequest> {
|
fun getVerificationRequests(userId: String): List<VerificationRequest> {
|
||||||
return inner.getVerificationRequests(userId).map {
|
return inner.getVerificationRequests(userId).map(verificationRequestFactory::create)
|
||||||
VerificationRequest(
|
|
||||||
machine = inner,
|
|
||||||
inner = it,
|
|
||||||
sender = requestSender,
|
|
||||||
coroutineDispatchers = coroutineDispatchers,
|
|
||||||
listeners = verificationListeners,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get a verification request for the given user with the given flow ID */
|
/** Get a verification request for the given user with the given flow ID */
|
||||||
fun getVerificationRequest(userId: String, flowId: String): VerificationRequest? {
|
fun getVerificationRequest(userId: String, flowId: String): VerificationRequest? {
|
||||||
val request = inner.getVerificationRequest(userId, flowId)
|
return inner.getVerificationRequest(userId, flowId)?.let { innerVerificationRequest ->
|
||||||
return if (request != null) {
|
verificationRequestFactory.create(innerVerificationRequest)
|
||||||
VerificationRequest(
|
|
||||||
machine = inner,
|
|
||||||
inner = request,
|
|
||||||
sender = requestSender,
|
|
||||||
coroutineDispatchers = coroutineDispatchers,
|
|
||||||
listeners = verificationListeners,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -936,4 +868,13 @@ internal class OlmMachine(
|
||||||
inner.verifyBackup(serializedAuthData)
|
inner.verifyBackup(serializedAuthData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun uniffi.olm.Device.wrap() = Device(
|
||||||
|
innerMachine = inner,
|
||||||
|
innerDevice = this,
|
||||||
|
requestSender = requestSender,
|
||||||
|
coroutineDispatchers = coroutineDispatchers,
|
||||||
|
listeners = verificationListeners,
|
||||||
|
verificationRequestFactory = verificationRequestFactory
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,24 +23,30 @@ import org.matrix.android.sdk.internal.di.DeviceId
|
||||||
import org.matrix.android.sdk.internal.di.SessionFilesDirectory
|
import org.matrix.android.sdk.internal.di.SessionFilesDirectory
|
||||||
import org.matrix.android.sdk.internal.di.UserId
|
import org.matrix.android.sdk.internal.di.UserId
|
||||||
import org.matrix.android.sdk.internal.session.SessionScope
|
import org.matrix.android.sdk.internal.session.SessionScope
|
||||||
|
import org.matrix.android.sdk.internal.util.time.Clock
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@SessionScope
|
@SessionScope
|
||||||
internal class OlmMachineProvider @Inject constructor(
|
internal class OlmMachineProvider @Inject constructor(
|
||||||
@UserId private val userId: String,
|
@UserId userId: String,
|
||||||
@DeviceId private val deviceId: String?,
|
@DeviceId deviceId: String?,
|
||||||
@SessionFilesDirectory private val dataDir: File,
|
@SessionFilesDirectory dataDir: File,
|
||||||
requestSender: RequestSender,
|
requestSender: RequestSender,
|
||||||
coroutineDispatchers: MatrixCoroutineDispatchers,
|
coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||||
moshi: Moshi
|
moshi: Moshi,
|
||||||
|
clock: Clock
|
||||||
) {
|
) {
|
||||||
|
|
||||||
var olmMachine: OlmMachine = OlmMachine(
|
val olmMachine: OlmMachine by lazy {
|
||||||
user_id = userId,
|
OlmMachine(
|
||||||
device_id = deviceId!!,
|
user_id = userId,
|
||||||
path = dataDir,
|
device_id = deviceId!!,
|
||||||
requestSender = requestSender,
|
path = dataDir,
|
||||||
coroutineDispatchers = coroutineDispatchers,
|
clock = clock,
|
||||||
moshi = moshi)
|
requestSender = requestSender,
|
||||||
|
coroutineDispatchers = coroutineDispatchers,
|
||||||
|
moshi = moshi
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022 New Vector Ltd
|
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
|
@ -207,7 +207,7 @@ internal class RustCrossSigningService @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSecretUSKGossip(uskPrivateKey: String) {
|
override fun onSecretUSKGossip(uskPrivateKey: String) {
|
||||||
// And
|
// And
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun shieldForGroup(userIds: List<String>): RoomEncryptionTrustLevel {
|
override suspend fun shieldForGroup(userIds: List<String>): RoomEncryptionTrustLevel {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022 New Vector Ltd
|
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
|
@ -24,8 +24,11 @@ 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
|
||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
import org.matrix.android.sdk.internal.crypto.network.RequestSender
|
import org.matrix.android.sdk.internal.crypto.network.RequestSender
|
||||||
|
import org.matrix.android.sdk.internal.crypto.verification.VerificationRequest
|
||||||
|
import org.matrix.android.sdk.internal.crypto.verification.VerificationRequestFactory
|
||||||
import org.matrix.android.sdk.internal.crypto.verification.prepareMethods
|
import org.matrix.android.sdk.internal.crypto.verification.prepareMethods
|
||||||
import uniffi.olm.CryptoStoreException
|
import uniffi.olm.CryptoStoreException
|
||||||
|
import uniffi.olm.OlmMachine
|
||||||
import uniffi.olm.SignatureException
|
import uniffi.olm.SignatureException
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,9 +82,11 @@ internal class OwnUserIdentity(
|
||||||
private val selfSigningKey: CryptoCrossSigningKey,
|
private val selfSigningKey: CryptoCrossSigningKey,
|
||||||
private val userSigningKey: CryptoCrossSigningKey,
|
private val userSigningKey: CryptoCrossSigningKey,
|
||||||
private val trustsOurOwnDevice: Boolean,
|
private val trustsOurOwnDevice: Boolean,
|
||||||
private val olmMachine: OlmMachine,
|
private val innerMachine: OlmMachine,
|
||||||
private val requestSender: RequestSender,
|
private val requestSender: RequestSender,
|
||||||
private val coroutineDispatchers: MatrixCoroutineDispatchers) : UserIdentities() {
|
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||||
|
private val verificationRequestFactory: VerificationRequestFactory,
|
||||||
|
) : UserIdentities() {
|
||||||
/**
|
/**
|
||||||
* Our own user id.
|
* Our own user id.
|
||||||
*/
|
*/
|
||||||
|
@ -96,7 +101,7 @@ internal class OwnUserIdentity(
|
||||||
*/
|
*/
|
||||||
@Throws(SignatureException::class)
|
@Throws(SignatureException::class)
|
||||||
override suspend fun verify() {
|
override suspend fun verify() {
|
||||||
val request = withContext(coroutineDispatchers.computation) { olmMachine.inner().verifyIdentity(userId) }
|
val request = withContext(coroutineDispatchers.computation) { innerMachine.verifyIdentity(userId) }
|
||||||
requestSender.sendSignatureUpload(request)
|
requestSender.sendSignatureUpload(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +112,7 @@ internal class OwnUserIdentity(
|
||||||
*/
|
*/
|
||||||
@Throws(CryptoStoreException::class)
|
@Throws(CryptoStoreException::class)
|
||||||
override suspend fun verified(): Boolean {
|
override suspend fun verified(): Boolean {
|
||||||
return withContext(coroutineDispatchers.io) { olmMachine.inner().isIdentityVerified(userId) }
|
return withContext(coroutineDispatchers.io) { innerMachine.isIdentityVerified(userId) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -134,16 +139,9 @@ internal class OwnUserIdentity(
|
||||||
@Throws(CryptoStoreException::class)
|
@Throws(CryptoStoreException::class)
|
||||||
suspend fun requestVerification(methods: List<VerificationMethod>): VerificationRequest {
|
suspend fun requestVerification(methods: List<VerificationMethod>): VerificationRequest {
|
||||||
val stringMethods = prepareMethods(methods)
|
val stringMethods = prepareMethods(methods)
|
||||||
val result = olmMachine.inner().requestSelfVerification(stringMethods)
|
val result = innerMachine.requestSelfVerification(stringMethods)
|
||||||
requestSender.sendVerificationRequest(result!!.request)
|
requestSender.sendVerificationRequest(result!!.request)
|
||||||
|
return verificationRequestFactory.create(result.verification)
|
||||||
return VerificationRequest(
|
|
||||||
machine = olmMachine.inner(),
|
|
||||||
inner = result.verification,
|
|
||||||
sender = requestSender,
|
|
||||||
coroutineDispatchers = coroutineDispatchers,
|
|
||||||
listeners = olmMachine.verificationListeners
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -173,9 +171,11 @@ internal class UserIdentity(
|
||||||
private val userId: String,
|
private val userId: String,
|
||||||
private val masterKey: CryptoCrossSigningKey,
|
private val masterKey: CryptoCrossSigningKey,
|
||||||
private val selfSigningKey: CryptoCrossSigningKey,
|
private val selfSigningKey: CryptoCrossSigningKey,
|
||||||
private val olmMachine: OlmMachine,
|
private val innerMachine: OlmMachine,
|
||||||
private val requestSender: RequestSender,
|
private val requestSender: RequestSender,
|
||||||
private val coroutineDispatchers: MatrixCoroutineDispatchers) : UserIdentities() {
|
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||||
|
private val verificationRequestFactory: VerificationRequestFactory,
|
||||||
|
) : UserIdentities() {
|
||||||
/**
|
/**
|
||||||
* The unique ID of the user that this identity belongs to.
|
* The unique ID of the user that this identity belongs to.
|
||||||
*/
|
*/
|
||||||
|
@ -192,7 +192,7 @@ internal class UserIdentity(
|
||||||
*/
|
*/
|
||||||
@Throws(SignatureException::class)
|
@Throws(SignatureException::class)
|
||||||
override suspend fun verify() {
|
override suspend fun verify() {
|
||||||
val request = withContext(coroutineDispatchers.computation) { olmMachine.inner().verifyIdentity(userId) }
|
val request = withContext(coroutineDispatchers.computation) { innerMachine.verifyIdentity(userId) }
|
||||||
requestSender.sendSignatureUpload(request)
|
requestSender.sendSignatureUpload(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,7 +202,7 @@ internal class UserIdentity(
|
||||||
* @return True if the identity is considered to be verified and trusted, false otherwise.
|
* @return True if the identity is considered to be verified and trusted, false otherwise.
|
||||||
*/
|
*/
|
||||||
override suspend fun verified(): Boolean {
|
override suspend fun verified(): Boolean {
|
||||||
return withContext(coroutineDispatchers.io) { olmMachine.inner().isIdentityVerified(userId) }
|
return withContext(coroutineDispatchers.io) { innerMachine.isIdentityVerified(userId) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -235,19 +235,10 @@ internal class UserIdentity(
|
||||||
transactionId: String
|
transactionId: String
|
||||||
): VerificationRequest {
|
): VerificationRequest {
|
||||||
val stringMethods = prepareMethods(methods)
|
val stringMethods = prepareMethods(methods)
|
||||||
val content = olmMachine.inner().verificationRequestContent(userId, stringMethods)!!
|
val content = innerMachine.verificationRequestContent(userId, stringMethods)!!
|
||||||
|
|
||||||
val eventID = requestSender.sendRoomMessage(EventType.MESSAGE, roomId, content, transactionId).eventId
|
val eventID = requestSender.sendRoomMessage(EventType.MESSAGE, roomId, content, transactionId).eventId
|
||||||
|
val innerRequest = innerMachine.requestVerification(userId, roomId, eventID, stringMethods)!!
|
||||||
val innerRequest = olmMachine.inner().requestVerification(userId, roomId, eventID, stringMethods)!!
|
return verificationRequestFactory.create(innerRequest)
|
||||||
|
|
||||||
return VerificationRequest(
|
|
||||||
machine = olmMachine.inner(),
|
|
||||||
inner = innerRequest,
|
|
||||||
sender = requestSender,
|
|
||||||
coroutineDispatchers = coroutineDispatchers,
|
|
||||||
listeners = olmMachine.verificationListeners
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package org.matrix.android.sdk.internal.crypto.api
|
package org.matrix.android.sdk.internal.crypto.api
|
||||||
|
|
||||||
import org.matrix.android.sdk.api.util.JsonDict
|
|
||||||
import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
|
import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
|
||||||
import org.matrix.android.sdk.api.session.crypto.model.DevicesListResponse
|
import org.matrix.android.sdk.api.session.crypto.model.DevicesListResponse
|
||||||
|
import org.matrix.android.sdk.api.util.JsonDict
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.DeleteDeviceParams
|
import org.matrix.android.sdk.internal.crypto.model.rest.DeleteDeviceParams
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.KeyChangesResponse
|
import org.matrix.android.sdk.internal.crypto.model.rest.KeyChangesResponse
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.KeysClaimBody
|
import org.matrix.android.sdk.internal.crypto.model.rest.KeysClaimBody
|
||||||
|
|
|
@ -227,7 +227,7 @@ internal class RequestSender @Inject constructor(
|
||||||
getKeysBackupLastVersionTask.executeRetry(Unit, 3)
|
getKeysBackupLastVersionTask.executeRetry(Unit, 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun <reified T> getKeyBackupVersion(block: ()-> T?): T?{
|
private inline fun <reified T> getKeyBackupVersion(block: () -> T?): T? {
|
||||||
return try {
|
return try {
|
||||||
block()
|
block()
|
||||||
} catch (failure: Throwable) {
|
} catch (failure: Throwable) {
|
||||||
|
|
|
@ -30,7 +30,6 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageRelationCont
|
||||||
import org.matrix.android.sdk.api.session.room.model.message.MessageType
|
import org.matrix.android.sdk.api.session.room.model.message.MessageType
|
||||||
import org.matrix.android.sdk.internal.crypto.OlmMachineProvider
|
import org.matrix.android.sdk.internal.crypto.OlmMachineProvider
|
||||||
import org.matrix.android.sdk.internal.crypto.OwnUserIdentity
|
import org.matrix.android.sdk.internal.crypto.OwnUserIdentity
|
||||||
import org.matrix.android.sdk.internal.crypto.SasVerification
|
|
||||||
import org.matrix.android.sdk.internal.crypto.UserIdentity
|
import org.matrix.android.sdk.internal.crypto.UserIdentity
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_QR_CODE_SCAN
|
import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_QR_CODE_SCAN
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_QR_CODE_SHOW
|
import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_QR_CODE_SHOW
|
||||||
|
@ -254,6 +253,15 @@ internal class RustVerificationService @Inject constructor(private val olmMachin
|
||||||
return verification.toPendingVerificationRequest()
|
return verification.toPendingVerificationRequest()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun requestDeviceVerification(methods: List<VerificationMethod>,
|
||||||
|
otherUserId: String,
|
||||||
|
otherDeviceId: String): PendingVerificationRequest? {
|
||||||
|
olmMachine.ensureUsersKeys(listOf(otherUserId))
|
||||||
|
val otherDevice = olmMachine.getDevice(otherUserId, otherDeviceId)
|
||||||
|
val verificationRequest = otherDevice?.requestVerification(methods)
|
||||||
|
return verificationRequest?.toPendingVerificationRequest()
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun readyPendingVerification(
|
override suspend fun readyPendingVerification(
|
||||||
methods: List<VerificationMethod>,
|
methods: List<VerificationMethod>,
|
||||||
otherUserId: String,
|
otherUserId: String,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2021 The Matrix.org Foundation C.I.C.
|
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.matrix.android.sdk.internal.crypto
|
package org.matrix.android.sdk.internal.crypto.verification
|
||||||
|
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
||||||
|
@ -25,8 +25,6 @@ import org.matrix.android.sdk.api.session.crypto.verification.VerificationServic
|
||||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState
|
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState
|
||||||
import org.matrix.android.sdk.api.session.crypto.verification.safeValueOf
|
import org.matrix.android.sdk.api.session.crypto.verification.safeValueOf
|
||||||
import org.matrix.android.sdk.internal.crypto.network.RequestSender
|
import org.matrix.android.sdk.internal.crypto.network.RequestSender
|
||||||
import org.matrix.android.sdk.internal.crypto.verification.UpdateDispatcher
|
|
||||||
import org.matrix.android.sdk.internal.crypto.verification.getEmojiForCode
|
|
||||||
import uniffi.olm.CryptoStoreException
|
import uniffi.olm.CryptoStoreException
|
||||||
import uniffi.olm.OlmMachine
|
import uniffi.olm.OlmMachine
|
||||||
import uniffi.olm.Sas
|
import uniffi.olm.Sas
|
||||||
|
@ -235,6 +233,11 @@ internal class SasVerification(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "SasVerification(otherUserId='$otherUserId', otherDeviceId=$otherDeviceId, isIncoming=$isIncoming, state=$state, transactionId='$transactionId')"
|
return "SasVerification(" +
|
||||||
|
"otherUserId='$otherUserId', " +
|
||||||
|
"otherDeviceId=$otherDeviceId, " +
|
||||||
|
"isIncoming=$isIncoming, " +
|
||||||
|
"state=$state, " +
|
||||||
|
"transactionId='$transactionId')"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2021 The Matrix.org Foundation C.I.C.
|
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.matrix.android.sdk.internal.crypto
|
package org.matrix.android.sdk.internal.crypto.verification
|
||||||
|
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
|
@ -30,7 +30,8 @@ import org.matrix.android.sdk.api.session.crypto.verification.safeValueOf
|
||||||
import org.matrix.android.sdk.api.util.toBase64NoPadding
|
import org.matrix.android.sdk.api.util.toBase64NoPadding
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_QR_CODE_SCAN
|
import org.matrix.android.sdk.internal.crypto.model.rest.VERIFICATION_METHOD_QR_CODE_SCAN
|
||||||
import org.matrix.android.sdk.internal.crypto.network.RequestSender
|
import org.matrix.android.sdk.internal.crypto.network.RequestSender
|
||||||
import org.matrix.android.sdk.internal.crypto.verification.prepareMethods
|
import org.matrix.android.sdk.internal.crypto.verification.qrcode.QrCodeVerification
|
||||||
|
import org.matrix.android.sdk.internal.util.time.Clock
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import uniffi.olm.OlmMachine
|
import uniffi.olm.OlmMachine
|
||||||
import uniffi.olm.VerificationRequest
|
import uniffi.olm.VerificationRequest
|
||||||
|
@ -43,11 +44,12 @@ import uniffi.olm.VerificationRequest
|
||||||
* concrete verification flows.
|
* concrete verification flows.
|
||||||
*/
|
*/
|
||||||
internal class VerificationRequest(
|
internal class VerificationRequest(
|
||||||
private val machine: OlmMachine,
|
private val innerOlmMachine: OlmMachine,
|
||||||
private var inner: VerificationRequest,
|
private var innerVerificationRequest: VerificationRequest,
|
||||||
private val sender: RequestSender,
|
private val requestSender: RequestSender,
|
||||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||||
private val listeners: ArrayList<VerificationService.Listener>
|
private val listeners: ArrayList<VerificationService.Listener>,
|
||||||
|
private val clock: Clock,
|
||||||
) {
|
) {
|
||||||
private val uiHandler = Handler(Looper.getMainLooper())
|
private val uiHandler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
|
@ -70,12 +72,12 @@ internal class VerificationRequest(
|
||||||
* event that initiated the flow.
|
* event that initiated the flow.
|
||||||
*/
|
*/
|
||||||
internal fun flowId(): String {
|
internal fun flowId(): String {
|
||||||
return inner.flowId
|
return innerVerificationRequest.flowId
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The user ID of the other user that is participating in this verification flow */
|
/** The user ID of the other user that is participating in this verification flow */
|
||||||
internal fun otherUser(): String {
|
internal fun otherUser(): String {
|
||||||
return inner.otherUserId
|
return innerVerificationRequest.otherUserId
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The device ID of the other user's device that is participating in this verification flow
|
/** The device ID of the other user's device that is participating in this verification flow
|
||||||
|
@ -85,12 +87,12 @@ internal class VerificationRequest(
|
||||||
* */
|
* */
|
||||||
internal fun otherDeviceId(): String? {
|
internal fun otherDeviceId(): String? {
|
||||||
refreshData()
|
refreshData()
|
||||||
return inner.otherDeviceId
|
return innerVerificationRequest.otherDeviceId
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Did we initiate this verification flow */
|
/** Did we initiate this verification flow */
|
||||||
internal fun weStarted(): Boolean {
|
internal fun weStarted(): Boolean {
|
||||||
return inner.weStarted
|
return innerVerificationRequest.weStarted
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the id of the room where this verification is happening
|
/** Get the id of the room where this verification is happening
|
||||||
|
@ -98,7 +100,7 @@ internal class VerificationRequest(
|
||||||
* Will be null if the verification is not happening inside a room.
|
* Will be null if the verification is not happening inside a room.
|
||||||
*/
|
*/
|
||||||
internal fun roomId(): String? {
|
internal fun roomId(): String? {
|
||||||
return inner.roomId
|
return innerVerificationRequest.roomId
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Did the non-initiating side respond with a m.key.verification.read event
|
/** Did the non-initiating side respond with a m.key.verification.read event
|
||||||
|
@ -109,13 +111,13 @@ internal class VerificationRequest(
|
||||||
*/
|
*/
|
||||||
internal fun isReady(): Boolean {
|
internal fun isReady(): Boolean {
|
||||||
refreshData()
|
refreshData()
|
||||||
return inner.isReady
|
return innerVerificationRequest.isReady
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Did we advertise that we're able to scan QR codes */
|
/** Did we advertise that we're able to scan QR codes */
|
||||||
internal fun canScanQrCodes(): Boolean {
|
internal fun canScanQrCodes(): Boolean {
|
||||||
refreshData()
|
refreshData()
|
||||||
return inner.ourMethods?.contains(VERIFICATION_METHOD_QR_CODE_SCAN) ?: false
|
return innerVerificationRequest.ourMethods?.contains(VERIFICATION_METHOD_QR_CODE_SCAN) ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Accept the verification request advertising the given methods as supported
|
/** Accept the verification request advertising the given methods as supported
|
||||||
|
@ -134,14 +136,14 @@ internal class VerificationRequest(
|
||||||
suspend fun acceptWithMethods(methods: List<VerificationMethod>) {
|
suspend fun acceptWithMethods(methods: List<VerificationMethod>) {
|
||||||
val stringMethods = prepareMethods(methods)
|
val stringMethods = prepareMethods(methods)
|
||||||
|
|
||||||
val request = machine.acceptVerificationRequest(
|
val request = innerOlmMachine.acceptVerificationRequest(
|
||||||
inner.otherUserId,
|
innerVerificationRequest.otherUserId,
|
||||||
inner.flowId,
|
innerVerificationRequest.flowId,
|
||||||
stringMethods
|
stringMethods
|
||||||
)
|
)
|
||||||
|
|
||||||
if (request != null) {
|
if (request != null) {
|
||||||
sender.sendVerificationRequest(request)
|
requestSender.sendVerificationRequest(request)
|
||||||
dispatchRequestUpdated()
|
dispatchRequestUpdated()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -161,11 +163,11 @@ internal class VerificationRequest(
|
||||||
*/
|
*/
|
||||||
internal suspend fun startSasVerification(): SasVerification? {
|
internal suspend fun startSasVerification(): SasVerification? {
|
||||||
return withContext(coroutineDispatchers.io) {
|
return withContext(coroutineDispatchers.io) {
|
||||||
val result = machine.startSasVerification(inner.otherUserId, inner.flowId)
|
val result = innerOlmMachine.startSasVerification(innerVerificationRequest.otherUserId, innerVerificationRequest.flowId)
|
||||||
|
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
sender.sendVerificationRequest(result.request)
|
requestSender.sendVerificationRequest(result.request)
|
||||||
SasVerification(machine, result.sas, sender, coroutineDispatchers, listeners)
|
SasVerification(innerOlmMachine, result.sas, requestSender, coroutineDispatchers, listeners)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
@ -189,10 +191,10 @@ internal class VerificationRequest(
|
||||||
// TODO again, what's the deal with ISO_8859_1?
|
// TODO again, what's the deal with ISO_8859_1?
|
||||||
val byteArray = data.toByteArray(Charsets.ISO_8859_1)
|
val byteArray = data.toByteArray(Charsets.ISO_8859_1)
|
||||||
val encodedData = byteArray.toBase64NoPadding()
|
val encodedData = byteArray.toBase64NoPadding()
|
||||||
val result = machine.scanQrCode(otherUser(), flowId(), encodedData) ?: return null
|
val result = innerOlmMachine.scanQrCode(otherUser(), flowId(), encodedData) ?: return null
|
||||||
|
|
||||||
sender.sendVerificationRequest(result.request)
|
requestSender.sendVerificationRequest(result.request)
|
||||||
return QrCodeVerification(machine, this, result.qr, sender, coroutineDispatchers, listeners)
|
return QrCodeVerification(innerOlmMachine, this, result.qr, requestSender, coroutineDispatchers, listeners)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Transition into a QR code verification to display a QR code
|
/** Transition into a QR code verification to display a QR code
|
||||||
|
@ -213,14 +215,14 @@ internal class VerificationRequest(
|
||||||
* QR code verification, or null if we can't yet transition into QR code verification.
|
* QR code verification, or null if we can't yet transition into QR code verification.
|
||||||
*/
|
*/
|
||||||
internal fun startQrVerification(): QrCodeVerification? {
|
internal fun startQrVerification(): QrCodeVerification? {
|
||||||
val qrcode = machine.startQrVerification(inner.otherUserId, inner.flowId)
|
val qrcode = innerOlmMachine.startQrVerification(innerVerificationRequest.otherUserId, innerVerificationRequest.flowId)
|
||||||
|
|
||||||
return if (qrcode != null) {
|
return if (qrcode != null) {
|
||||||
QrCodeVerification(
|
QrCodeVerification(
|
||||||
machine = machine,
|
machine = innerOlmMachine,
|
||||||
request = this,
|
request = this,
|
||||||
inner = qrcode,
|
inner = qrcode,
|
||||||
sender = sender,
|
sender = requestSender,
|
||||||
coroutineDispatchers = coroutineDispatchers,
|
coroutineDispatchers = coroutineDispatchers,
|
||||||
listeners = listeners,
|
listeners = listeners,
|
||||||
)
|
)
|
||||||
|
@ -240,24 +242,24 @@ internal class VerificationRequest(
|
||||||
* The method turns into a noop, if the verification flow has already been cancelled.
|
* The method turns into a noop, if the verification flow has already been cancelled.
|
||||||
*/
|
*/
|
||||||
internal suspend fun cancel() {
|
internal suspend fun cancel() {
|
||||||
val request = machine.cancelVerification(
|
val request = innerOlmMachine.cancelVerification(
|
||||||
inner.otherUserId,
|
innerVerificationRequest.otherUserId,
|
||||||
inner.flowId,
|
innerVerificationRequest.flowId,
|
||||||
CancelCode.User.value
|
CancelCode.User.value
|
||||||
)
|
)
|
||||||
|
|
||||||
if (request != null) {
|
if (request != null) {
|
||||||
sender.sendVerificationRequest(request)
|
requestSender.sendVerificationRequest(request)
|
||||||
dispatchRequestUpdated()
|
dispatchRequestUpdated()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Fetch fresh data from the Rust side for our verification flow */
|
/** Fetch fresh data from the Rust side for our verification flow */
|
||||||
private fun refreshData() {
|
private fun refreshData() {
|
||||||
val request = machine.getVerificationRequest(inner.otherUserId, inner.flowId)
|
val request = innerOlmMachine.getVerificationRequest(innerVerificationRequest.otherUserId, innerVerificationRequest.flowId)
|
||||||
|
|
||||||
if (request != null) {
|
if (request != null) {
|
||||||
inner = request
|
innerVerificationRequest = request
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,7 +274,7 @@ internal class VerificationRequest(
|
||||||
*/
|
*/
|
||||||
internal fun toPendingVerificationRequest(): PendingVerificationRequest {
|
internal fun toPendingVerificationRequest(): PendingVerificationRequest {
|
||||||
refreshData()
|
refreshData()
|
||||||
val cancelInfo = inner.cancelInfo
|
val cancelInfo = innerVerificationRequest.cancelInfo
|
||||||
val cancelCode =
|
val cancelCode =
|
||||||
if (cancelInfo != null) {
|
if (cancelInfo != null) {
|
||||||
safeValueOf(cancelInfo.cancelCode)
|
safeValueOf(cancelInfo.cancelCode)
|
||||||
|
@ -280,60 +282,60 @@ internal class VerificationRequest(
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
val ourMethods = inner.ourMethods
|
val ourMethods = innerVerificationRequest.ourMethods
|
||||||
val theirMethods = inner.theirMethods
|
val theirMethods = innerVerificationRequest.theirMethods
|
||||||
val otherDeviceId = inner.otherDeviceId
|
val otherDeviceId = innerVerificationRequest.otherDeviceId
|
||||||
|
|
||||||
var requestInfo: ValidVerificationInfoRequest? = null
|
var requestInfo: ValidVerificationInfoRequest? = null
|
||||||
var readyInfo: ValidVerificationInfoReady? = null
|
var readyInfo: ValidVerificationInfoReady? = null
|
||||||
|
|
||||||
if (inner.weStarted && ourMethods != null) {
|
if (innerVerificationRequest.weStarted && ourMethods != null) {
|
||||||
requestInfo =
|
requestInfo =
|
||||||
ValidVerificationInfoRequest(
|
ValidVerificationInfoRequest(
|
||||||
transactionId = inner.flowId,
|
transactionId = innerVerificationRequest.flowId,
|
||||||
fromDevice = machine.deviceId(),
|
fromDevice = innerOlmMachine.deviceId(),
|
||||||
methods = ourMethods,
|
methods = ourMethods,
|
||||||
timestamp = null,
|
timestamp = null,
|
||||||
)
|
)
|
||||||
} else if (!inner.weStarted && ourMethods != null) {
|
} else if (!innerVerificationRequest.weStarted && ourMethods != null) {
|
||||||
readyInfo =
|
readyInfo =
|
||||||
ValidVerificationInfoReady(
|
ValidVerificationInfoReady(
|
||||||
transactionId = inner.flowId,
|
transactionId = innerVerificationRequest.flowId,
|
||||||
fromDevice = machine.deviceId(),
|
fromDevice = innerOlmMachine.deviceId(),
|
||||||
methods = ourMethods,
|
methods = ourMethods,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inner.weStarted && theirMethods != null && otherDeviceId != null) {
|
if (innerVerificationRequest.weStarted && theirMethods != null && otherDeviceId != null) {
|
||||||
readyInfo =
|
readyInfo =
|
||||||
ValidVerificationInfoReady(
|
ValidVerificationInfoReady(
|
||||||
transactionId = inner.flowId,
|
transactionId = innerVerificationRequest.flowId,
|
||||||
fromDevice = otherDeviceId,
|
fromDevice = otherDeviceId,
|
||||||
methods = theirMethods,
|
methods = theirMethods,
|
||||||
)
|
)
|
||||||
} else if (!inner.weStarted && theirMethods != null && otherDeviceId != null) {
|
} else if (!innerVerificationRequest.weStarted && theirMethods != null && otherDeviceId != null) {
|
||||||
requestInfo =
|
requestInfo =
|
||||||
ValidVerificationInfoRequest(
|
ValidVerificationInfoRequest(
|
||||||
transactionId = inner.flowId,
|
transactionId = innerVerificationRequest.flowId,
|
||||||
fromDevice = otherDeviceId,
|
fromDevice = otherDeviceId,
|
||||||
methods = theirMethods,
|
methods = theirMethods,
|
||||||
timestamp = System.currentTimeMillis(),
|
timestamp = clock.epochMillis(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return PendingVerificationRequest(
|
return PendingVerificationRequest(
|
||||||
// Creation time
|
// Creation time
|
||||||
ageLocalTs = System.currentTimeMillis(),
|
ageLocalTs = clock.epochMillis(),
|
||||||
// Who initiated the request
|
// Who initiated the request
|
||||||
isIncoming = !inner.weStarted,
|
isIncoming = !innerVerificationRequest.weStarted,
|
||||||
// Local echo id, what to do here?
|
// Local echo id, what to do here?
|
||||||
localId = inner.flowId,
|
localId = innerVerificationRequest.flowId,
|
||||||
// other user
|
// other user
|
||||||
otherUserId = inner.otherUserId,
|
otherUserId = innerVerificationRequest.otherUserId,
|
||||||
// room id
|
// room id
|
||||||
roomId = inner.roomId,
|
roomId = innerVerificationRequest.roomId,
|
||||||
// transaction id
|
// transaction id
|
||||||
transactionId = inner.flowId,
|
transactionId = innerVerificationRequest.flowId,
|
||||||
// val requestInfo: ValidVerificationInfoRequest? = null,
|
// val requestInfo: ValidVerificationInfoRequest? = null,
|
||||||
requestInfo = requestInfo,
|
requestInfo = requestInfo,
|
||||||
// val readyInfo: ValidVerificationInfoReady? = null,
|
// val readyInfo: ValidVerificationInfoReady? = null,
|
||||||
|
@ -341,9 +343,9 @@ internal class VerificationRequest(
|
||||||
// cancel code if there is one
|
// cancel code if there is one
|
||||||
cancelConclusion = cancelCode,
|
cancelConclusion = cancelCode,
|
||||||
// are we done/successful
|
// are we done/successful
|
||||||
isSuccessful = inner.isDone,
|
isSuccessful = innerVerificationRequest.isDone,
|
||||||
// did another device answer the request
|
// did another device answer the request
|
||||||
handledByOtherSession = inner.isPassive,
|
handledByOtherSession = innerVerificationRequest.isPassive,
|
||||||
// devices that should receive the events we send out
|
// devices that should receive the events we send out
|
||||||
targetDevices = null
|
targetDevices = null
|
||||||
)
|
)
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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 org.matrix.android.sdk.internal.crypto.verification
|
||||||
|
|
||||||
|
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
||||||
|
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
|
||||||
|
import org.matrix.android.sdk.internal.crypto.network.RequestSender
|
||||||
|
import org.matrix.android.sdk.internal.util.time.Clock
|
||||||
|
import uniffi.olm.OlmMachine
|
||||||
|
|
||||||
|
internal class VerificationRequestFactory(
|
||||||
|
private val innerOlmMachine: OlmMachine,
|
||||||
|
private val requestSender: RequestSender,
|
||||||
|
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||||
|
private val listeners: ArrayList<VerificationService.Listener>,
|
||||||
|
private val clock: Clock,
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun create(inner: uniffi.olm.VerificationRequest): VerificationRequest {
|
||||||
|
return VerificationRequest(
|
||||||
|
innerOlmMachine = innerOlmMachine,
|
||||||
|
innerVerificationRequest = inner,
|
||||||
|
requestSender = requestSender,
|
||||||
|
coroutineDispatchers = coroutineDispatchers,
|
||||||
|
listeners = listeners,
|
||||||
|
clock = clock
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2021 The Matrix.org Foundation C.I.C.
|
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.matrix.android.sdk.internal.crypto
|
package org.matrix.android.sdk.internal.crypto.verification.qrcode
|
||||||
|
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
||||||
|
@ -26,6 +26,7 @@ import org.matrix.android.sdk.api.session.crypto.verification.safeValueOf
|
||||||
import org.matrix.android.sdk.api.util.fromBase64
|
import org.matrix.android.sdk.api.util.fromBase64
|
||||||
import org.matrix.android.sdk.internal.crypto.network.RequestSender
|
import org.matrix.android.sdk.internal.crypto.network.RequestSender
|
||||||
import org.matrix.android.sdk.internal.crypto.verification.UpdateDispatcher
|
import org.matrix.android.sdk.internal.crypto.verification.UpdateDispatcher
|
||||||
|
import org.matrix.android.sdk.internal.crypto.verification.VerificationRequest
|
||||||
import uniffi.olm.CryptoStoreException
|
import uniffi.olm.CryptoStoreException
|
||||||
import uniffi.olm.OlmMachine
|
import uniffi.olm.OlmMachine
|
||||||
import uniffi.olm.QrCode
|
import uniffi.olm.QrCode
|
||||||
|
@ -213,6 +214,12 @@ internal class QrCodeVerification(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "QrCodeVerification(qrCodeText=$qrCodeText, state=$state, transactionId='$transactionId', otherUserId='$otherUserId', otherDeviceId=$otherDeviceId, isIncoming=$isIncoming)"
|
return "QrCodeVerification(" +
|
||||||
|
"qrCodeText=$qrCodeText, " +
|
||||||
|
"state=$state, " +
|
||||||
|
"transactionId='$transactionId', " +
|
||||||
|
"otherUserId='$otherUserId', " +
|
||||||
|
"otherDeviceId=$otherDeviceId, " +
|
||||||
|
"isIncoming=$isIncoming)"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -19,10 +19,6 @@ package org.matrix.android.sdk.internal.session
|
||||||
import org.matrix.android.sdk.api.session.ToDeviceService
|
import org.matrix.android.sdk.api.session.ToDeviceService
|
||||||
import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap
|
import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap
|
||||||
import org.matrix.android.sdk.api.session.events.model.Content
|
import org.matrix.android.sdk.api.session.events.model.Content
|
||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
|
||||||
import org.matrix.android.sdk.internal.crypto.EncryptEventContentUseCase
|
|
||||||
import org.matrix.android.sdk.internal.crypto.OlmMachineProvider
|
|
||||||
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
|
|
||||||
import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask
|
import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -52,7 +48,7 @@ internal class DefaultToDeviceService @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun sendEncryptedToDevice(eventType: String, targets: Map<String, List<String>>, content: Content, txnId: String?) {
|
override suspend fun sendEncryptedToDevice(eventType: String, targets: Map<String, List<String>>, content: Content, txnId: String?) {
|
||||||
//TODO: add to rust-ffi
|
// TODO: add to rust-ffi
|
||||||
/*
|
/*
|
||||||
val payloadJson = mapOf(
|
val payloadJson = mapOf(
|
||||||
"type" to eventType,
|
"type" to eventType,
|
||||||
|
|
|
@ -45,7 +45,6 @@ import org.matrix.android.sdk.api.util.Optional
|
||||||
import org.matrix.android.sdk.internal.session.permalinks.ViaParameterFinder
|
import org.matrix.android.sdk.internal.session.permalinks.ViaParameterFinder
|
||||||
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource
|
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource
|
||||||
import org.matrix.android.sdk.internal.session.space.DefaultSpace
|
import org.matrix.android.sdk.internal.session.space.DefaultSpace
|
||||||
import java.security.InvalidParameterException
|
|
||||||
|
|
||||||
internal class DefaultRoom(
|
internal class DefaultRoom(
|
||||||
override val roomId: String,
|
override val roomId: String,
|
||||||
|
@ -81,7 +80,6 @@ internal class DefaultRoom(
|
||||||
return roomSummaryDataSource.getRoomSummary(roomId)
|
return roomSummaryDataSource.getRoomSummary(roomId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun asSpace(): Space? {
|
override fun asSpace(): Space? {
|
||||||
if (roomSummary()?.roomType != RoomType.SPACE) return null
|
if (roomSummary()?.roomType != RoomType.SPACE) return null
|
||||||
return DefaultSpace(this, roomSummaryDataSource, viaParameterFinder)
|
return DefaultSpace(this, roomSummaryDataSource, viaParameterFinder)
|
||||||
|
|
|
@ -21,7 +21,6 @@ import io.realm.kotlin.createObject
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.matrix.android.sdk.api.extensions.orFalse
|
import org.matrix.android.sdk.api.extensions.orFalse
|
||||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.CrossSigningService
|
|
||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent
|
import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent
|
||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
|
|
|
@ -31,7 +31,6 @@ import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupVersionTrust
|
|
||||||
|
|
||||||
class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialState: KeysBackupSettingViewState,
|
class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialState: KeysBackupSettingViewState,
|
||||||
session: Session
|
session: Session
|
||||||
|
|
|
@ -66,6 +66,7 @@ class KeyRequestHandler @Inject constructor(
|
||||||
var session: Session? = null
|
var session: Session? = null
|
||||||
|
|
||||||
var scope: CoroutineScope? = null
|
var scope: CoroutineScope? = null
|
||||||
|
|
||||||
// This functionality is disabled in element for now. As it could be prone to social attacks
|
// This functionality is disabled in element for now. As it could be prone to social attacks
|
||||||
var enablePromptingForRequest = false
|
var enablePromptingForRequest = false
|
||||||
|
|
||||||
|
|
|
@ -44,12 +44,10 @@ import org.matrix.android.sdk.api.auth.registration.nextUncompletedStage
|
||||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||||
import org.matrix.android.sdk.api.failure.Failure
|
import org.matrix.android.sdk.api.failure.Failure
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupLastVersionResult
|
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.extractCurveKeyFromRecoveryKey
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.extractCurveKeyFromRecoveryKey
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult
|
||||||
import org.matrix.android.sdk.api.session.securestorage.RawBytesKeySpec
|
import org.matrix.android.sdk.api.session.securestorage.RawBytesKeySpec
|
||||||
import org.matrix.android.sdk.api.session.uia.DefaultBaseAuth
|
import org.matrix.android.sdk.api.session.uia.DefaultBaseAuth
|
||||||
import org.matrix.android.sdk.api.util.awaitCallback
|
|
||||||
import org.matrix.android.sdk.api.util.fromBase64
|
import org.matrix.android.sdk.api.util.fromBase64
|
||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
import kotlin.coroutines.Continuation
|
import kotlin.coroutines.Continuation
|
||||||
|
|
|
@ -462,7 +462,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
|
||||||
tx.performAccept()
|
tx.performAccept()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
// Use this one!
|
// Use this one!
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
|
|
|
@ -42,15 +42,12 @@ import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
|
||||||
import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
|
import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
|
||||||
import org.matrix.android.sdk.api.auth.registration.nextUncompletedStage
|
import org.matrix.android.sdk.api.auth.registration.nextUncompletedStage
|
||||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||||
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
|
|
||||||
import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap
|
|
||||||
import org.matrix.android.sdk.api.session.getUser
|
import org.matrix.android.sdk.api.session.getUser
|
||||||
import org.matrix.android.sdk.api.session.initsync.SyncStatusService
|
import org.matrix.android.sdk.api.session.initsync.SyncStatusService
|
||||||
import org.matrix.android.sdk.api.session.pushrules.RuleIds
|
import org.matrix.android.sdk.api.session.pushrules.RuleIds
|
||||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||||
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
||||||
import org.matrix.android.sdk.api.settings.LightweightSettingsStorage
|
import org.matrix.android.sdk.api.settings.LightweightSettingsStorage
|
||||||
import org.matrix.android.sdk.api.util.awaitCallback
|
|
||||||
import org.matrix.android.sdk.api.util.toMatrixItem
|
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||||
import org.matrix.android.sdk.flow.flow
|
import org.matrix.android.sdk.flow.flow
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
|
@ -250,7 +250,7 @@ class MessageActionsViewModel @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun actionsForEvent(timelineEvent: TimelineEvent, actionPermissions: ActionPermissions): List<EventSharedAction> {
|
private suspend fun actionsForEvent(timelineEvent: TimelineEvent, actionPermissions: ActionPermissions): List<EventSharedAction> {
|
||||||
val messageContent = timelineEvent.getLastMessageContent()
|
val messageContent = timelineEvent.getLastMessageContent()
|
||||||
val msgType = messageContent?.msgType
|
val msgType = messageContent?.msgType
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue