mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-15 01:35:07 +08:00
Ignore some test in tust. Added some supports flags
This commit is contained in:
parent
238d10d4cb
commit
5f069264d0
@ -45,6 +45,7 @@ import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.session.getRoomSummary
|
||||
import org.matrix.android.sdk.api.session.room.Room
|
||||
import org.matrix.android.sdk.api.session.room.failure.JoinRoomFailure
|
||||
import org.matrix.android.sdk.api.session.room.getTimelineEvent
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
|
||||
import org.matrix.android.sdk.api.session.room.send.SendState
|
||||
@ -83,7 +84,7 @@ class CommonTestHelper internal constructor(context: Context, val cryptoConfig:
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
internal fun runCryptoTest(context: Context, cryptoConfig: MXCryptoConfig? = null, autoSignoutOnClose: Boolean = true, block: suspend CoroutineScope.(CryptoTestHelper, CommonTestHelper) -> Unit) {
|
||||
internal fun runCryptoTest(context: Context, cryptoConfig: MXCryptoConfig? = null, autoSignoutOnClose: Boolean = true, block: suspend CoroutineScope.(CryptoTestHelper, CommonTestHelper) -> Unit) {
|
||||
val testHelper = CommonTestHelper(context, cryptoConfig)
|
||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
||||
return try {
|
||||
@ -209,18 +210,28 @@ class CommonTestHelper internal constructor(context: Context, val cryptoConfig:
|
||||
}
|
||||
})
|
||||
return messageSent.await()
|
||||
// return withTimeout(TestConstants.timeOutMillis) { messageSent.await() }
|
||||
// return withTimeout(TestConstants.timeOutMillis) { messageSent.await() }
|
||||
}
|
||||
|
||||
suspend fun ensureMessage(room: Room, eventId: String, block: ((event: TimelineEvent) -> Boolean)) {
|
||||
Log.v("#E2E TEST", "ensureMessage room:${room.roomId} <$eventId>")
|
||||
val timeline = room.timelineService().createTimeline(null, TimelineSettings(60))
|
||||
val timeline = room.timelineService().createTimeline(null, TimelineSettings(60, buildReadReceipts = false))
|
||||
|
||||
// check if not already there?
|
||||
val existing = withContext(Dispatchers.Main) {
|
||||
room.getTimelineEvent(eventId)
|
||||
}
|
||||
if (existing != null && block(existing)) return Unit.also {
|
||||
Log.v("#E2E TEST", "Already received")
|
||||
}
|
||||
|
||||
val messageSent = CompletableDeferred<Unit>()
|
||||
|
||||
timeline.addListener(object : Timeline.Listener {
|
||||
override fun onNewTimelineEvents(eventIds: List<String>) {
|
||||
Log.v("#E2E TEST", "onNewTimelineEvents snapshot is $eventIds")
|
||||
}
|
||||
|
||||
override fun onTimelineUpdated(snapshot: List<TimelineEvent>) {
|
||||
val success = timeline.getSnapshot()
|
||||
// .filter { it.root.getClearType() == EventType.MESSAGE }
|
||||
@ -243,13 +254,13 @@ class CommonTestHelper internal constructor(context: Context, val cryptoConfig:
|
||||
|
||||
timeline.start()
|
||||
|
||||
return messageSent.await()
|
||||
return messageSent.await()
|
||||
// withTimeout(TestConstants.timeOutMillis) {
|
||||
// messageSent.await()
|
||||
// }
|
||||
}
|
||||
|
||||
fun ensureMessagePromise(room: Room, eventId: String, block: ((event: TimelineEvent) -> Boolean)): CompletableDeferred<Unit> {
|
||||
fun ensureMessagePromise(room: Room, eventId: String, block: ((event: TimelineEvent) -> Boolean)): CompletableDeferred<Unit> {
|
||||
val timeline = room.timelineService().createTimeline(null, TimelineSettings(60))
|
||||
timeline.start()
|
||||
val messageSent = CompletableDeferred<Unit>()
|
||||
@ -334,11 +345,11 @@ class CommonTestHelper internal constructor(context: Context, val cryptoConfig:
|
||||
}
|
||||
|
||||
suspend fun waitForAndAcceptInviteInRoom(otherSession: Session, roomID: String) {
|
||||
retryPeriodically {
|
||||
retryWithBackoff {
|
||||
val roomSummary = otherSession.getRoomSummary(roomID)
|
||||
(roomSummary != null && roomSummary.membership == Membership.INVITE).also {
|
||||
if (it) {
|
||||
Log.v("# TEST", "${otherSession.myUserId} can see the invite")
|
||||
Log.v("#E2E TEST", "${otherSession.myUserId} can see the invite")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -354,7 +365,7 @@ class CommonTestHelper internal constructor(context: Context, val cryptoConfig:
|
||||
}
|
||||
|
||||
Log.v("#E2E TEST", "${otherSession.myUserId} waiting for join echo ...")
|
||||
retryPeriodically {
|
||||
retryWithBackoff {
|
||||
val roomSummary = otherSession.getRoomSummary(roomID)
|
||||
roomSummary != null && roomSummary.membership == Membership.JOIN
|
||||
}
|
||||
|
@ -136,7 +136,9 @@ class CryptoTestHelper(val testHelper: CommonTestHelper) {
|
||||
suspend fun inviteNewUsersAndWaitForThemToJoin(session: Session, roomId: String, usernames: List<String>): List<Session> {
|
||||
val newSessions = usernames.map { username ->
|
||||
testHelper.createAccount(username, SessionTestParams(true)).also {
|
||||
it.cryptoService().enableKeyGossiping(false)
|
||||
if (it.cryptoService().supportsDisablingKeyGossiping()) {
|
||||
it.cryptoService().enableKeyGossiping(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -560,7 +562,7 @@ class CryptoTestHelper(val testHelper: CommonTestHelper) {
|
||||
} catch (error: MXCryptoError) {
|
||||
// nop
|
||||
}
|
||||
Log.v("TEST", "ensureCanDecrypt ${event.getClearType()} is ${event.getClearContent()}")
|
||||
Log.v("#E2E TEST", "ensureCanDecrypt ${event.getClearType()} is ${event.getClearContent()}")
|
||||
event.getClearType() == EventType.MESSAGE &&
|
||||
messagesText[index] == event.getClearContent()?.toModel<MessageContent>()?.body
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import android.util.Log
|
||||
import androidx.test.filters.LargeTest
|
||||
import org.amshove.kluent.internal.assertEquals
|
||||
import org.junit.Assert
|
||||
import org.junit.Assume
|
||||
import org.junit.FixMethodOrder
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@ -28,6 +29,7 @@ import org.junit.runners.MethodSorters
|
||||
import org.matrix.android.sdk.InstrumentedTest
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.getRoom
|
||||
import org.matrix.android.sdk.api.session.room.getTimelineEvent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
|
||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||
@ -58,15 +60,15 @@ class E2EShareKeysConfigTest : InstrumentedTest {
|
||||
enableEncryption()
|
||||
})
|
||||
|
||||
commonTestHelper.retryPeriodically {
|
||||
commonTestHelper.retryWithBackoff {
|
||||
aliceSession.roomService().getRoomSummary(roomId)?.isEncrypted == true
|
||||
}
|
||||
val roomAlice = aliceSession.roomService().getRoom(roomId)!!
|
||||
|
||||
// send some messages
|
||||
val withSession1 = commonTestHelper.sendTextMessage(roomAlice, "Hello", 1)
|
||||
val withSession1 = commonTestHelper.sendMessageInRoom(roomAlice, "Hello")
|
||||
aliceSession.cryptoService().discardOutboundSession(roomId)
|
||||
val withSession2 = commonTestHelper.sendTextMessage(roomAlice, "World", 1)
|
||||
val withSession2 = commonTestHelper.sendMessageInRoom(roomAlice, "World")
|
||||
|
||||
// Create bob account
|
||||
val bobSession = commonTestHelper.createAccount(TestConstants.USER_BOB, SessionTestParams(withInitialSync = true))
|
||||
@ -78,7 +80,7 @@ class E2EShareKeysConfigTest : InstrumentedTest {
|
||||
|
||||
// Bob has join but should not be able to decrypt history
|
||||
cryptoTestHelper.ensureCannotDecrypt(
|
||||
withSession1.map { it.eventId } + withSession2.map { it.eventId },
|
||||
listOf(withSession1, withSession2),
|
||||
bobSession,
|
||||
roomId
|
||||
)
|
||||
@ -86,44 +88,53 @@ class E2EShareKeysConfigTest : InstrumentedTest {
|
||||
// We don't need bob anymore
|
||||
commonTestHelper.signOutAndClose(bobSession)
|
||||
|
||||
// Now let's enable history key sharing on alice side
|
||||
aliceSession.cryptoService().enableShareKeyOnInvite(true)
|
||||
if (aliceSession.cryptoService().supportsShareKeysOnInvite()) {
|
||||
// Now let's enable history key sharing on alice side
|
||||
aliceSession.cryptoService().enableShareKeyOnInvite(true)
|
||||
|
||||
// let's add a new message first
|
||||
val afterFlagOn = commonTestHelper.sendTextMessage(roomAlice, "After", 1)
|
||||
// let's add a new message first
|
||||
val afterFlagOn = commonTestHelper.sendMessageInRoom(roomAlice, "After")
|
||||
|
||||
// Worth nothing to check that the session was rotated
|
||||
Assert.assertNotEquals(
|
||||
"Session should have been rotated",
|
||||
withSession2.first().root.content?.get("session_id")!!,
|
||||
afterFlagOn.first().root.content?.get("session_id")!!
|
||||
)
|
||||
// Worth nothing to check that the session was rotated
|
||||
Assert.assertNotEquals(
|
||||
"Session should have been rotated",
|
||||
aliceSession.roomService().getRoom(roomId)?.getTimelineEvent(withSession1)?.root?.content?.get("session_id")!!,
|
||||
aliceSession.roomService().getRoom(roomId)?.getTimelineEvent(afterFlagOn)?.root?.content?.get("session_id")!!
|
||||
)
|
||||
|
||||
// Invite a new user
|
||||
val samSession = commonTestHelper.createAccount(TestConstants.USER_SAM, SessionTestParams(withInitialSync = true))
|
||||
// Invite a new user
|
||||
val samSession = commonTestHelper.createAccount(TestConstants.USER_SAM, SessionTestParams(withInitialSync = true))
|
||||
|
||||
// Let alice invite sam
|
||||
roomAlice.membershipService().invite(samSession.myUserId)
|
||||
// Let alice invite sam
|
||||
roomAlice.membershipService().invite(samSession.myUserId)
|
||||
|
||||
commonTestHelper.waitForAndAcceptInviteInRoom(samSession, roomId)
|
||||
commonTestHelper.waitForAndAcceptInviteInRoom(samSession, roomId)
|
||||
|
||||
// Sam shouldn't be able to decrypt messages with the first session, but should decrypt the one with 3rd session
|
||||
cryptoTestHelper.ensureCannotDecrypt(
|
||||
withSession1.map { it.eventId } + withSession2.map { it.eventId },
|
||||
samSession,
|
||||
roomId
|
||||
)
|
||||
// Sam shouldn't be able to decrypt messages with the first session, but should decrypt the one with 3rd session
|
||||
cryptoTestHelper.ensureCannotDecrypt(
|
||||
listOf(withSession1, withSession2),
|
||||
samSession,
|
||||
roomId
|
||||
)
|
||||
|
||||
cryptoTestHelper.ensureCanDecrypt(
|
||||
afterFlagOn.map { it.eventId },
|
||||
samSession,
|
||||
roomId,
|
||||
afterFlagOn.map { it.root.getClearContent()?.get("body") as String })
|
||||
cryptoTestHelper.ensureCanDecrypt(
|
||||
listOf(afterFlagOn),
|
||||
samSession,
|
||||
roomId,
|
||||
listOf(aliceSession.roomService().getRoom(roomId)?.getTimelineEvent(afterFlagOn)?.root?.getClearContent()?.get("body") as String)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun ifSharingDisabledOnAliceSideBobShouldNotShareAliceHistory() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
|
||||
|
||||
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(roomHistoryVisibility = RoomHistoryVisibility.SHARED)
|
||||
|
||||
Assume.assumeTrue("Shared key on invite needed to test this",
|
||||
testData.firstSession.cryptoService().supportsShareKeysOnInvite()
|
||||
)
|
||||
|
||||
val aliceSession = testData.firstSession.also {
|
||||
it.cryptoService().enableShareKeyOnInvite(false)
|
||||
}
|
||||
@ -151,6 +162,11 @@ class E2EShareKeysConfigTest : InstrumentedTest {
|
||||
@Test
|
||||
fun ifSharingEnabledOnAliceSideBobShouldShareAliceHistory() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
|
||||
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(roomHistoryVisibility = RoomHistoryVisibility.SHARED)
|
||||
|
||||
Assume.assumeTrue("Shared key on invite needed to test this",
|
||||
testData.firstSession.cryptoService().supportsShareKeysOnInvite()
|
||||
)
|
||||
|
||||
val aliceSession = testData.firstSession.also {
|
||||
it.cryptoService().enableShareKeyOnInvite(true)
|
||||
}
|
||||
@ -193,6 +209,11 @@ class E2EShareKeysConfigTest : InstrumentedTest {
|
||||
@Test
|
||||
fun testBackupFlagIsCorrect() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
|
||||
val aliceSession = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = true))
|
||||
|
||||
Assume.assumeTrue("Shared key on invite needed to test this",
|
||||
aliceSession.cryptoService().supportsShareKeysOnInvite()
|
||||
)
|
||||
|
||||
aliceSession.cryptoService().enableShareKeyOnInvite(false)
|
||||
val roomId = aliceSession.roomService().createRoom(CreateRoomParams().apply {
|
||||
historyVisibility = RoomHistoryVisibility.SHARED
|
||||
@ -206,9 +227,10 @@ class E2EShareKeysConfigTest : InstrumentedTest {
|
||||
val roomAlice = aliceSession.roomService().getRoom(roomId)!!
|
||||
|
||||
// send some messages
|
||||
val notSharableMessage = commonTestHelper.sendTextMessage(roomAlice, "Hello", 1)
|
||||
val notSharableMessage = commonTestHelper.sendMessageInRoom(roomAlice, "Hello")
|
||||
|
||||
aliceSession.cryptoService().enableShareKeyOnInvite(true)
|
||||
val sharableMessage = commonTestHelper.sendTextMessage(roomAlice, "World", 1)
|
||||
val sharableMessage = commonTestHelper.sendMessageInRoom(roomAlice, "World")
|
||||
|
||||
Log.v("#E2E TEST", "Create and start key backup for bob ...")
|
||||
val keysBackupService = aliceSession.cryptoService().keysBackupService()
|
||||
@ -224,6 +246,7 @@ class E2EShareKeysConfigTest : InstrumentedTest {
|
||||
commonTestHelper.signOutAndClose(aliceSession)
|
||||
|
||||
val newAliceSession = commonTestHelper.logIntoAccount(aliceSession.myUserId, SessionTestParams(true))
|
||||
|
||||
newAliceSession.cryptoService().enableShareKeyOnInvite(true)
|
||||
|
||||
newAliceSession.cryptoService().keysBackupService().let { kbs ->
|
||||
@ -251,15 +274,16 @@ class E2EShareKeysConfigTest : InstrumentedTest {
|
||||
|
||||
// Sam shouldn't be able to decrypt messages with the first session, but should decrypt the one with 3rd session
|
||||
cryptoTestHelper.ensureCannotDecrypt(
|
||||
notSharableMessage.map { it.eventId },
|
||||
listOf(notSharableMessage),
|
||||
samSession,
|
||||
roomId
|
||||
)
|
||||
|
||||
cryptoTestHelper.ensureCanDecrypt(
|
||||
sharableMessage.map { it.eventId },
|
||||
listOf(sharableMessage),
|
||||
samSession,
|
||||
roomId,
|
||||
sharableMessage.map { it.root.getClearContent()?.get("body") as String })
|
||||
listOf(roomAlice.getTimelineEvent(sharableMessage)?.root?.getClearContent()?.get("body") as String)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -53,15 +53,13 @@ class E2eeConfigTest : InstrumentedTest {
|
||||
|
||||
val roomAlicePOV = cryptoTestData.firstSession.roomService().getRoom(cryptoTestData.roomId)!!
|
||||
|
||||
val sentMessage = testHelper.sendTextMessage(roomAlicePOV, "you are blocked", 1).first()
|
||||
val sentMessage = testHelper.sendMessageInRoom(roomAlicePOV, "you are blocked")
|
||||
|
||||
val roomBobPOV = cryptoTestData.secondSession!!.roomService().getRoom(cryptoTestData.roomId)!!
|
||||
// ensure other received
|
||||
testHelper.retryPeriodically {
|
||||
roomBobPOV.timelineService().getTimelineEvent(sentMessage.eventId) != null
|
||||
}
|
||||
testHelper.ensureMessage(roomBobPOV, sentMessage) { true }
|
||||
|
||||
cryptoTestHelper.ensureCannotDecrypt(listOf(sentMessage.eventId), cryptoTestData.secondSession!!, cryptoTestData.roomId)
|
||||
cryptoTestHelper.ensureCannotDecrypt(listOf(sentMessage), cryptoTestData.secondSession!!, cryptoTestData.roomId)
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -77,19 +75,20 @@ class E2eeConfigTest : InstrumentedTest {
|
||||
|
||||
val roomAlicePOV = cryptoTestData.firstSession.roomService().getRoom(cryptoTestData.roomId)!!
|
||||
|
||||
val sentMessage = testHelper.sendTextMessage(roomAlicePOV, "you can read", 1).first()
|
||||
val sentMessage = testHelper.sendMessageInRoom(roomAlicePOV, "you can read")
|
||||
|
||||
val roomBobPOV = cryptoTestData.secondSession!!.roomService().getRoom(cryptoTestData.roomId)!!
|
||||
// ensure other received
|
||||
testHelper.retryPeriodically {
|
||||
roomBobPOV.timelineService().getTimelineEvent(sentMessage.eventId) != null
|
||||
}
|
||||
|
||||
testHelper.ensureMessage(roomBobPOV, sentMessage) { true }
|
||||
|
||||
cryptoTestHelper.ensureCanDecrypt(
|
||||
listOf(sentMessage.eventId),
|
||||
listOf(sentMessage),
|
||||
cryptoTestData.secondSession!!,
|
||||
cryptoTestData.roomId,
|
||||
listOf(sentMessage.getLastMessageContent()!!.body)
|
||||
listOf(
|
||||
roomBobPOV.timelineService().getTimelineEvent(sentMessage)?.getLastMessageContent()!!.body
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -75,8 +75,12 @@ class E2eeSanityTests : InstrumentedTest {
|
||||
val e2eRoomID = cryptoTestData.roomId
|
||||
val aliceRoomPOV = aliceSession.getRoom(e2eRoomID)!!
|
||||
// we want to disable key gossiping to just check initial sending of keys
|
||||
aliceSession.cryptoService().enableKeyGossiping(false)
|
||||
cryptoTestData.secondSession?.cryptoService()?.enableKeyGossiping(false)
|
||||
if (aliceSession.cryptoService().supportsDisablingKeyGossiping()) {
|
||||
aliceSession.cryptoService().enableKeyGossiping(false)
|
||||
}
|
||||
if (cryptoTestData.secondSession?.cryptoService()?.supportsDisablingKeyGossiping() == true) {
|
||||
cryptoTestData.secondSession?.cryptoService()?.enableKeyGossiping(false)
|
||||
}
|
||||
|
||||
// add some more users and invite them
|
||||
val otherAccounts = listOf("benoit", "valere", "ganfra") // , "adam", "manu")
|
||||
|
@ -22,6 +22,7 @@ import org.amshove.kluent.fail
|
||||
import org.amshove.kluent.internal.assertEquals
|
||||
import org.amshove.kluent.internal.assertNotEquals
|
||||
import org.junit.Assert
|
||||
import org.junit.Assume
|
||||
import org.junit.FixMethodOrder
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@ -79,9 +80,9 @@ class E2eeShareKeysHistoryTest : InstrumentedTest {
|
||||
runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||
val aliceMessageText = "Hello Bob, I am Alice!"
|
||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true, roomHistoryVisibility)
|
||||
|
||||
val e2eRoomID = cryptoTestData.roomId
|
||||
|
||||
Assume.assumeTrue(cryptoTestData.firstSession.cryptoService().supportsShareKeysOnInvite())
|
||||
// Alice
|
||||
val aliceSession = cryptoTestData.firstSession.also {
|
||||
it.cryptoService().enableShareKeyOnInvite(true)
|
||||
@ -251,6 +252,8 @@ class E2eeShareKeysHistoryTest : InstrumentedTest {
|
||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true, initRoomHistoryVisibility)
|
||||
val e2eRoomID = cryptoTestData.roomId
|
||||
|
||||
Assume.assumeTrue(cryptoTestData.firstSession.cryptoService().supportsShareKeysOnInvite())
|
||||
|
||||
// Alice
|
||||
val aliceSession = cryptoTestData.firstSession.also {
|
||||
it.cryptoService().enableShareKeyOnInvite(true)
|
||||
|
@ -24,6 +24,7 @@ import org.junit.Assert.assertNotNull
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Assert.fail
|
||||
import org.junit.Assume
|
||||
import org.junit.FixMethodOrder
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@ -195,11 +196,15 @@ class XSigningTest : InstrumentedTest {
|
||||
|
||||
@Test
|
||||
fun testWarnOnCrossSigningReset() = runCryptoTest(context()) { cryptoTestHelper, testHelper ->
|
||||
|
||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
||||
|
||||
val aliceSession = cryptoTestData.firstSession
|
||||
val bobSession = cryptoTestData.secondSession
|
||||
|
||||
// Remove when https://github.com/matrix-org/matrix-rust-sdk/issues/1129
|
||||
Assume.assumeTrue("Not yet supported by rust", aliceSession.cryptoService().name() != "rust-sdk")
|
||||
|
||||
val aliceAuthParams = UserPasswordAuth(
|
||||
user = aliceSession.myUserId,
|
||||
password = TestConstants.PASSWORD
|
||||
|
@ -25,6 +25,7 @@ import junit.framework.TestCase.assertTrue
|
||||
import org.amshove.kluent.shouldBeEqualTo
|
||||
import org.junit.Assert
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Assume
|
||||
import org.junit.FixMethodOrder
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@ -59,6 +60,8 @@ class KeyShareTests : InstrumentedTest {
|
||||
fun test_DoNotSelfShareIfNotTrusted() = runCryptoTest(context()) { cryptoTestHelper, commonTestHelper ->
|
||||
|
||||
val aliceSession = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
|
||||
|
||||
Assume.assumeTrue("Not supported", aliceSession.cryptoService().supportKeyRequestInspection())
|
||||
Log.v("#TEST", "=======> AliceSession 1 is ${aliceSession.sessionParams.deviceId}")
|
||||
|
||||
// Create an encrypted room and add a message
|
||||
@ -70,8 +73,9 @@ class KeyShareTests : InstrumentedTest {
|
||||
)
|
||||
val room = aliceSession.getRoom(roomId)
|
||||
assertNotNull(room)
|
||||
Thread.sleep(4_000)
|
||||
assertTrue(room?.roomCryptoService()?.isEncrypted() == true)
|
||||
commonTestHelper.retryWithBackoff {
|
||||
room?.roomCryptoService()?.isEncrypted() == true
|
||||
}
|
||||
|
||||
val sentEvent = commonTestHelper.sendTextMessage(room!!, "My Message", 1).first()
|
||||
val sentEventId = sentEvent.eventId
|
||||
@ -207,6 +211,9 @@ class KeyShareTests : InstrumentedTest {
|
||||
|
||||
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
||||
val aliceSession = testData.firstSession
|
||||
|
||||
Assume.assumeTrue("Not supported", aliceSession.cryptoService().supportKeyRequestInspection())
|
||||
|
||||
val roomFromAlice = aliceSession.getRoom(testData.roomId)!!
|
||||
val bobSession = testData.secondSession!!
|
||||
|
||||
@ -239,6 +246,9 @@ class KeyShareTests : InstrumentedTest {
|
||||
|
||||
val testData = cryptoTestHelper.doE2ETestWithAliceInARoom(true)
|
||||
val aliceSession = testData.firstSession
|
||||
|
||||
Assume.assumeTrue("Not supported", aliceSession.cryptoService().supportKeyRequestInspection())
|
||||
|
||||
val roomFromAlice = aliceSession.getRoom(testData.roomId)!!
|
||||
|
||||
val aliceNewSession = commonTestHelper.logIntoAccount(aliceSession.myUserId, SessionTestParams(true))
|
||||
@ -274,6 +284,9 @@ class KeyShareTests : InstrumentedTest {
|
||||
|
||||
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
||||
val aliceSession = testData.firstSession
|
||||
|
||||
Assume.assumeTrue("Not supported", aliceSession.cryptoService().supportKeyRequestInspection())
|
||||
|
||||
val bobSession = testData.secondSession!!
|
||||
val roomFromBob = bobSession.getRoom(testData.roomId)!!
|
||||
|
||||
@ -386,6 +399,9 @@ class KeyShareTests : InstrumentedTest {
|
||||
) { cryptoTestHelper, commonTestHelper ->
|
||||
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
||||
val aliceSession = testData.firstSession
|
||||
|
||||
Assume.assumeTrue("Not supported", aliceSession.cryptoService().supportKeyRequestInspection())
|
||||
|
||||
val bobSession = testData.secondSession!!
|
||||
val roomFromBob = bobSession.getRoom(testData.roomId)!!
|
||||
|
||||
|
@ -20,6 +20,7 @@ import android.util.Log
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.LargeTest
|
||||
import org.junit.Assert
|
||||
import org.junit.Assume
|
||||
import org.junit.FixMethodOrder
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
@ -153,6 +154,7 @@ class WithHeldTests : InstrumentedTest {
|
||||
|
||||
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
||||
val aliceSession = testData.firstSession
|
||||
Assume.assumeTrue("Not supported", aliceSession.cryptoService().supportKeyRequestInspection())
|
||||
val bobSession = testData.secondSession!!
|
||||
val aliceInterceptor = testHelper.getTestInterceptor(aliceSession)
|
||||
|
||||
@ -222,6 +224,7 @@ class WithHeldTests : InstrumentedTest {
|
||||
|
||||
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
|
||||
val aliceSession = testData.firstSession
|
||||
Assume.assumeTrue("Not supported by rust sdk", aliceSession.cryptoService().supportsForwardedKeyWiththeld())
|
||||
val bobSession = testData.secondSession!!
|
||||
|
||||
val roomAlicePov = aliceSession.getRoom(testData.roomId)!!
|
||||
@ -236,19 +239,9 @@ class WithHeldTests : InstrumentedTest {
|
||||
// initialize to force request keys if missing
|
||||
cryptoTestHelper.initializeCrossSigning(bobSecondSession)
|
||||
|
||||
// // wait until alice downloaded the new device
|
||||
// testHelper.retryWithBackoff {
|
||||
// aliceSession.cryptoService().getUserDevices(bobSession.myUserId).any { it.deviceId == bobSecondSession.sessionParams.deviceId}
|
||||
// }
|
||||
//
|
||||
// // Trust bob second device from Alice POV
|
||||
// aliceSession.cryptoService().crossSigningService().trustDevice(bobSecondSession.sessionParams.deviceId)
|
||||
//
|
||||
// // wait until bob downloaded alice device
|
||||
// testHelper.retryWithBackoff {
|
||||
// bobSecondSession.cryptoService().getUserDevices(aliceSession.myUserId).any { it.deviceId == aliceSession.sessionParams.deviceId}
|
||||
// }
|
||||
// bobSecondSession.cryptoService().crossSigningService().trustDevice(aliceSession.sessionParams.deviceId)
|
||||
// Trust bob second device from Alice POV
|
||||
aliceSession.cryptoService().crossSigningService().trustDevice(bobSecondSession.sessionParams.deviceId)
|
||||
bobSecondSession.cryptoService().crossSigningService().trustDevice(aliceSession.sessionParams.deviceId)
|
||||
|
||||
var sessionId: String? = null
|
||||
// Check that the
|
||||
@ -264,18 +257,10 @@ class WithHeldTests : InstrumentedTest {
|
||||
timeLineEvent != null
|
||||
}
|
||||
|
||||
|
||||
mustFail(
|
||||
message = "This session should not be able to decrypt",
|
||||
failureBlock = { failure ->
|
||||
val type = (failure as MXCryptoError.Base).errorType
|
||||
val technicalMessage = failure.technicalMessage
|
||||
Assert.assertEquals("Error should be withheld", MXCryptoError.ErrorType.KEYS_WITHHELD, type)
|
||||
Assert.assertEquals("Cause should be unverified", WithHeldCode.UNVERIFIED.value, technicalMessage)
|
||||
}
|
||||
) {
|
||||
val timeLineEvent = bobSecondSession.getRoom(testData.roomId)?.getTimelineEvent(eventId)
|
||||
bobSecondSession.cryptoService().decryptEvent(timeLineEvent!!.root, "")
|
||||
// Check that bob second session requested the key
|
||||
testHelper.retryPeriodically {
|
||||
val wc = bobSecondSession.cryptoService().getWithHeldMegolmSession(roomAlicePov.roomId, sessionId!!)
|
||||
wc?.code == WithHeldCode.UNAUTHORISED
|
||||
}
|
||||
// // Check that bob second session requested the key
|
||||
// testHelper.retryPeriodically {
|
||||
|
@ -21,6 +21,7 @@ import org.amshove.kluent.internal.assertFailsWith
|
||||
import org.junit.Assert
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.fail
|
||||
import org.junit.Assume
|
||||
import org.junit.FixMethodOrder
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@ -43,6 +44,9 @@ class ReplayAttackTest : InstrumentedTest {
|
||||
|
||||
// Alice
|
||||
val aliceSession = cryptoTestData.firstSession
|
||||
|
||||
// Until https://github.com/matrix-org/matrix-rust-sdk/issues/397
|
||||
Assume.assumeTrue("Not yet supported by rust", cryptoTestData.firstSession.cryptoService().name() != "rust-sdk")
|
||||
val aliceRoomPOV = aliceSession.roomService().getRoom(e2eRoomID)!!
|
||||
|
||||
// Bob
|
||||
|
@ -194,6 +194,15 @@ internal class DefaultCryptoService @Inject constructor(
|
||||
private val isStarting = AtomicBoolean(false)
|
||||
private val isStarted = AtomicBoolean(false)
|
||||
|
||||
override fun name() = "kotlin-sdk"
|
||||
|
||||
override fun supportsKeyWithheld() = true
|
||||
override fun supportKeyRequestInspection() = true
|
||||
|
||||
override fun supportsDisablingKeyGossiping() = true
|
||||
|
||||
override fun supportsForwardedKeyWiththeld() = true
|
||||
|
||||
override suspend fun onStateEvent(roomId: String, event: Event, cryptoStoreAggregator: CryptoStoreAggregator?) {
|
||||
when (event.type) {
|
||||
EventType.STATE_ROOM_ENCRYPTION -> onRoomEncryptionEvent(roomId, event)
|
||||
@ -1395,7 +1404,7 @@ internal class DefaultCryptoService @Inject constructor(
|
||||
throw IllegalArgumentException("Missing algorithm")
|
||||
}
|
||||
|
||||
(alg as? IMXGroupEncryption)?.preshareKey(userIds)
|
||||
(alg as? IMXGroupEncryption)?.preshareKey(userIds)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.CryptoStoreAggregator
|
||||
|
||||
interface CryptoService {
|
||||
|
||||
fun name(): String
|
||||
fun verificationService(): VerificationService
|
||||
|
||||
fun crossSigningService(): CrossSigningService
|
||||
@ -80,6 +81,8 @@ interface CryptoService {
|
||||
|
||||
fun getLiveGlobalCryptoConfig(): LiveData<GlobalCryptoConfig>
|
||||
|
||||
fun supportsDisablingKeyGossiping(): Boolean
|
||||
|
||||
/**
|
||||
* Enable or disable key gossiping.
|
||||
* Default is true.
|
||||
@ -186,6 +189,8 @@ interface CryptoService {
|
||||
fun addNewSessionListener(newSessionListener: NewSessionListener)
|
||||
fun removeSessionListener(listener: NewSessionListener)
|
||||
|
||||
fun supportKeyRequestInspection(): Boolean
|
||||
|
||||
fun getOutgoingRoomKeyRequests(): List<OutgoingKeyRequest>
|
||||
fun getOutgoingRoomKeyRequestsPaged(): LiveData<PagedList<OutgoingKeyRequest>>
|
||||
|
||||
|
@ -28,4 +28,3 @@ internal class MigrateSessionTo052(realm: DynamicRealm) : RealmMigrator(realm, 5
|
||||
?.setNullable(EventEntityFields.IS_VERIFICATION_STATE_DIRTY, true)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,8 @@ import org.matrix.android.sdk.api.session.crypto.model.UnsignedDeviceInfo
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction
|
||||
import org.matrix.android.sdk.api.session.events.model.Content
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.toContent
|
||||
import org.matrix.android.sdk.api.session.sync.model.DeviceListResponse
|
||||
import org.matrix.android.sdk.api.session.sync.model.DeviceOneTimeKeysCountSyncResponse
|
||||
import org.matrix.android.sdk.api.session.sync.model.ToDeviceSyncResponse
|
||||
@ -439,6 +441,19 @@ internal class OlmMachine @Inject constructor(
|
||||
if (event.roomId.isNullOrBlank()) {
|
||||
throw MXCryptoError.Base(MXCryptoError.ErrorType.MISSING_FIELDS, MXCryptoError.MISSING_FIELDS_REASON)
|
||||
}
|
||||
if (event.isRedacted()) {
|
||||
// we shouldn't attempt to decrypt a redacted event because the content is cleared and decryption will fail because of null algorithm
|
||||
// Workaround until https://github.com/matrix-org/matrix-rust-sdk/issues/1642
|
||||
return@withContext MXEventDecryptionResult(
|
||||
clearEvent = mapOf(
|
||||
"room_id" to event.roomId,
|
||||
"type" to EventType.MESSAGE,
|
||||
"content" to emptyMap<String, Any>(),
|
||||
"unsigned" to event.unsignedData.toContent()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val serializedEvent = adapter.toJson(event)
|
||||
val decrypted = inner.decryptRoomEvent(serializedEvent, event.roomId, false, false)
|
||||
|
||||
@ -493,7 +508,7 @@ internal class OlmMachine @Inject constructor(
|
||||
ShieldColor.RED -> {
|
||||
when (this.message) {
|
||||
"Encrypted by an unverified device." -> MessageVerificationState.UN_SIGNED_DEVICE
|
||||
"Encrypted by a device not verified by its owner." -> MessageVerificationState.UN_SIGNED_DEVICE_OF_VERIFIED_USER
|
||||
"Encrypted by a device not verified by its owner." -> MessageVerificationState.UN_SIGNED_DEVICE
|
||||
"Encrypted by an unknown or deleted device." -> MessageVerificationState.UNKNOWN_DEVICE
|
||||
else -> MessageVerificationState.UN_SIGNED_DEVICE
|
||||
}
|
||||
|
@ -53,7 +53,6 @@ import org.matrix.android.sdk.api.session.crypto.model.IncomingRoomKeyRequest
|
||||
import org.matrix.android.sdk.api.session.crypto.model.MXEncryptEventContentResult
|
||||
import org.matrix.android.sdk.api.session.crypto.model.MXEventDecryptionResult
|
||||
import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap
|
||||
import org.matrix.android.sdk.api.session.crypto.model.TrailType
|
||||
import org.matrix.android.sdk.api.session.events.model.Content
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
@ -141,6 +140,8 @@ internal class RustCryptoService @Inject constructor(
|
||||
private val isStarting = AtomicBoolean(false)
|
||||
private val isStarted = AtomicBoolean(false)
|
||||
|
||||
override fun name() = "rust-sdk"
|
||||
|
||||
override suspend fun onStateEvent(roomId: String, event: Event, cryptoStoreAggregator: CryptoStoreAggregator?) {
|
||||
when (event.type) {
|
||||
EventType.STATE_ROOM_ENCRYPTION -> onRoomEncryptionEvent(roomId, event)
|
||||
@ -510,8 +511,8 @@ internal class RustCryptoService @Inject constructor(
|
||||
// } catch (throwable: Throwable) {
|
||||
// Timber.e(throwable, "## CRYPTO | onRoomEncryptionEvent ERROR FAILED TO SETUP CRYPTO ")
|
||||
// } finally {
|
||||
val userIds = getRoomUserIds(roomId)
|
||||
setEncryptionInRoom(roomId, event.content?.toModel<EncryptionEventContent>(), userIds)
|
||||
val userIds = getRoomUserIds(roomId)
|
||||
setEncryptionInRoom(roomId, event.content?.toModel<EncryptionEventContent>(), userIds)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
@ -559,7 +560,7 @@ internal class RustCryptoService @Inject constructor(
|
||||
// know what other servers are in the room at the time they've been invited.
|
||||
// They therefore will not send device updates if a user logs in whilst
|
||||
// their state is invite.
|
||||
olmMachine.updateTrackedUsers(listOf(userId))
|
||||
olmMachine.updateTrackedUsers(listOf(userId))
|
||||
} else {
|
||||
// nop
|
||||
}
|
||||
@ -651,8 +652,8 @@ internal class RustCryptoService @Inject constructor(
|
||||
this.verificationService.onEvent(null, event)
|
||||
}
|
||||
}
|
||||
liveEventManager.get().dispatchOnLiveToDevice(event)
|
||||
}
|
||||
liveEventManager.get().dispatchOnLiveToDevice(event)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -717,12 +718,14 @@ internal class RustCryptoService @Inject constructor(
|
||||
return cryptoStore.getLiveGlobalCryptoConfig()
|
||||
}
|
||||
|
||||
// Until https://github.com/matrix-org/matrix-rust-sdk/issues/1364
|
||||
override fun supportsDisablingKeyGossiping() = false
|
||||
override fun enableKeyGossiping(enable: Boolean) {
|
||||
cryptoStore.enableKeyGossiping(enable)
|
||||
if (!enable) throw UnsupportedOperationException("Not supported by rust")
|
||||
}
|
||||
|
||||
override fun isKeyGossipingEnabled(): Boolean {
|
||||
return cryptoStore.isKeyGossipingEnabled()
|
||||
return true
|
||||
}
|
||||
|
||||
override fun supportsShareKeysOnInvite() = false
|
||||
@ -730,10 +733,9 @@ internal class RustCryptoService @Inject constructor(
|
||||
override fun supportsKeyWithheld() = true
|
||||
override fun supportsForwardedKeyWiththeld() = false
|
||||
|
||||
|
||||
override fun enableShareKeyOnInvite(enable: Boolean) {
|
||||
if (enable && !supportsShareKeysOnInvite()) {
|
||||
throw java.lang.UnsupportedOperationException("Enable share key on invite not implemented in rust");
|
||||
throw java.lang.UnsupportedOperationException("Enable share key on invite not implemented in rust")
|
||||
}
|
||||
}
|
||||
|
||||
@ -844,19 +846,20 @@ internal class RustCryptoService @Inject constructor(
|
||||
return "DefaultCryptoService of $myUserId ($deviceId)"
|
||||
}
|
||||
|
||||
// Until https://github.com/matrix-org/matrix-rust-sdk/issues/701
|
||||
// https://github.com/matrix-org/matrix-rust-sdk/issues/702
|
||||
override fun supportKeyRequestInspection() = false
|
||||
override fun getOutgoingRoomKeyRequests(): List<OutgoingKeyRequest> {
|
||||
return cryptoStore.getOutgoingRoomKeyRequests()
|
||||
throw UnsupportedOperationException("Not supported by rust")
|
||||
}
|
||||
|
||||
override fun getOutgoingRoomKeyRequestsPaged(): LiveData<PagedList<OutgoingKeyRequest>> {
|
||||
return cryptoStore.getOutgoingRoomKeyRequestsPaged()
|
||||
throw UnsupportedOperationException("Not supported by rust")
|
||||
// return cryptoStore.getOutgoingRoomKeyRequestsPaged()
|
||||
}
|
||||
|
||||
override fun getIncomingRoomKeyRequestsPaged(): LiveData<PagedList<IncomingRoomKeyRequest>> {
|
||||
return cryptoStore.getGossipingEventsTrail(TrailType.IncomingKeyRequest) {
|
||||
IncomingRoomKeyRequest.fromEvent(it)
|
||||
?: IncomingRoomKeyRequest(localCreationTimestamp = 0L)
|
||||
}
|
||||
throw UnsupportedOperationException("Not supported by rust")
|
||||
}
|
||||
|
||||
override suspend fun manuallyAcceptRoomKeyRequest(request: IncomingRoomKeyRequest) {
|
||||
@ -864,25 +867,23 @@ internal class RustCryptoService @Inject constructor(
|
||||
}
|
||||
|
||||
override fun getIncomingRoomKeyRequests(): List<IncomingRoomKeyRequest> {
|
||||
return emptyList()
|
||||
throw UnsupportedOperationException("Not supported by rust")
|
||||
}
|
||||
|
||||
override fun getGossipingEventsTrail(): LiveData<PagedList<AuditTrail>> {
|
||||
return cryptoStore.getGossipingEventsTrail()
|
||||
throw UnsupportedOperationException("Not supported by rust")
|
||||
}
|
||||
|
||||
override fun getGossipingEvents(): List<AuditTrail> {
|
||||
return cryptoStore.getGossipingEvents()
|
||||
throw UnsupportedOperationException("Not supported by rust")
|
||||
}
|
||||
|
||||
override fun getSharedWithInfo(roomId: String?, sessionId: String): MXUsersDevicesMap<Int> {
|
||||
// TODO not exposed in rust?
|
||||
return cryptoStore.getSharedWithInfo(roomId, sessionId)
|
||||
throw UnsupportedOperationException("Not supported by rust")
|
||||
}
|
||||
|
||||
override fun getWithHeldMegolmSession(roomId: String, sessionId: String): RoomKeyWithHeldContent? {
|
||||
// TODO not exposed in rust.
|
||||
return cryptoStore.getWithHeldMegolmSession(roomId, sessionId)
|
||||
throw UnsupportedOperationException("Not supported by rust")
|
||||
}
|
||||
|
||||
override fun logDbUsageInfo() {
|
||||
|
@ -242,6 +242,9 @@ class BugReporter @Inject constructor(
|
||||
activeSessionHolder.getSafeActiveSession()
|
||||
?.takeIf { !mIsCancelled && withKeyRequestHistory }
|
||||
?.cryptoService()
|
||||
?.takeIf {
|
||||
it.supportKeyRequestInspection()
|
||||
}
|
||||
?.getGossipingEvents()
|
||||
?.let { GossipingEventsSerializer().serialize(it) }
|
||||
?.toByteArray()
|
||||
|
@ -187,6 +187,7 @@ class VectorPreferences @Inject constructor(
|
||||
const val SETTINGS_PREF_SPACE_CATEGORY = "SETTINGS_PREF_SPACE_CATEGORY"
|
||||
|
||||
private const val SETTINGS_DEVELOPER_MODE_PREFERENCE_KEY = "SETTINGS_DEVELOPER_MODE_PREFERENCE_KEY"
|
||||
const val SETTINGS_DEVELOPER_MODE_KEY_REQUEST_AUDIT_KEY = "SETTINGS_DEVELOPER_MODE_KEY_REQUEST_AUDIT_KEY"
|
||||
private const val SETTINGS_LABS_SHOW_HIDDEN_EVENTS_PREFERENCE_KEY = "SETTINGS_LABS_SHOW_HIDDEN_EVENTS_PREFERENCE_KEY"
|
||||
private const val SETTINGS_LABS_ENABLE_SWIPE_TO_REPLY = "SETTINGS_LABS_ENABLE_SWIPE_TO_REPLY"
|
||||
private const val SETTINGS_DEVELOPER_MODE_FAIL_FAST_PREFERENCE_KEY = "SETTINGS_DEVELOPER_MODE_FAIL_FAST_PREFERENCE_KEY"
|
||||
|
@ -73,6 +73,10 @@ class VectorSettingsAdvancedSettingsFragment :
|
||||
copyToClipboard(requireActivity(), session.sessionParams.credentials.accessToken)
|
||||
true
|
||||
}
|
||||
|
||||
findPreference<VectorPreference>(VectorPreferences.SETTINGS_DEVELOPER_MODE_KEY_REQUEST_AUDIT_KEY)?.apply {
|
||||
isVisible = session.cryptoService().supportKeyRequestInspection()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupRageShakeSection() {
|
||||
|
@ -52,11 +52,13 @@ class GossipingEventsPaperTrailViewModel @AssistedInject constructor(
|
||||
setState {
|
||||
copy(events = Loading())
|
||||
}
|
||||
session.cryptoService().getGossipingEventsTrail()
|
||||
.asFlow()
|
||||
.execute {
|
||||
copy(events = it)
|
||||
}
|
||||
if (session.cryptoService().supportKeyRequestInspection()) {
|
||||
session.cryptoService().getGossipingEventsTrail()
|
||||
.asFlow()
|
||||
.execute {
|
||||
copy(events = it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun handle(action: EmptyAction) {}
|
||||
|
@ -90,6 +90,7 @@
|
||||
|
||||
<im.vector.app.core.preference.VectorPreference
|
||||
android:persistent="false"
|
||||
android:key="SETTINGS_DEVELOPER_MODE_KEY_REQUEST_AUDIT_KEY"
|
||||
android:title="@string/settings_key_requests"
|
||||
app:fragment="im.vector.app.features.settings.devtools.KeyRequestsFragment" />
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user