Merge pull request #9 from poljar/feature/fga/device_verification

Feature/fga/device verification
This commit is contained in:
ganfra 2022-06-02 15:42:42 +02:00 committed by GitHub
commit e519561edf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 361 additions and 273 deletions

View File

@ -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

View File

@ -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 }
} }
} }
} }

View File

@ -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!!

View File

@ -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!!,
) )
} }

View File

@ -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

View File

@ -108,7 +108,6 @@ class MXUsersDevicesMap<E> {
map.putAll(other) map.putAll(other)
} }
/** /**
* Add entries from another MXUsersDevicesMap * Add entries from another MXUsersDevicesMap
* *

View File

@ -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).
*/ */

View File

@ -30,5 +30,4 @@ internal data class MessageVerificationAcceptContent(
) { ) {
val transactionId: String? = relatesTo?.eventId val transactionId: String? = relatesTo?.eventId
} }

View File

@ -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

View File

@ -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.

View File

@ -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> {

View File

@ -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)
} }

View File

@ -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.

View File

@ -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.

View File

@ -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
}
}
}

View File

@ -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
)
} }

View File

@ -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
)
}
} }

View File

@ -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.

View File

@ -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 {

View File

@ -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.

View File

@ -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
)
} }
/** /**

View File

@ -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

View File

@ -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) {

View File

@ -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,

View File

@ -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')"
} }
} }

View File

@ -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
) )

View File

@ -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
)
}
}

View File

@ -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)"
} }
} }

View File

@ -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,

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -462,7 +462,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
tx.performAccept() tx.performAccept()
} }
} }
*/ */
// Use this one! // Use this one!
setState { setState {
copy( copy(

View File

@ -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

View File

@ -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