Merge remote-tracking branch 'origin/develop' into dependency-cleanup
This commit is contained in:
commit
9ce9ad6d3a
|
@ -36,7 +36,7 @@ Other changes
|
|||
- Reformatted project code ([#5953](https://github.com/vector-im/element-android/issues/5953))
|
||||
- Update check for server-side threads support to match spec. ([#5997](https://github.com/vector-im/element-android/issues/5997))
|
||||
- Setup detekt ([#6038](https://github.com/vector-im/element-android/issues/6038))
|
||||
- Notify the user for each new message ([#46312](https://github.com/vector-im/element-android/issues/46312))
|
||||
- Notify the user for each new message ([#4632](https://github.com/vector-im/element-android/issues/4632))
|
||||
|
||||
|
||||
Changes in Element v1.4.14 (2022-05-05)
|
||||
|
|
|
@ -27,7 +27,7 @@ buildscript {
|
|||
classpath 'com.google.gms:google-services:4.3.10'
|
||||
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.3'
|
||||
classpath 'com.google.android.gms:oss-licenses-plugin:0.10.5'
|
||||
classpath "com.likethesalad.android:stem-plugin:2.0.0"
|
||||
classpath "com.likethesalad.android:stem-plugin:2.1.1"
|
||||
classpath 'org.owasp:dependency-check-gradle:7.1.0.1'
|
||||
classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.6.21"
|
||||
classpath "org.jetbrains.kotlinx:kotlinx-knit:0.4.0"
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Adds email input and verification screens to the new FTUE onboarding flow
|
|
@ -0,0 +1 @@
|
|||
FTUE - Adds the redesigned Sign In screen
|
|
@ -0,0 +1 @@
|
|||
FTUE - Overrides sign up flow ordering for matrix.org only
|
|
@ -0,0 +1 @@
|
|||
Use fixed text size in read receipt counter
|
|
@ -0,0 +1 @@
|
|||
Live location sharing: navigation from timeline to map screen
|
|
@ -0,0 +1 @@
|
|||
Revert: Use member name instead of room name in DM creation item
|
|
@ -0,0 +1 @@
|
|||
Poll refactoring with unit tests
|
|
@ -0,0 +1 @@
|
|||
Improve replay attacks and reduce duplicate message index errors
|
|
@ -0,0 +1 @@
|
|||
Test: Ensure calling 'fail()' is not caught by the catch block
|
|
@ -0,0 +1 @@
|
|||
Labs flag for enabling live location sharing
|
|
@ -0,0 +1 @@
|
|||
Excludes transitive optional non FOSS google location dependency from fdroid builds
|
|
@ -0,0 +1 @@
|
|||
Glide - Use current drawable while loading new static map image
|
|
@ -0,0 +1 @@
|
|||
Fix sending multiple invites to a room reaching only one or two people
|
|
@ -0,0 +1 @@
|
|||
[Live location sharing] Update entity in DB when a live is timed out
|
|
@ -0,0 +1 @@
|
|||
Prevent widget web view from reloading on screen / orientation change
|
|
@ -0,0 +1 @@
|
|||
Downgrade gradle from 7.2.0 to 7.1.3
|
|
@ -0,0 +1 @@
|
|||
Fix decrypting redacted event from sending errors
|
|
@ -7,7 +7,10 @@ ext.versions = [
|
|||
'targetCompat' : JavaVersion.VERSION_11,
|
||||
]
|
||||
|
||||
def gradle = "7.2.0"
|
||||
|
||||
// Pinned to 7.1.3 because of https://github.com/vector-im/element-android/issues/6142
|
||||
// Please test carefully before upgrading again.
|
||||
def gradle = "7.1.3"
|
||||
// Ref: https://kotlinlang.org/releases.html
|
||||
def kotlin = "1.6.21"
|
||||
def kotlinCoroutines = "1.6.1"
|
||||
|
@ -23,7 +26,7 @@ def mavericks = "2.6.1"
|
|||
def glide = "4.13.2"
|
||||
def bigImageViewer = "1.8.1"
|
||||
def jjwt = "0.11.5"
|
||||
def vanniktechEmoji = "0.9.0"
|
||||
def vanniktechEmoji = "0.13.0"
|
||||
|
||||
// Testing
|
||||
def mockk = "1.12.4"
|
||||
|
@ -51,7 +54,7 @@ ext.libs = [
|
|||
'recyclerview' : "androidx.recyclerview:recyclerview:1.2.1",
|
||||
'exifinterface' : "androidx.exifinterface:exifinterface:1.3.3",
|
||||
'fragmentKtx' : "androidx.fragment:fragment-ktx:1.4.1",
|
||||
'constraintLayout' : "androidx.constraintlayout:constraintlayout:2.1.3",
|
||||
'constraintLayout' : "androidx.constraintlayout:constraintlayout:2.1.4",
|
||||
'work' : "androidx.work:work-runtime-ktx:2.7.1",
|
||||
'autoFill' : "androidx.autofill:autofill:1.1.0",
|
||||
'preferenceKtx' : "androidx.preference:preference-ktx:1.2.0",
|
||||
|
@ -110,6 +113,10 @@ ext.libs = [
|
|||
'mavericks' : "com.airbnb.android:mavericks:$mavericks",
|
||||
'mavericksTesting' : "com.airbnb.android:mavericks-testing:$mavericks"
|
||||
],
|
||||
maplibre : [
|
||||
'androidSdk' : "org.maplibre.gl:android-sdk:9.5.2",
|
||||
'pluginAnnotation' : "org.maplibre.gl:android-plugin-annotation-v9:1.0.0"
|
||||
],
|
||||
mockk : [
|
||||
'mockk' : "io.mockk:mockk:$mockk",
|
||||
'mockkAndroid' : "io.mockk:mockk-android:$mockk"
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape>
|
||||
<gradient
|
||||
android:angle="@integer/rtl_mirror_flip"
|
||||
android:endColor="#55DFD1FF"
|
||||
android:startColor="#55A5F2E0" />
|
||||
</shape>
|
||||
</item>
|
||||
<item>
|
||||
<shape>
|
||||
<gradient
|
||||
android:angle="90"
|
||||
android:endColor="@android:color/transparent"
|
||||
android:startColor="?android:colorBackground" />
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<style name="TimelineContentStubBaseParams">
|
||||
<item name="android:layout_width">match_parent</item>
|
||||
|
@ -33,5 +33,8 @@
|
|||
<item name="android:gravity">center</item>
|
||||
</style>
|
||||
|
||||
<style name="TimelineFixedSizeCaptionStyle" parent="@style/Widget.Vector.TextView.Caption">
|
||||
<item name="android:textSize" tools:ignore="SpUsage">12dp</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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
|
||||
|
||||
import junit.framework.TestCase.fail
|
||||
|
||||
/**
|
||||
* Will fail the test if invoking [block] is not throwing a Throwable.
|
||||
*
|
||||
* @param message the failure message, if the block does not throw any Throwable
|
||||
* @param failureBlock a Lambda to be able to do extra check on the thrown Throwable
|
||||
* @param block the block to test
|
||||
*/
|
||||
internal suspend fun mustFail(
|
||||
message: String = "must fail",
|
||||
failureBlock: ((Throwable) -> Unit)? = null,
|
||||
block: suspend () -> Unit,
|
||||
) {
|
||||
val isSuccess = try {
|
||||
block.invoke()
|
||||
true
|
||||
} catch (throwable: Throwable) {
|
||||
failureBlock?.invoke(throwable)
|
||||
false
|
||||
}
|
||||
|
||||
if (isSuccess) {
|
||||
fail(message)
|
||||
}
|
||||
}
|
|
@ -96,7 +96,7 @@ class CommonTestHelper(context: Context) {
|
|||
/**
|
||||
* This methods init the event stream and check for initial sync
|
||||
*
|
||||
* @param session the session to sync
|
||||
* @param session the session to sync
|
||||
*/
|
||||
fun syncSession(session: Session, timeout: Long = TestConstants.timeOutMillis * 10) {
|
||||
val lock = CountDownLatch(1)
|
||||
|
@ -119,7 +119,7 @@ class CommonTestHelper(context: Context) {
|
|||
/**
|
||||
* This methods clear the cache and waits for initialSync
|
||||
*
|
||||
* @param session the session to sync
|
||||
* @param session the session to sync
|
||||
*/
|
||||
fun clearCacheAndSync(session: Session, timeout: Long = TestConstants.timeOutMillis) {
|
||||
waitWithLatch(timeout) { latch ->
|
||||
|
@ -142,8 +142,8 @@ class CommonTestHelper(context: Context) {
|
|||
/**
|
||||
* Sends text messages in a room
|
||||
*
|
||||
* @param room the room where to send the messages
|
||||
* @param message the message to send
|
||||
* @param room the room where to send the messages
|
||||
* @param message the message to send
|
||||
* @param nbOfMessages the number of time the message will be sent
|
||||
*/
|
||||
fun sendTextMessage(room: Room, message: String, nbOfMessages: Int, timeout: Long = TestConstants.timeOutMillis): List<TimelineEvent> {
|
||||
|
@ -207,8 +207,8 @@ class CommonTestHelper(context: Context) {
|
|||
|
||||
/**
|
||||
* Reply in a thread
|
||||
* @param room the room where to send the messages
|
||||
* @param message the message to send
|
||||
* @param room the room where to send the messages
|
||||
* @param message the message to send
|
||||
* @param numberOfMessages the number of time the message will be sent
|
||||
*/
|
||||
fun replyInThreadMessage(
|
||||
|
@ -232,8 +232,8 @@ class CommonTestHelper(context: Context) {
|
|||
* Creates a unique account
|
||||
*
|
||||
* @param userNamePrefix the user name prefix
|
||||
* @param password the password
|
||||
* @param testParams test params about the session
|
||||
* @param password the password
|
||||
* @param testParams test params about the session
|
||||
* @return the session associated with the newly created account
|
||||
*/
|
||||
private fun createAccount(userNamePrefix: String,
|
||||
|
@ -251,8 +251,8 @@ class CommonTestHelper(context: Context) {
|
|||
/**
|
||||
* Logs into an existing account
|
||||
*
|
||||
* @param userId the userId to log in
|
||||
* @param password the password to log in
|
||||
* @param userId the userId to log in
|
||||
* @param password the password to log in
|
||||
* @param testParams test params about the session
|
||||
* @return the session associated with the existing account
|
||||
*/
|
||||
|
@ -267,8 +267,8 @@ class CommonTestHelper(context: Context) {
|
|||
/**
|
||||
* Create an account and a dedicated session
|
||||
*
|
||||
* @param userName the account username
|
||||
* @param password the password
|
||||
* @param userName the account username
|
||||
* @param password the password
|
||||
* @param sessionTestParams parameters for the test
|
||||
*/
|
||||
private fun createAccountAndSync(userName: String,
|
||||
|
@ -305,8 +305,8 @@ class CommonTestHelper(context: Context) {
|
|||
/**
|
||||
* Start an account login
|
||||
*
|
||||
* @param userName the account username
|
||||
* @param password the password
|
||||
* @param userName the account username
|
||||
* @param password the password
|
||||
* @param sessionTestParams session test params
|
||||
*/
|
||||
private fun logAccountAndSync(userName: String,
|
||||
|
|
|
@ -40,6 +40,9 @@ class RetryTestRule(val retryCount: Int = 3) : TestRule {
|
|||
for (i in 0 until retryCount) {
|
||||
try {
|
||||
base.evaluate()
|
||||
if (i > 0) {
|
||||
println("Retried test $i times")
|
||||
}
|
||||
return
|
||||
} catch (t: Throwable) {
|
||||
caughtThrowable = t
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright 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 androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import org.junit.Assert
|
||||
import org.junit.FixMethodOrder
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.MethodSorters
|
||||
import org.matrix.android.sdk.InstrumentedTest
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.session.getRoom
|
||||
import org.matrix.android.sdk.api.session.room.getTimelineEvent
|
||||
import org.matrix.android.sdk.common.CommonTestHelper
|
||||
import org.matrix.android.sdk.common.CryptoTestHelper
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@FixMethodOrder(MethodSorters.JVM)
|
||||
class DecryptRedactedEventTest : InstrumentedTest {
|
||||
|
||||
@Test
|
||||
fun doNotFailToDecryptRedactedEvent() {
|
||||
val testHelper = CommonTestHelper(context())
|
||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
||||
|
||||
val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
||||
val e2eRoomID = testData.roomId
|
||||
val aliceSession = testData.firstSession
|
||||
val bobSession = testData.secondSession!!
|
||||
|
||||
val roomALicePOV = aliceSession.getRoom(e2eRoomID)!!
|
||||
val timelineEvent = testHelper.sendTextMessage(roomALicePOV, "Hello", 1).first()
|
||||
val redactionReason = "Wrong Room"
|
||||
roomALicePOV.sendService().redactEvent(timelineEvent.root, redactionReason)
|
||||
|
||||
// get the event from bob
|
||||
testHelper.waitWithLatch {
|
||||
testHelper.retryPeriodicallyWithLatch(it) {
|
||||
bobSession.getRoom(e2eRoomID)?.getTimelineEvent(timelineEvent.eventId)?.root?.isRedacted() == true
|
||||
}
|
||||
}
|
||||
|
||||
val eventBobPov = bobSession.getRoom(e2eRoomID)?.getTimelineEvent(timelineEvent.eventId)!!
|
||||
|
||||
testHelper.runBlockingTest {
|
||||
try {
|
||||
val result = bobSession.cryptoService().decryptEvent(eventBobPov.root, "")
|
||||
Assert.assertEquals(
|
||||
"Unexpected redacted reason",
|
||||
redactionReason,
|
||||
result.clearEvent.toModel<Event>()?.unsignedData?.redactedEvent?.content?.get("reason")
|
||||
)
|
||||
Assert.assertEquals(
|
||||
"Unexpected Redacted event id",
|
||||
timelineEvent.eventId,
|
||||
result.clearEvent.toModel<Event>()?.unsignedData?.redactedEvent?.redacts
|
||||
)
|
||||
} catch (failure: Throwable) {
|
||||
Assert.fail("Should not throw when decrypting a redacted event")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,6 +23,7 @@ import org.amshove.kluent.fail
|
|||
import org.amshove.kluent.internal.assertEquals
|
||||
import org.junit.Assert
|
||||
import org.junit.FixMethodOrder
|
||||
import org.junit.Ignore
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
@ -62,11 +63,13 @@ import org.matrix.android.sdk.common.RetryTestRule
|
|||
import org.matrix.android.sdk.common.SessionTestParams
|
||||
import org.matrix.android.sdk.common.TestConstants
|
||||
import org.matrix.android.sdk.common.TestMatrixCallback
|
||||
import org.matrix.android.sdk.mustFail
|
||||
import java.util.concurrent.CountDownLatch
|
||||
|
||||
@RunWith(JUnit4::class)
|
||||
@FixMethodOrder(MethodSorters.JVM)
|
||||
@LargeTest
|
||||
@Ignore("This test fails with an unhandled exception thrown from a coroutine which terminates the entire test run.")
|
||||
class E2eeSanityTests : InstrumentedTest {
|
||||
|
||||
@get:Rule val rule = RetryTestRule(3)
|
||||
|
@ -525,10 +528,8 @@ class E2eeSanityTests : InstrumentedTest {
|
|||
|
||||
// Confirm we can decrypt one but not the other
|
||||
testHelper.runBlockingTest {
|
||||
try {
|
||||
mustFail(message = "Should not be able to decrypt event") {
|
||||
newBobSession.cryptoService().decryptEvent(firstEventNewBobPov.root, "")
|
||||
fail("Should not be able to decrypt event")
|
||||
} catch (_: MXCryptoError) {
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
|||
import androidx.test.filters.LargeTest
|
||||
import junit.framework.TestCase.assertNotNull
|
||||
import junit.framework.TestCase.assertTrue
|
||||
import junit.framework.TestCase.fail
|
||||
import org.amshove.kluent.internal.assertEquals
|
||||
import org.junit.Assert
|
||||
import org.junit.Assert.assertNull
|
||||
|
@ -47,6 +46,7 @@ import org.matrix.android.sdk.common.CryptoTestHelper
|
|||
import org.matrix.android.sdk.common.RetryTestRule
|
||||
import org.matrix.android.sdk.common.SessionTestParams
|
||||
import org.matrix.android.sdk.common.TestConstants
|
||||
import org.matrix.android.sdk.mustFail
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@FixMethodOrder(MethodSorters.JVM)
|
||||
|
@ -95,12 +95,10 @@ class KeyShareTests : InstrumentedTest {
|
|||
assertNotNull(receivedEvent)
|
||||
assert(receivedEvent!!.isEncrypted())
|
||||
|
||||
try {
|
||||
commonTestHelper.runBlockingTest {
|
||||
commonTestHelper.runBlockingTest {
|
||||
mustFail {
|
||||
aliceSession2.cryptoService().decryptEvent(receivedEvent.root, "foo")
|
||||
}
|
||||
fail("should fail")
|
||||
} catch (failure: Throwable) {
|
||||
}
|
||||
|
||||
val outgoingRequestsBefore = aliceSession2.cryptoService().getOutgoingRoomKeyRequests()
|
||||
|
@ -168,12 +166,10 @@ class KeyShareTests : InstrumentedTest {
|
|||
}
|
||||
}
|
||||
|
||||
try {
|
||||
commonTestHelper.runBlockingTest {
|
||||
commonTestHelper.runBlockingTest {
|
||||
mustFail {
|
||||
aliceSession2.cryptoService().decryptEvent(receivedEvent.root, "foo")
|
||||
}
|
||||
fail("should fail")
|
||||
} catch (failure: Throwable) {
|
||||
}
|
||||
|
||||
// Mark the device as trusted
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.matrix.android.sdk.common.MockOkHttpInterceptor
|
|||
import org.matrix.android.sdk.common.RetryTestRule
|
||||
import org.matrix.android.sdk.common.SessionTestParams
|
||||
import org.matrix.android.sdk.common.TestConstants
|
||||
import org.matrix.android.sdk.mustFail
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@FixMethodOrder(MethodSorters.JVM)
|
||||
|
@ -96,17 +97,19 @@ class WithHeldTests : InstrumentedTest {
|
|||
// =============================
|
||||
|
||||
// Bob should not be able to decrypt because the keys is withheld
|
||||
try {
|
||||
// .. might need to wait a bit for stability?
|
||||
testHelper.runBlockingTest {
|
||||
// .. might need to wait a bit for stability?
|
||||
testHelper.runBlockingTest {
|
||||
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)
|
||||
}
|
||||
) {
|
||||
bobUnverifiedSession.cryptoService().decryptEvent(eventBobPOV.root, "")
|
||||
}
|
||||
Assert.fail("This session should not be able to decrypt")
|
||||
} catch (failure: Throwable) {
|
||||
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)
|
||||
}
|
||||
|
||||
// Let's see if the reply we got from bob first session is unverified
|
||||
|
@ -137,17 +140,18 @@ class WithHeldTests : InstrumentedTest {
|
|||
}
|
||||
|
||||
// Previous message should still be undecryptable (partially withheld session)
|
||||
try {
|
||||
// .. might need to wait a bit for stability?
|
||||
testHelper.runBlockingTest {
|
||||
// .. might need to wait a bit for stability?
|
||||
testHelper.runBlockingTest {
|
||||
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)
|
||||
}) {
|
||||
bobUnverifiedSession.cryptoService().decryptEvent(eventBobPOV.root, "")
|
||||
}
|
||||
Assert.fail("This session should not be able to decrypt")
|
||||
} catch (failure: Throwable) {
|
||||
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)
|
||||
}
|
||||
|
||||
testHelper.signOutAndClose(aliceSession)
|
||||
|
@ -190,17 +194,18 @@ class WithHeldTests : InstrumentedTest {
|
|||
|
||||
// Previous message should still be undecryptable (partially withheld session)
|
||||
val eventBobPOV = bobSession.getRoom(testData.roomId)?.getTimelineEvent(eventId)
|
||||
try {
|
||||
// .. might need to wait a bit for stability?
|
||||
testHelper.runBlockingTest {
|
||||
// .. might need to wait a bit for stability?
|
||||
testHelper.runBlockingTest {
|
||||
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.NO_OLM.value, technicalMessage)
|
||||
}) {
|
||||
bobSession.cryptoService().decryptEvent(eventBobPOV!!.root, "")
|
||||
}
|
||||
Assert.fail("This session should not be able to decrypt")
|
||||
} catch (failure: Throwable) {
|
||||
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.NO_OLM.value, technicalMessage)
|
||||
}
|
||||
|
||||
// Ensure that alice has marked the session to be shared with bob
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.junit.Assert.assertNotNull
|
|||
import org.junit.Assert.assertNull
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.FixMethodOrder
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.MethodSorters
|
||||
|
@ -45,6 +46,7 @@ import org.matrix.android.sdk.api.session.crypto.model.ImportRoomKeysResult
|
|||
import org.matrix.android.sdk.api.session.getRoom
|
||||
import org.matrix.android.sdk.common.CommonTestHelper
|
||||
import org.matrix.android.sdk.common.CryptoTestHelper
|
||||
import org.matrix.android.sdk.common.RetryTestRule
|
||||
import org.matrix.android.sdk.common.TestConstants
|
||||
import org.matrix.android.sdk.common.TestMatrixCallback
|
||||
import java.util.Collections
|
||||
|
@ -55,6 +57,8 @@ import java.util.concurrent.CountDownLatch
|
|||
@LargeTest
|
||||
class KeysBackupTest : InstrumentedTest {
|
||||
|
||||
@get:Rule val rule = RetryTestRule(3)
|
||||
|
||||
/**
|
||||
* - From doE2ETestWithAliceAndBobInARoomWithEncryptedMessages, we should have no backed up keys
|
||||
* - Check backup keys after having marked one as backed up
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright 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.replayattack
|
||||
|
||||
import androidx.test.filters.LargeTest
|
||||
import org.amshove.kluent.internal.assertFailsWith
|
||||
import org.junit.Assert
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.fail
|
||||
import org.junit.FixMethodOrder
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.JUnit4
|
||||
import org.junit.runners.MethodSorters
|
||||
import org.matrix.android.sdk.InstrumentedTest
|
||||
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
|
||||
import org.matrix.android.sdk.common.CommonTestHelper
|
||||
import org.matrix.android.sdk.common.CryptoTestHelper
|
||||
|
||||
@RunWith(JUnit4::class)
|
||||
@FixMethodOrder(MethodSorters.JVM)
|
||||
@LargeTest
|
||||
class ReplayAttackTest : InstrumentedTest {
|
||||
|
||||
@Test
|
||||
fun replayAttackAlreadyDecryptedEventTest() {
|
||||
val testHelper = CommonTestHelper(context())
|
||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
||||
|
||||
val e2eRoomID = cryptoTestData.roomId
|
||||
|
||||
// Alice
|
||||
val aliceSession = cryptoTestData.firstSession
|
||||
val aliceRoomPOV = aliceSession.roomService().getRoom(e2eRoomID)!!
|
||||
|
||||
// Bob
|
||||
val bobSession = cryptoTestData.secondSession
|
||||
val bobRoomPOV = bobSession!!.roomService().getRoom(e2eRoomID)!!
|
||||
assertEquals(bobRoomPOV.roomSummary()?.joinedMembersCount, 2)
|
||||
|
||||
// Alice will send a message
|
||||
val sentEvents = testHelper.sendTextMessage(aliceRoomPOV, "Hello I will be decrypted twice", 1)
|
||||
assertEquals(1, sentEvents.size)
|
||||
|
||||
val fakeEventId = sentEvents[0].eventId + "_fake"
|
||||
val fakeEventWithTheSameIndex =
|
||||
sentEvents[0].copy(eventId = fakeEventId, root = sentEvents[0].root.copy(eventId = fakeEventId))
|
||||
|
||||
testHelper.runBlockingTest {
|
||||
// Lets assume we are from the main timelineId
|
||||
val timelineId = "timelineId"
|
||||
// Lets decrypt the original event
|
||||
aliceSession.cryptoService().decryptEvent(sentEvents[0].root, timelineId)
|
||||
// Lets decrypt the fake event that will have the same message index
|
||||
val exception = assertFailsWith<MXCryptoError.Base> {
|
||||
// An exception should be thrown while the same index would have been used for the previous decryption
|
||||
aliceSession.cryptoService().decryptEvent(fakeEventWithTheSameIndex.root, timelineId)
|
||||
}
|
||||
assertEquals(MXCryptoError.ErrorType.DUPLICATED_MESSAGE_INDEX, exception.errorType)
|
||||
}
|
||||
cryptoTestData.cleanUp(testHelper)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun replayAttackSameEventTest() {
|
||||
val testHelper = CommonTestHelper(context())
|
||||
val cryptoTestHelper = CryptoTestHelper(testHelper)
|
||||
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(true)
|
||||
|
||||
val e2eRoomID = cryptoTestData.roomId
|
||||
|
||||
// Alice
|
||||
val aliceSession = cryptoTestData.firstSession
|
||||
val aliceRoomPOV = aliceSession.roomService().getRoom(e2eRoomID)!!
|
||||
|
||||
// Bob
|
||||
val bobSession = cryptoTestData.secondSession
|
||||
val bobRoomPOV = bobSession!!.roomService().getRoom(e2eRoomID)!!
|
||||
assertEquals(bobRoomPOV.roomSummary()?.joinedMembersCount, 2)
|
||||
|
||||
// Alice will send a message
|
||||
val sentEvents = testHelper.sendTextMessage(aliceRoomPOV, "Hello I will be decrypted twice", 1)
|
||||
Assert.assertTrue("Message should be sent", sentEvents.size == 1)
|
||||
assertEquals(sentEvents.size, 1)
|
||||
|
||||
testHelper.runBlockingTest {
|
||||
// Lets assume we are from the main timelineId
|
||||
val timelineId = "timelineId"
|
||||
// Lets decrypt the original event
|
||||
aliceSession.cryptoService().decryptEvent(sentEvents[0].root, timelineId)
|
||||
try {
|
||||
// Lets try to decrypt the same event
|
||||
aliceSession.cryptoService().decryptEvent(sentEvents[0].root, timelineId)
|
||||
} catch (ex: Throwable) {
|
||||
fail("Shouldn't throw a decryption error for same event")
|
||||
}
|
||||
}
|
||||
cryptoTestData.cleanUp(testHelper)
|
||||
}
|
||||
}
|
|
@ -195,7 +195,7 @@ data class HomeServerConnectionConfig(
|
|||
* - https://www.ssi.gouv.fr/uploads/2017/07/anssi-guide-recommandations_de_securite_relatives_a_tls-v1.2.pdf
|
||||
* - https://developer.android.com/reference/javax/net/ssl/SSLEngine
|
||||
*
|
||||
* @param tlsLimitations true to use Tls limitations
|
||||
* @param tlsLimitations true to use Tls limitations
|
||||
* @param enableCompatibilityMode set to true for Android < 20
|
||||
* @return this builder
|
||||
*/
|
||||
|
|
|
@ -36,7 +36,7 @@ interface ContentUrlResolver {
|
|||
/**
|
||||
* Get the actual URL for accessing the full-size image of a Matrix media content URI.
|
||||
*
|
||||
* @param contentUrl the Matrix media content URI (in the form of "mxc://...").
|
||||
* @param contentUrl the Matrix media content URI (in the form of "mxc://...").
|
||||
* @return the URL to access the described resource, or null if the url is invalid.
|
||||
*/
|
||||
fun resolveFullSize(contentUrl: String?): String?
|
||||
|
@ -44,7 +44,7 @@ interface ContentUrlResolver {
|
|||
/**
|
||||
* Get the ResolvedMethod to download a URL.
|
||||
*
|
||||
* @param contentUrl the Matrix media content URI (in the form of "mxc://...").
|
||||
* @param contentUrl the Matrix media content URI (in the form of "mxc://...").
|
||||
* @param elementToDecrypt Encryption data may be required if you use a content scanner
|
||||
* @return the Method to access resource, or null if invalid
|
||||
*/
|
||||
|
@ -54,9 +54,9 @@ interface ContentUrlResolver {
|
|||
* Get the actual URL for accessing the thumbnail image of a given Matrix media content URI.
|
||||
*
|
||||
* @param contentUrl the Matrix media content URI (in the form of "mxc://...").
|
||||
* @param width the desired width
|
||||
* @param height the desired height
|
||||
* @param method the desired method (METHOD_CROP or METHOD_SCALE)
|
||||
* @param width the desired width
|
||||
* @param height the desired height
|
||||
* @param method the desired method (METHOD_CROP or METHOD_SCALE)
|
||||
* @return the URL to access the described resource, or null if the url is invalid.
|
||||
*/
|
||||
fun resolveThumbnail(contentUrl: String?, width: Int, height: Int, method: ThumbnailMethod): String?
|
||||
|
|
|
@ -33,7 +33,7 @@ interface ContentScannerService {
|
|||
|
||||
/**
|
||||
* Get the current public curve25519 key that the AV server is advertising.
|
||||
* @param callback on success callback containing the server public key
|
||||
* @param forceDownload true to force the SDK to download again the server public key
|
||||
*/
|
||||
suspend fun getServerPublicKey(forceDownload: Boolean = false): String?
|
||||
suspend fun getScanResultForAttachment(mxcUrl: String, fileInfo: ElementToDecrypt? = null): ScanStatusInfo
|
||||
|
|
|
@ -34,7 +34,7 @@ interface KeysBackupService {
|
|||
* Create a new keys backup version and enable it, using the information return from [prepareKeysBackupVersion].
|
||||
*
|
||||
* @param keysBackupCreationInfo the info object from [prepareKeysBackupVersion].
|
||||
* @param callback Asynchronous callback
|
||||
* @param callback Asynchronous callback
|
||||
*/
|
||||
fun createKeysBackupVersion(keysBackupCreationInfo: MegolmBackupCreationInfo,
|
||||
callback: MatrixCallback<KeysVersion>)
|
||||
|
@ -122,7 +122,7 @@ interface KeysBackupService {
|
|||
* Delete a keys backup version. It will delete all backed up keys on the server, and the backup itself.
|
||||
* If we are backing up to this version. Backup will be stopped.
|
||||
*
|
||||
* @param version the backup version to delete.
|
||||
* @param version the backup version to delete.
|
||||
* @param callback Asynchronous callback
|
||||
*/
|
||||
fun deleteBackup(version: String,
|
||||
|
@ -173,12 +173,12 @@ interface KeysBackupService {
|
|||
/**
|
||||
* Restore a backup with a recovery key from a given backup version stored on the homeserver.
|
||||
*
|
||||
* @param keysVersionResult the backup version to restore from.
|
||||
* @param recoveryKey the recovery key to decrypt the retrieved backup.
|
||||
* @param roomId the id of the room to get backup data from.
|
||||
* @param sessionId the id of the session to restore.
|
||||
* @param keysVersionResult the backup version to restore from.
|
||||
* @param recoveryKey the recovery key to decrypt the retrieved backup.
|
||||
* @param roomId the id of the room to get backup data from.
|
||||
* @param sessionId the id of the session to restore.
|
||||
* @param stepProgressListener the step progress listener
|
||||
* @param callback Callback. It provides the number of found keys and the number of successfully imported keys.
|
||||
* @param callback Callback. It provides the number of found keys and the number of successfully imported keys.
|
||||
*/
|
||||
fun restoreKeysWithRecoveryKey(keysVersionResult: KeysVersionResult,
|
||||
recoveryKey: String, roomId: String?,
|
||||
|
|
|
@ -48,8 +48,7 @@ data class IncomingRoomKeyRequest(
|
|||
/**
|
||||
* Factory.
|
||||
*
|
||||
* @param event the event
|
||||
* @param currentTimeMillis the current time in milliseconds
|
||||
* @param trail the AuditTrail data
|
||||
*/
|
||||
fun fromEvent(trail: AuditTrail): IncomingRoomKeyRequest? {
|
||||
return trail
|
||||
|
|
|
@ -46,8 +46,8 @@ class MXUsersDevicesMap<E> {
|
|||
/**
|
||||
* Provides the object for a device id and a user Id.
|
||||
*
|
||||
* @param userId the user id
|
||||
* @param deviceId the device id
|
||||
* @param userId the object id
|
||||
* @return the object
|
||||
*/
|
||||
fun getObject(userId: String?, deviceId: String?): E? {
|
||||
|
@ -59,9 +59,9 @@ class MXUsersDevicesMap<E> {
|
|||
/**
|
||||
* Set an object for a dedicated user Id and device Id.
|
||||
*
|
||||
* @param userId the user Id
|
||||
* @param userId the user Id
|
||||
* @param deviceId the device id
|
||||
* @param o the object to set
|
||||
* @param o the object to set
|
||||
*/
|
||||
fun setObject(userId: String?, deviceId: String?, o: E?) {
|
||||
if (null != o && userId?.isNotBlank() == true && deviceId?.isNotBlank() == true) {
|
||||
|
@ -73,8 +73,8 @@ class MXUsersDevicesMap<E> {
|
|||
/**
|
||||
* Defines the objects map for a user Id.
|
||||
*
|
||||
* @param userId the user id
|
||||
* @param objectsPerDevices the objects maps
|
||||
* @param userId the user id
|
||||
*/
|
||||
fun setObjects(userId: String?, objectsPerDevices: Map<String, E>?) {
|
||||
if (!userId.isNullOrBlank()) {
|
||||
|
|
|
@ -33,7 +33,7 @@ interface FileService {
|
|||
/**
|
||||
* The original file is in cache, but the decrypted files can be deleted for security reason.
|
||||
* To decrypt the file again, call [downloadFile], the encrypted file will not be downloaded again
|
||||
* @param decryptedFileInCache true if the decrypted file is available. Always true for clear files.
|
||||
* @property decryptedFileInCache true if the decrypted file is available. Always true for clear files.
|
||||
*/
|
||||
data class InCache(val decryptedFileInCache: Boolean) : FileState()
|
||||
object Downloading : FileState()
|
||||
|
|
|
@ -74,6 +74,7 @@ interface IdentityService {
|
|||
/**
|
||||
* Submit the code that the identity server has sent to the user (in email or SMS).
|
||||
* Once successful, you will have to call [finalizeBindThreePid]
|
||||
* @param threePid the three pid
|
||||
* @param code the code sent to the user
|
||||
*/
|
||||
suspend fun submitValidationToken(threePid: ThreePid, code: String)
|
||||
|
|
|
@ -99,6 +99,7 @@ interface IntegrationManagerService {
|
|||
* Offers to allow or disallow a native widget domain.
|
||||
* @param widgetType the widget type to check for
|
||||
* @param domain the domain to check for
|
||||
* @param allowed true or false
|
||||
*/
|
||||
suspend fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean)
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ object MatrixLinkify {
|
|||
* Find the matrix spans i.e matrix id , user id ... to display them as URL.
|
||||
*
|
||||
* @param spannable the text in which the matrix items has to be clickable.
|
||||
* @param callback listener to be notified when the span is clicked
|
||||
*/
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
fun addLinks(spannable: Spannable, callback: MatrixPermalinkSpan.Callback?): Boolean {
|
||||
|
|
|
@ -22,8 +22,8 @@ import org.matrix.android.sdk.api.session.permalinks.MatrixPermalinkSpan.Callbac
|
|||
|
||||
/**
|
||||
* This MatrixPermalinkSpan is a clickable span which use a [Callback] to communicate back.
|
||||
* @param url the permalink url tied to the span
|
||||
* @param callback the callback to use.
|
||||
* @property url the permalink url tied to the span
|
||||
* @property callback the callback to use.
|
||||
*/
|
||||
class MatrixPermalinkSpan(private val url: String,
|
||||
private val callback: Callback? = null) : ClickableSpan() {
|
||||
|
|
|
@ -60,6 +60,7 @@ interface PermalinkService {
|
|||
* Creates a permalink for a roomId, including the via parameters.
|
||||
*
|
||||
* @param roomId the room id
|
||||
* @param viaServers the via parameter
|
||||
* @param forceMatrixTo whether we should force using matrix.to base URL
|
||||
*
|
||||
* @return the permalink, or null in case of error
|
||||
|
@ -70,7 +71,7 @@ interface PermalinkService {
|
|||
* Creates a permalink for an event. If you have an event you can use [createPermalink]
|
||||
* Ex: "https://matrix.to/#/!nbzmcXAqpxBXjAdgoX:matrix.org/$1531497316352799BevdV:matrix.org?via=matrix.org"
|
||||
*
|
||||
* @param roomId the id of the room
|
||||
* @param roomId the id of the room
|
||||
* @param eventId the id of the event
|
||||
* @param forceMatrixTo whether we should force using matrix.to base URL
|
||||
*
|
||||
|
@ -90,7 +91,7 @@ interface PermalinkService {
|
|||
* Creates a HTML or Markdown mention span template. Can be used to replace a mention with a permalink to mentioned user.
|
||||
* Ex: "<a href=\"https://matrix.to/#/%1\$s\">%2\$s</a>" or "[%2\$s](https://matrix.to/#/%1\$s)"
|
||||
*
|
||||
* @param type: type of template to create
|
||||
* @param type type of template to create
|
||||
* @param forceMatrixTo whether we should force using matrix.to base URL
|
||||
*
|
||||
* @return the created template
|
||||
|
|
|
@ -47,12 +47,12 @@ interface PushersService {
|
|||
* Add a new Email pusher.
|
||||
* Ref: https://matrix.org/docs/spec/client_server/latest#post-matrix-client-r0-pushers-set
|
||||
*
|
||||
* @param email The email address to send notifications to.
|
||||
* @param lang The preferred language for receiving notifications (e.g. "en" or "en-US").
|
||||
* @param emailBranding The branding placeholder to include in the email communications.
|
||||
* @param appDisplayName A human readable string that will allow the user to identify what application owns this pusher.
|
||||
* @param email The email address to send notifications to.
|
||||
* @param lang The preferred language for receiving notifications (e.g. "en" or "en-US").
|
||||
* @param emailBranding The branding placeholder to include in the email communications.
|
||||
* @param appDisplayName A human readable string that will allow the user to identify what application owns this pusher.
|
||||
* @param deviceDisplayName A human readable string that will allow the user to identify what device owns this pusher.
|
||||
* @param append If true, the homeserver should add another pusher with the given pushkey and App ID in addition
|
||||
* @param append If true, the homeserver should add another pusher with the given pushkey and App ID in addition
|
||||
* to any others with different user IDs. Otherwise, the homeserver must remove any other pushers
|
||||
* with the same App ID and pushkey for different users. Typically We always want to append for
|
||||
* email pushers since we don't want to stop other accounts notifying to the same email address.
|
||||
|
|
|
@ -34,10 +34,11 @@ interface PushRuleService {
|
|||
|
||||
/**
|
||||
* Enables/Disables a push rule and updates the actions if necessary.
|
||||
* @param kind the rule kind
|
||||
* @param ruleId the rule id
|
||||
* @param enable Enables/Disables the rule
|
||||
* @param actions Actions to update if not null
|
||||
*/
|
||||
|
||||
suspend fun updatePushRuleActions(kind: RuleKind, ruleId: String, enable: Boolean, actions: List<Action>?)
|
||||
|
||||
suspend fun removePushRule(kind: RuleKind, ruleId: String)
|
||||
|
|
|
@ -67,7 +67,7 @@ data class RuleSet(
|
|||
/**
|
||||
* Find a rule from its rule Id.
|
||||
*
|
||||
* @param rules the rules list.
|
||||
* @param rules the rules list.
|
||||
* @param ruleId the rule Id.
|
||||
* @return the bing rule if it exists, else null.
|
||||
*/
|
||||
|
|
|
@ -28,7 +28,8 @@ interface RoomCryptoService {
|
|||
|
||||
/**
|
||||
* Enable encryption of the room.
|
||||
* @param Use force to ensure that this algorithm will be used. Otherwise this call
|
||||
* @param algorithm the algorithm to set, default to [MXCRYPTO_ALGORITHM_MEGOLM]
|
||||
* @param force Use force to ensure that this algorithm will be used. Otherwise this call
|
||||
* will throw if encryption is already setup or if the algorithm is not supported. Only to
|
||||
* be used by admins to fix misconfigured encryption.
|
||||
*/
|
||||
|
|
|
@ -22,6 +22,9 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocati
|
|||
* Aggregation info concerning a live location share.
|
||||
*/
|
||||
data class LiveLocationShareAggregatedSummary(
|
||||
/**
|
||||
* Indicate whether the live is currently running.
|
||||
*/
|
||||
val isActive: Boolean?,
|
||||
val endOfLiveTimestampMillis: Long?,
|
||||
val lastLocationDataContent: MessageBeaconLocationDataContent?,
|
||||
|
|
|
@ -71,8 +71,8 @@ interface RelationService {
|
|||
|
||||
/**
|
||||
* Edit a poll.
|
||||
* @param pollType indicates open or closed polls
|
||||
* @param targetEvent The poll event to edit
|
||||
* @param pollType indicates open or closed polls
|
||||
* @param question The edited question
|
||||
* @param options The edited options
|
||||
*/
|
||||
|
@ -84,7 +84,9 @@ interface RelationService {
|
|||
/**
|
||||
* Edit a text message body. Limited to "m.text" contentType.
|
||||
* @param targetEvent The event to edit
|
||||
* @param msgType the message type
|
||||
* @param newBodyText The edited body
|
||||
* @param newBodyAutoMarkdown true to parse markdown on the new body
|
||||
* @param compatibilityBodyText The text that will appear on clients that don't support yet edition
|
||||
*/
|
||||
fun editTextMessage(targetEvent: TimelineEvent,
|
||||
|
@ -153,8 +155,8 @@ interface RelationService {
|
|||
* @param rootThreadEventId the root thread eventId
|
||||
* @param replyInThreadText the reply text
|
||||
* @param msgType the message type: MessageType.MSGTYPE_TEXT (default) or MessageType.MSGTYPE_EMOTE
|
||||
* @param formattedText The formatted body using MessageType#FORMAT_MATRIX_HTML
|
||||
* @param autoMarkdown If true, the SDK will generate a formatted HTML message from the body text if markdown syntax is present
|
||||
* @param formattedText The formatted body using MessageType#FORMAT_MATRIX_HTML
|
||||
* @param eventReplied the event referenced by the reply within a thread
|
||||
*/
|
||||
fun replyInThread(rootThreadEventId: String,
|
||||
|
|
|
@ -58,7 +58,7 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
|
|||
/**
|
||||
* Tell if an user can send an event of a certain type.
|
||||
*
|
||||
* @param userId the id of the user to check for.
|
||||
* @param userId the id of the user to check for.
|
||||
* @param isState true if the event is a state event (ie. state key is not null)
|
||||
* @param eventType the event type to check for
|
||||
* @return true if the user can send this type of event
|
||||
|
|
|
@ -71,7 +71,7 @@ interface ReadService {
|
|||
|
||||
/**
|
||||
* Returns a live list of read receipts for a given event.
|
||||
* @param eventId: the event
|
||||
* @param eventId the event
|
||||
*/
|
||||
fun getEventReadReceiptsLive(eventId: String): LiveData<List<ReadReceipt>>
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@ interface SendService {
|
|||
* @param quotedEvent The event to which we will quote it's content.
|
||||
* @param text the text message to send
|
||||
* @param autoMarkdown If true, the SDK will generate a formatted HTML message from the body text if markdown syntax is present
|
||||
* @param rootThreadEventId when this param is not null, the message will be sent in this specific thread
|
||||
* @return a [Cancelable]
|
||||
*/
|
||||
fun sendQuotedTextMessage(quotedEvent: TimelineEvent, text: String, autoMarkdown: Boolean, rootThreadEventId: String? = null): Cancelable
|
||||
|
|
|
@ -90,23 +90,29 @@ interface StateService {
|
|||
|
||||
/**
|
||||
* Get a state event of the room.
|
||||
* @param eventType An eventType.
|
||||
* @param stateKey the query which will be done on the stateKey
|
||||
*/
|
||||
fun getStateEvent(eventType: String, stateKey: QueryStringValue = QueryStringValue.NoCondition): Event?
|
||||
|
||||
/**
|
||||
* Get a live state event of the room.
|
||||
* @param eventType An eventType.
|
||||
* @param stateKey the query which will be done on the stateKey
|
||||
*/
|
||||
fun getStateEventLive(eventType: String, stateKey: QueryStringValue = QueryStringValue.NoCondition): LiveData<Optional<Event>>
|
||||
|
||||
/**
|
||||
* Get state events of the room.
|
||||
* @param eventTypes Set of eventType. If empty, all state events will be returned
|
||||
* @param stateKey the query which will be done on the stateKey
|
||||
*/
|
||||
fun getStateEvents(eventTypes: Set<String>, stateKey: QueryStringValue = QueryStringValue.NoCondition): List<Event>
|
||||
|
||||
/**
|
||||
* Get live state events of the room.
|
||||
* @param eventTypes Set of eventType to observe. If empty, all state events will be observed
|
||||
* @param stateKey the query which will be done on the stateKey
|
||||
*/
|
||||
fun getStateEventsLive(eventTypes: Set<String>, stateKey: QueryStringValue = QueryStringValue.NoCondition): LiveData<List<Event>>
|
||||
|
||||
|
|
|
@ -90,6 +90,7 @@ data class TimelineEvent(
|
|||
|
||||
/**
|
||||
* Get the metadata associated with a key.
|
||||
* @param T type to cast the metadata to
|
||||
* @param key the key to get the metadata
|
||||
* @return the metadata
|
||||
*/
|
||||
|
|
|
@ -92,7 +92,7 @@ interface SharedSecretStorageService {
|
|||
* Clients MUST ensure that the key is trusted before using it to encrypt secrets.
|
||||
*
|
||||
* @param name The name of the secret
|
||||
* @param secret The secret contents.
|
||||
* @param secretBase64 The secret contents.
|
||||
* @param keys The list of (ID,privateKey) of the keys to use to encrypt the secret.
|
||||
*/
|
||||
suspend fun storeSecret(name: String, secretBase64: String, keys: List<KeyRef>)
|
||||
|
|
|
@ -44,8 +44,8 @@ interface SpaceService {
|
|||
roomAliasLocalPart: String? = null): String
|
||||
|
||||
/**
|
||||
* Get a space from a roomId.
|
||||
* @param spaceId the roomId to look for.
|
||||
* Get a space from a spaceId.
|
||||
* @param spaceId the spaceId to look for.
|
||||
* @return a space with spaceId or null if room type is not space
|
||||
*/
|
||||
fun getSpace(spaceId: String): Space?
|
||||
|
@ -54,21 +54,24 @@ interface SpaceService {
|
|||
* Try to resolve (peek) rooms and subspace in this space.
|
||||
* Use this call get preview of children of this space, particularly useful to get a
|
||||
* preview of rooms that you did not join yet.
|
||||
* @param spaceId the spaceId to look for.
|
||||
*/
|
||||
suspend fun peekSpace(spaceId: String): SpacePeekResult
|
||||
|
||||
/**
|
||||
* Get's information of a space by querying the server.
|
||||
*
|
||||
* @param spaceId the spaceId to look for.
|
||||
* @param suggestedOnly If true, return only child events and rooms where the m.space.child event has suggested: true.
|
||||
* @param limit a client-defined limit to the maximum number of rooms to return per page. Must be a non-negative integer.
|
||||
* @param from: Optional. Pagination token given to retrieve the next set of rooms. Note that if a pagination token is provided,
|
||||
* @param from Optional. Pagination token given to retrieve the next set of rooms. Note that if a pagination token is provided,
|
||||
* then the parameters given for suggested_only and max_depth must be the same.
|
||||
* @param knownStateList when paginating, pass back the m.space.child state events
|
||||
*/
|
||||
suspend fun querySpaceChildren(spaceId: String,
|
||||
suggestedOnly: Boolean? = null,
|
||||
limit: Int? = null,
|
||||
from: String? = null,
|
||||
// when paginating, pass back the m.space.child state events
|
||||
knownStateList: List<Event>? = null): SpaceHierarchyData
|
||||
|
||||
/**
|
||||
|
@ -98,7 +101,10 @@ interface SpaceService {
|
|||
|
||||
/**
|
||||
* Let this room declare that it has a parent.
|
||||
* @param childRoomId the space to set as a child
|
||||
* @param parentSpaceId the parentId which will be set
|
||||
* @param canonical true if it should be the main parent of this room
|
||||
* @param viaServers list of candidate servers that can be used to set the parent
|
||||
* In practice, well behaved rooms should only have one canonical parent, but given this is not enforced:
|
||||
* if multiple are present the client should select the one with the lowest room ID, as determined via a lexicographic utf-8 ordering.
|
||||
*/
|
||||
|
|
|
@ -49,7 +49,7 @@ interface WidgetPostAPIMediator {
|
|||
/**
|
||||
* Send a boolean response.
|
||||
*
|
||||
* @param response the response
|
||||
* @param response the response
|
||||
* @param eventData the modular data
|
||||
*/
|
||||
fun sendBoolResponse(response: Boolean, eventData: JsonDict)
|
||||
|
@ -57,7 +57,7 @@ interface WidgetPostAPIMediator {
|
|||
/**
|
||||
* Send an integer response.
|
||||
*
|
||||
* @param response the response
|
||||
* @param response the response
|
||||
* @param eventData the modular data
|
||||
*/
|
||||
fun sendIntegerResponse(response: Int, eventData: JsonDict)
|
||||
|
@ -65,8 +65,9 @@ interface WidgetPostAPIMediator {
|
|||
/**
|
||||
* Send an object response.
|
||||
*
|
||||
* @param klass the class of the response
|
||||
* @param response the response
|
||||
* @param T the generic type
|
||||
* @param type the type of the response
|
||||
* @param response the response
|
||||
* @param eventData the modular data
|
||||
*/
|
||||
fun <T> sendObjectResponse(type: Type, response: T?, eventData: JsonDict)
|
||||
|
@ -81,7 +82,7 @@ interface WidgetPostAPIMediator {
|
|||
/**
|
||||
* Send an error.
|
||||
*
|
||||
* @param message the error message
|
||||
* @param message the error message
|
||||
* @param eventData the modular data
|
||||
*/
|
||||
fun sendError(message: String, eventData: JsonDict)
|
||||
|
|
|
@ -111,8 +111,8 @@ interface WidgetService {
|
|||
/**
|
||||
* Deactivate a widget in a room. It makes sure you have the rights to handle this.
|
||||
*
|
||||
* @param roomId: the room where you want to deactivate the widget.
|
||||
* @param widgetId: the widget to deactivate.
|
||||
* @param roomId the room where you want to deactivate the widget.
|
||||
* @param widgetId the widget to deactivate.
|
||||
*/
|
||||
suspend fun destroyRoomWidget(roomId: String, widgetId: String)
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ internal class CryptoSessionInfoProvider @Inject constructor(
|
|||
}
|
||||
|
||||
/**
|
||||
* @param roomId the room Id
|
||||
* @param allActive if true return joined as well as invited, if false, only joined
|
||||
*/
|
||||
fun getRoomUserIds(roomId: String, allActive: Boolean): List<String> {
|
||||
|
|
|
@ -508,7 +508,7 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
/**
|
||||
* Provides the device information for a user id and a device Id.
|
||||
*
|
||||
* @param userId the user id
|
||||
* @param userId the user id
|
||||
* @param deviceId the device id
|
||||
*/
|
||||
override fun getDeviceInfo(userId: String, deviceId: String?): CryptoDeviceInfo? {
|
||||
|
@ -538,7 +538,7 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
/**
|
||||
* Set the devices as known.
|
||||
*
|
||||
* @param devices the devices. Note that the verified member of the devices in this list will not be updated by this method.
|
||||
* @param devices the devices. Note that the verified member of the devices in this list will not be updated by this method.
|
||||
* @param callback the asynchronous callback
|
||||
*/
|
||||
override fun setDevicesKnown(devices: List<MXDeviceInfo>, callback: MatrixCallback<Unit>?) {
|
||||
|
@ -576,8 +576,8 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
* Update the blocked/verified state of the given device.
|
||||
*
|
||||
* @param trustLevel the new trust level
|
||||
* @param userId the owner of the device
|
||||
* @param deviceId the unique identifier for the device.
|
||||
* @param userId the owner of the device
|
||||
* @param deviceId the unique identifier for the device.
|
||||
*/
|
||||
override fun setDeviceVerification(trustLevel: DeviceTrustLevel, userId: String, deviceId: String) {
|
||||
setDeviceVerificationAction.handle(trustLevel, userId, deviceId)
|
||||
|
@ -586,10 +586,10 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
/**
|
||||
* Configure a room to use encryption.
|
||||
*
|
||||
* @param roomId the room id to enable encryption in.
|
||||
* @param algorithm the encryption config for the room.
|
||||
* @param roomId the room id to enable encryption in.
|
||||
* @param algorithm the encryption config for the room.
|
||||
* @param inhibitDeviceQuery true to suppress device list query for users in the room (for now)
|
||||
* @param membersId list of members to start tracking their devices
|
||||
* @param membersId list of members to start tracking their devices
|
||||
* @return true if the operation succeeds.
|
||||
*/
|
||||
private suspend fun setEncryptionInRoom(roomId: String,
|
||||
|
@ -687,9 +687,9 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
* Encrypt an event content according to the configuration of the room.
|
||||
*
|
||||
* @param eventContent the content of the event.
|
||||
* @param eventType the type of the event.
|
||||
* @param roomId the room identifier the event will be sent.
|
||||
* @param callback the asynchronous callback
|
||||
* @param eventType the type of the event.
|
||||
* @param roomId the room identifier the event will be sent.
|
||||
* @param callback the asynchronous callback
|
||||
*/
|
||||
override fun encryptEventContent(eventContent: Content,
|
||||
eventType: String,
|
||||
|
@ -742,7 +742,7 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
/**
|
||||
* Decrypt an event.
|
||||
*
|
||||
* @param event the raw event.
|
||||
* @param event the raw event.
|
||||
* @param timeline the id of the timeline where the event is decrypted. It is used to prevent replay attack.
|
||||
* @return the MXEventDecryptionResult data, or throw in case of error
|
||||
*/
|
||||
|
@ -754,7 +754,7 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
/**
|
||||
* Decrypt an event asynchronously.
|
||||
*
|
||||
* @param event the raw event.
|
||||
* @param event the raw event.
|
||||
* @param timeline the id of the timeline where the event is decrypted. It is used to prevent replay attack.
|
||||
* @param callback the callback to return data or null
|
||||
*/
|
||||
|
@ -765,7 +765,7 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
/**
|
||||
* Decrypt an event.
|
||||
*
|
||||
* @param event the raw event.
|
||||
* @param event the raw event.
|
||||
* @param timeline the id of the timeline where the event is decrypted. It is used to prevent replay attack.
|
||||
* @return the MXEventDecryptionResult data, or null in case of error
|
||||
*/
|
||||
|
@ -905,6 +905,7 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
/**
|
||||
* Handle an m.room.encryption event.
|
||||
*
|
||||
* @param roomId the room Id
|
||||
* @param event the encryption event.
|
||||
*/
|
||||
private fun onRoomEncryptionEvent(roomId: String, event: Event) {
|
||||
|
@ -928,6 +929,7 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
/**
|
||||
* Handle a change in the membership state of a member of a room.
|
||||
*
|
||||
* @param roomId the room Id
|
||||
* @param event the membership event causing the change
|
||||
*/
|
||||
private fun onRoomMembershipEvent(roomId: String, event: Event) {
|
||||
|
@ -996,7 +998,7 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
/**
|
||||
* Export the crypto keys.
|
||||
*
|
||||
* @param password the password
|
||||
* @param password the password
|
||||
* @param anIterationCount the encryption iteration count (0 means no encryption)
|
||||
*/
|
||||
private suspend fun exportRoomKeys(password: String, anIterationCount: Int): ByteArray {
|
||||
|
@ -1015,8 +1017,8 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
/**
|
||||
* Import the room keys.
|
||||
*
|
||||
* @param roomKeysAsArray the room keys as array.
|
||||
* @param password the password
|
||||
* @param roomKeysAsArray the room keys as array.
|
||||
* @param password the password
|
||||
* @param progressListener the progress listener
|
||||
* @return the result ImportRoomKeysResult
|
||||
*/
|
||||
|
@ -1066,7 +1068,7 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
* A success means there is no unknown devices.
|
||||
* If there are some unknown devices, a MXCryptoError.UnknownDevice exception is triggered.
|
||||
*
|
||||
* @param userIds the user ids list
|
||||
* @param userIds the user ids list
|
||||
* @param callback the asynchronous callback.
|
||||
*/
|
||||
fun checkUnknownDevices(userIds: List<String>, callback: MatrixCallback<Unit>) {
|
||||
|
@ -1089,7 +1091,7 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
* If false, it can still be overridden per-room.
|
||||
* If true, it overrides the per-room settings.
|
||||
*
|
||||
* @param block true to unilaterally blacklist all
|
||||
* @param block true to unilaterally blacklist all
|
||||
*/
|
||||
override fun setGlobalBlacklistUnverifiedDevices(block: Boolean) {
|
||||
cryptoStore.setGlobalBlacklistUnverifiedDevices(block)
|
||||
|
@ -1129,8 +1131,8 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
/**
|
||||
* Manages the room black-listing for unverified devices.
|
||||
*
|
||||
* @param roomId the room id
|
||||
* @param add true to add the room id to the list, false to remove it.
|
||||
* @param roomId the room id
|
||||
* @param add true to add the room id to the list, false to remove it.
|
||||
*/
|
||||
private fun setRoomBlacklistUnverifiedDevices(roomId: String, add: Boolean) {
|
||||
val roomIds = cryptoStore.getRoomsListBlacklistUnverifiedDevices().toMutableList()
|
||||
|
@ -1149,7 +1151,7 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
/**
|
||||
* Add this room to the ones which don't encrypt messages to unverified devices.
|
||||
*
|
||||
* @param roomId the room id
|
||||
* @param roomId the room id
|
||||
*/
|
||||
override fun setRoomBlacklistUnverifiedDevices(roomId: String) {
|
||||
setRoomBlacklistUnverifiedDevices(roomId, true)
|
||||
|
@ -1158,7 +1160,7 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
/**
|
||||
* Remove this room to the ones which don't encrypt messages to unverified devices.
|
||||
*
|
||||
* @param roomId the room id
|
||||
* @param roomId the room id
|
||||
*/
|
||||
override fun setRoomUnBlacklistUnverifiedDevices(roomId: String) {
|
||||
setRoomBlacklistUnverifiedDevices(roomId, false)
|
||||
|
|
|
@ -170,7 +170,7 @@ internal class DeviceListManager @Inject constructor(
|
|||
* Update the devices list statuses.
|
||||
*
|
||||
* @param changed the user ids list which have new devices
|
||||
* @param left the user ids list which left a room
|
||||
* @param left the user ids list which left a room
|
||||
*/
|
||||
fun handleDeviceListsChanges(changed: Collection<String>, left: Collection<String>) {
|
||||
Timber.v("## CRYPTO: handleDeviceListsChanges changed: ${changed.logLimit()} / left: ${left.logLimit()}")
|
||||
|
@ -223,7 +223,7 @@ internal class DeviceListManager @Inject constructor(
|
|||
/**
|
||||
* The keys download succeeded.
|
||||
*
|
||||
* @param userIds the userIds list
|
||||
* @param userIds the userIds list
|
||||
* @param failures the failure map.
|
||||
*/
|
||||
private fun onKeysDownloadSucceed(userIds: List<String>, failures: Map<String, Map<String, Any>>?): MXUsersDevicesMap<CryptoDeviceInfo> {
|
||||
|
@ -276,7 +276,7 @@ internal class DeviceListManager @Inject constructor(
|
|||
* Download the device keys for a list of users and stores the keys in the MXStore.
|
||||
* It must be called in getEncryptingThreadHandler() thread.
|
||||
*
|
||||
* @param userIds The users to fetch.
|
||||
* @param userIds The users to fetch.
|
||||
* @param forceDownload Always download the keys even if cached.
|
||||
*/
|
||||
suspend fun downloadKeys(userIds: List<String>?, forceDownload: Boolean): MXUsersDevicesMap<CryptoDeviceInfo> {
|
||||
|
@ -421,9 +421,9 @@ internal class DeviceListManager @Inject constructor(
|
|||
* Validate device keys.
|
||||
* This method must called on getEncryptingThreadHandler() thread.
|
||||
*
|
||||
* @param deviceKeys the device keys to validate.
|
||||
* @param userId the id of the user of the device.
|
||||
* @param deviceId the id of the device.
|
||||
* @param deviceKeys the device keys to validate.
|
||||
* @param userId the id of the user of the device.
|
||||
* @param deviceId the id of the device.
|
||||
* @param previouslyStoredDeviceKeys the device keys we received before for this device
|
||||
* @return true if succeeds
|
||||
*/
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap
|
|||
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.content.OlmEventContent
|
||||
import org.matrix.android.sdk.api.session.events.model.toContent
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.internal.crypto.actions.EnsureOlmSessionsForDevicesAction
|
||||
import org.matrix.android.sdk.internal.crypto.actions.MessageEncrypter
|
||||
|
@ -42,7 +43,7 @@ import javax.inject.Inject
|
|||
|
||||
private const val SEND_TO_DEVICE_RETRY_COUNT = 3
|
||||
|
||||
private val loggerTag = LoggerTag("CryptoSyncHandler", LoggerTag.CRYPTO)
|
||||
private val loggerTag = LoggerTag("EventDecryptor", LoggerTag.CRYPTO)
|
||||
|
||||
@SessionScope
|
||||
internal class EventDecryptor @Inject constructor(
|
||||
|
@ -72,7 +73,7 @@ internal class EventDecryptor @Inject constructor(
|
|||
/**
|
||||
* Decrypt an event.
|
||||
*
|
||||
* @param event the raw event.
|
||||
* @param event the raw event.
|
||||
* @param timeline the id of the timeline where the event is decrypted. It is used to prevent replay attack.
|
||||
* @return the MXEventDecryptionResult data, or throw in case of error
|
||||
*/
|
||||
|
@ -84,7 +85,7 @@ internal class EventDecryptor @Inject constructor(
|
|||
/**
|
||||
* Decrypt an event asynchronously.
|
||||
*
|
||||
* @param event the raw event.
|
||||
* @param event the raw event.
|
||||
* @param timeline the id of the timeline where the event is decrypted. It is used to prevent replay attack.
|
||||
* @param callback the callback to return data or null
|
||||
*/
|
||||
|
@ -100,7 +101,7 @@ internal class EventDecryptor @Inject constructor(
|
|||
/**
|
||||
* Decrypt an event.
|
||||
*
|
||||
* @param event the raw event.
|
||||
* @param event the raw event.
|
||||
* @param timeline the id of the timeline where the event is decrypted. It is used to prevent replay attack.
|
||||
* @return the MXEventDecryptionResult data, or null in case of error
|
||||
*/
|
||||
|
@ -110,6 +111,16 @@ internal class EventDecryptor @Inject constructor(
|
|||
if (eventContent == null) {
|
||||
Timber.tag(loggerTag.value).e("decryptEvent : empty event content")
|
||||
throw MXCryptoError.Base(MXCryptoError.ErrorType.BAD_ENCRYPTED_MESSAGE, MXCryptoError.BAD_ENCRYPTED_MESSAGE_REASON)
|
||||
} else 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
|
||||
return MXEventDecryptionResult(
|
||||
clearEvent = mapOf(
|
||||
"room_id" to event.roomId.orEmpty(),
|
||||
"type" to EventType.MESSAGE,
|
||||
"content" to emptyMap<String, Any>(),
|
||||
"unsigned" to event.unsignedData.toContent()
|
||||
)
|
||||
)
|
||||
} else {
|
||||
val algorithm = eventContent["algorithm"]?.toString()
|
||||
val alg = roomDecryptorProvider.getOrCreateRoomDecryptor(event.roomId, algorithm)
|
||||
|
|
|
@ -68,7 +68,7 @@ internal object MXMegolmExportEncryption {
|
|||
/**
|
||||
* Decrypt a megolm key file.
|
||||
*
|
||||
* @param data the data to decrypt
|
||||
* @param data the data to decrypt
|
||||
* @param password the password.
|
||||
* @return the decrypted output.
|
||||
* @throws Exception the failure reason
|
||||
|
@ -138,9 +138,9 @@ internal object MXMegolmExportEncryption {
|
|||
/**
|
||||
* Encrypt a string into the megolm export format.
|
||||
*
|
||||
* @param data the data to encrypt.
|
||||
* @param password the password
|
||||
* @param kdf_rounds the iteration count
|
||||
* @param data the data to encrypt.
|
||||
* @param password the password
|
||||
* @param kdfRounds the iteration count
|
||||
* @return the encrypted data
|
||||
* @throws Exception the failure reason
|
||||
*/
|
||||
|
@ -304,9 +304,9 @@ internal object MXMegolmExportEncryption {
|
|||
/**
|
||||
* Derive the AES and HMAC-SHA-256 keys for the file.
|
||||
*
|
||||
* @param salt salt for pbkdf
|
||||
* @param salt salt for pbkdf
|
||||
* @param iterations number of pbkdf iterations
|
||||
* @param password password
|
||||
* @param password password
|
||||
* @return the derived keys
|
||||
*/
|
||||
@Throws(Exception::class)
|
||||
|
|
|
@ -96,8 +96,9 @@ internal class MXOlmDevice @Inject constructor(
|
|||
// So, store these message indexes per timeline id.
|
||||
//
|
||||
// The first level keys are timeline ids.
|
||||
// The second level keys are strings of form "<senderKey>|<session_id>|<message_index>"
|
||||
private val inboundGroupSessionMessageIndexes: MutableMap<String, MutableSet<String>> = HashMap()
|
||||
// The second level values is a Map that represents:
|
||||
// "<senderKey>|<session_id>|<roomId>|<message_index>" --> eventId
|
||||
private val inboundGroupSessionMessageIndexes: MutableMap<String, MutableMap<String, String>> = HashMap()
|
||||
|
||||
init {
|
||||
// Retrieve the account from the store
|
||||
|
@ -260,7 +261,7 @@ internal class MXOlmDevice @Inject constructor(
|
|||
* The new session will be stored in the MXStore.
|
||||
*
|
||||
* @param theirIdentityKey the remote user's Curve25519 identity key
|
||||
* @param theirOneTimeKey the remote user's one-time Curve25519 key
|
||||
* @param theirOneTimeKey the remote user's one-time Curve25519 key
|
||||
* @return the session id for the outbound session.
|
||||
*/
|
||||
fun createOutboundSession(theirIdentityKey: String, theirOneTimeKey: String): String? {
|
||||
|
@ -299,8 +300,8 @@ internal class MXOlmDevice @Inject constructor(
|
|||
* Generate a new inbound session, given an incoming message.
|
||||
*
|
||||
* @param theirDeviceIdentityKey the remote user's Curve25519 identity key.
|
||||
* @param messageType the message_type field from the received message (must be 0).
|
||||
* @param ciphertext base64-encoded body from the received message.
|
||||
* @param messageType the message_type field from the received message (must be 0).
|
||||
* @param ciphertext base64-encoded body from the received message.
|
||||
* @return {{payload: string, session_id: string}} decrypted payload, and session id of new session.
|
||||
*/
|
||||
fun createInboundSession(theirDeviceIdentityKey: String, messageType: Int, ciphertext: String): Map<String, String>? {
|
||||
|
@ -394,8 +395,8 @@ internal class MXOlmDevice @Inject constructor(
|
|||
* Encrypt an outgoing message using an existing session.
|
||||
*
|
||||
* @param theirDeviceIdentityKey the Curve25519 identity key for the remote device.
|
||||
* @param sessionId the id of the active session
|
||||
* @param payloadString the payload to be encrypted and sent
|
||||
* @param sessionId the id of the active session
|
||||
* @param payloadString the payload to be encrypted and sent
|
||||
* @return the cipher text
|
||||
*/
|
||||
suspend fun encryptMessage(theirDeviceIdentityKey: String, sessionId: String, payloadString: String): Map<String, Any>? {
|
||||
|
@ -427,10 +428,10 @@ internal class MXOlmDevice @Inject constructor(
|
|||
/**
|
||||
* Decrypt an incoming message using an existing session.
|
||||
*
|
||||
* @param ciphertext the base64-encoded body from the received message.
|
||||
* @param messageType message_type field from the received message.
|
||||
* @param ciphertext the base64-encoded body from the received message.
|
||||
* @param messageType message_type field from the received message.
|
||||
* @param sessionId the id of the active session.
|
||||
* @param theirDeviceIdentityKey the Curve25519 identity key for the remote device.
|
||||
* @param sessionId the id of the active session.
|
||||
* @return the decrypted payload.
|
||||
*/
|
||||
@kotlin.jvm.Throws
|
||||
|
@ -460,9 +461,9 @@ internal class MXOlmDevice @Inject constructor(
|
|||
* Determine if an incoming messages is a prekey message matching an existing session.
|
||||
*
|
||||
* @param theirDeviceIdentityKey the Curve25519 identity key for the remote device.
|
||||
* @param sessionId the id of the active session.
|
||||
* @param messageType message_type field from the received message.
|
||||
* @param ciphertext the base64-encoded body from the received message.
|
||||
* @param sessionId the id of the active session.
|
||||
* @param messageType message_type field from the received message.
|
||||
* @param ciphertext the base64-encoded body from the received message.
|
||||
* @return YES if the received message is a prekey message which matchesthe given session.
|
||||
*/
|
||||
fun matchesSession(theirDeviceIdentityKey: String, sessionId: String, messageType: Int, ciphertext: String): Boolean {
|
||||
|
@ -563,7 +564,7 @@ internal class MXOlmDevice @Inject constructor(
|
|||
/**
|
||||
* Encrypt an outgoing message with an outbound group session.
|
||||
*
|
||||
* @param sessionId the id of the outbound group session.
|
||||
* @param sessionId the id of the outbound group session.
|
||||
* @param payloadString the payload to be encrypted and sent.
|
||||
* @return ciphertext
|
||||
*/
|
||||
|
@ -590,13 +591,13 @@ internal class MXOlmDevice @Inject constructor(
|
|||
/**
|
||||
* Add an inbound group session to the session store.
|
||||
*
|
||||
* @param sessionId the session identifier.
|
||||
* @param sessionKey base64-encoded secret key.
|
||||
* @param roomId the id of the room in which this session will be used.
|
||||
* @param senderKey the base64-encoded curve25519 key of the sender.
|
||||
* @param sessionId the session identifier.
|
||||
* @param sessionKey base64-encoded secret key.
|
||||
* @param roomId the id of the room in which this session will be used.
|
||||
* @param senderKey the base64-encoded curve25519 key of the sender.
|
||||
* @param forwardingCurve25519KeyChain Devices involved in forwarding this session to us.
|
||||
* @param keysClaimed Other keys the sender claims.
|
||||
* @param exportFormat true if the megolm keys are in export format
|
||||
* @param keysClaimed Other keys the sender claims.
|
||||
* @param exportFormat true if the megolm keys are in export format
|
||||
* @return true if the operation succeeds.
|
||||
*/
|
||||
fun addInboundGroupSession(sessionId: String,
|
||||
|
@ -752,70 +753,75 @@ internal class MXOlmDevice @Inject constructor(
|
|||
/**
|
||||
* Decrypt a received message with an inbound group session.
|
||||
*
|
||||
* @param body the base64-encoded body of the encrypted message.
|
||||
* @param roomId the room in which the message was received.
|
||||
* @param timeline the id of the timeline where the event is decrypted. It is used to prevent replay attack.
|
||||
* @param body the base64-encoded body of the encrypted message.
|
||||
* @param roomId the room in which the message was received.
|
||||
* @param timeline the id of the timeline where the event is decrypted. It is used to prevent replay attack.
|
||||
* @param eventId the eventId of the message that will be decrypted
|
||||
* @param sessionId the session identifier.
|
||||
* @param senderKey the base64-encoded curve25519 key of the sender.
|
||||
* @return the decrypting result. Nil if the sessionId is unknown.
|
||||
* @return the decrypting result. Null if the sessionId is unknown.
|
||||
*/
|
||||
@Throws(MXCryptoError::class)
|
||||
suspend fun decryptGroupMessage(body: String,
|
||||
roomId: String,
|
||||
timeline: String?,
|
||||
eventId: String,
|
||||
sessionId: String,
|
||||
senderKey: String): OlmDecryptionResult {
|
||||
val sessionHolder = getInboundGroupSession(sessionId, senderKey, roomId)
|
||||
val wrapper = sessionHolder.wrapper
|
||||
val inboundGroupSession = wrapper.olmInboundGroupSession
|
||||
?: throw MXCryptoError.Base(MXCryptoError.ErrorType.UNABLE_TO_DECRYPT, "Session is null")
|
||||
// Check that the room id matches the original one for the session. This stops
|
||||
// the HS pretending a message was targeting a different room.
|
||||
if (roomId == wrapper.roomId) {
|
||||
val decryptResult = try {
|
||||
sessionHolder.mutex.withLock {
|
||||
inboundGroupSession.decryptMessage(body)
|
||||
}
|
||||
} catch (e: OlmException) {
|
||||
Timber.tag(loggerTag.value).e(e, "## decryptGroupMessage () : decryptMessage failed")
|
||||
throw MXCryptoError.OlmError(e)
|
||||
}
|
||||
|
||||
if (timeline?.isNotBlank() == true) {
|
||||
val timelineSet = inboundGroupSessionMessageIndexes.getOrPut(timeline) { mutableSetOf() }
|
||||
|
||||
val messageIndexKey = senderKey + "|" + sessionId + "|" + decryptResult.mIndex
|
||||
|
||||
if (timelineSet.contains(messageIndexKey)) {
|
||||
val reason = String.format(MXCryptoError.DUPLICATE_MESSAGE_INDEX_REASON, decryptResult.mIndex)
|
||||
Timber.tag(loggerTag.value).e("## decryptGroupMessage() timelineId=$timeline: $reason")
|
||||
throw MXCryptoError.Base(MXCryptoError.ErrorType.DUPLICATED_MESSAGE_INDEX, reason)
|
||||
}
|
||||
|
||||
timelineSet.add(messageIndexKey)
|
||||
}
|
||||
|
||||
inboundGroupSessionStore.storeInBoundGroupSession(sessionHolder, sessionId, senderKey)
|
||||
val payload = try {
|
||||
val adapter = MoshiProvider.providesMoshi().adapter<JsonDict>(JSON_DICT_PARAMETERIZED_TYPE)
|
||||
val payloadString = convertFromUTF8(decryptResult.mDecryptedMessage)
|
||||
adapter.fromJson(payloadString)
|
||||
} catch (e: Exception) {
|
||||
Timber.tag(loggerTag.value).e("## decryptGroupMessage() : fails to parse the payload")
|
||||
throw MXCryptoError.Base(MXCryptoError.ErrorType.BAD_DECRYPTED_FORMAT, MXCryptoError.BAD_DECRYPTED_FORMAT_TEXT_REASON)
|
||||
}
|
||||
|
||||
return OlmDecryptionResult(
|
||||
payload,
|
||||
wrapper.keysClaimed,
|
||||
senderKey,
|
||||
wrapper.forwardingCurve25519KeyChain
|
||||
)
|
||||
} else {
|
||||
if (roomId != wrapper.roomId) {
|
||||
// Check that the room id matches the original one for the session. This stops
|
||||
// the HS pretending a message was targeting a different room.
|
||||
val reason = String.format(MXCryptoError.INBOUND_SESSION_MISMATCH_ROOM_ID_REASON, roomId, wrapper.roomId)
|
||||
Timber.tag(loggerTag.value).e("## decryptGroupMessage() : $reason")
|
||||
throw MXCryptoError.Base(MXCryptoError.ErrorType.INBOUND_SESSION_MISMATCH_ROOM_ID, reason)
|
||||
}
|
||||
val decryptResult = try {
|
||||
sessionHolder.mutex.withLock {
|
||||
inboundGroupSession.decryptMessage(body)
|
||||
}
|
||||
} catch (e: OlmException) {
|
||||
Timber.tag(loggerTag.value).e(e, "## decryptGroupMessage () : decryptMessage failed")
|
||||
throw MXCryptoError.OlmError(e)
|
||||
}
|
||||
|
||||
val messageIndexKey = senderKey + "|" + sessionId + "|" + roomId + "|" + decryptResult.mIndex
|
||||
Timber.tag(loggerTag.value).v("##########################################################")
|
||||
Timber.tag(loggerTag.value).v("## decryptGroupMessage() timeline: $timeline")
|
||||
Timber.tag(loggerTag.value).v("## decryptGroupMessage() senderKey: $senderKey")
|
||||
Timber.tag(loggerTag.value).v("## decryptGroupMessage() sessionId: $sessionId")
|
||||
Timber.tag(loggerTag.value).v("## decryptGroupMessage() roomId: $roomId")
|
||||
Timber.tag(loggerTag.value).v("## decryptGroupMessage() eventId: $eventId")
|
||||
Timber.tag(loggerTag.value).v("## decryptGroupMessage() mIndex: ${decryptResult.mIndex}")
|
||||
|
||||
if (timeline?.isNotBlank() == true) {
|
||||
val replayAttackMap = inboundGroupSessionMessageIndexes.getOrPut(timeline) { mutableMapOf() }
|
||||
if (replayAttackMap.contains(messageIndexKey) && replayAttackMap[messageIndexKey] != eventId) {
|
||||
val reason = String.format(MXCryptoError.DUPLICATE_MESSAGE_INDEX_REASON, decryptResult.mIndex)
|
||||
Timber.tag(loggerTag.value).e("## decryptGroupMessage() timelineId=$timeline: $reason")
|
||||
throw MXCryptoError.Base(MXCryptoError.ErrorType.DUPLICATED_MESSAGE_INDEX, reason)
|
||||
}
|
||||
replayAttackMap[messageIndexKey] = eventId
|
||||
}
|
||||
inboundGroupSessionStore.storeInBoundGroupSession(sessionHolder, sessionId, senderKey)
|
||||
val payload = try {
|
||||
val adapter = MoshiProvider.providesMoshi().adapter<JsonDict>(JSON_DICT_PARAMETERIZED_TYPE)
|
||||
val payloadString = convertFromUTF8(decryptResult.mDecryptedMessage)
|
||||
adapter.fromJson(payloadString)
|
||||
} catch (e: Exception) {
|
||||
Timber.tag(loggerTag.value).e("## decryptGroupMessage() : fails to parse the payload")
|
||||
throw MXCryptoError.Base(MXCryptoError.ErrorType.BAD_DECRYPTED_FORMAT, MXCryptoError.BAD_DECRYPTED_FORMAT_TEXT_REASON)
|
||||
}
|
||||
|
||||
return OlmDecryptionResult(
|
||||
payload,
|
||||
wrapper.keysClaimed,
|
||||
senderKey,
|
||||
wrapper.forwardingCurve25519KeyChain
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -834,9 +840,9 @@ internal class MXOlmDevice @Inject constructor(
|
|||
/**
|
||||
* Verify an ed25519 signature on a JSON object.
|
||||
*
|
||||
* @param key the ed25519 key.
|
||||
* @param key the ed25519 key.
|
||||
* @param jsonDictionary the JSON object which was signed.
|
||||
* @param signature the base64-encoded signature to be checked.
|
||||
* @param signature the base64-encoded signature to be checked.
|
||||
* @throws Exception the exception
|
||||
*/
|
||||
@Throws(Exception::class)
|
||||
|
@ -859,7 +865,7 @@ internal class MXOlmDevice @Inject constructor(
|
|||
* Search an OlmSession.
|
||||
*
|
||||
* @param theirDeviceIdentityKey the device key
|
||||
* @param sessionId the session Id
|
||||
* @param sessionId the session Id
|
||||
* @return the olm session
|
||||
*/
|
||||
private fun getSessionForDevice(theirDeviceIdentityKey: String, sessionId: String): OlmSessionWrapper? {
|
||||
|
@ -873,9 +879,9 @@ internal class MXOlmDevice @Inject constructor(
|
|||
* Extract an InboundGroupSession from the session store and do some check.
|
||||
* inboundGroupSessionWithIdError describes the failure reason.
|
||||
*
|
||||
* @param roomId the room where the session is used.
|
||||
* @param sessionId the session identifier.
|
||||
* @param senderKey the base64-encoded curve25519 key of the sender.
|
||||
* @param roomId the room where the session is used.
|
||||
* @return the inbound group session.
|
||||
*/
|
||||
fun getInboundGroupSession(sessionId: String?, senderKey: String?, roomId: String?): InboundGroupSessionHolder {
|
||||
|
@ -905,7 +911,7 @@ internal class MXOlmDevice @Inject constructor(
|
|||
/**
|
||||
* Determine if we have the keys for a given megolm session.
|
||||
*
|
||||
* @param roomId room in which the message was received
|
||||
* @param roomId room in which the message was received
|
||||
* @param senderKey base64-encoded curve25519 key of the sender
|
||||
* @param sessionId session identifier
|
||||
* @return true if the unbound session keys are known.
|
||||
|
|
|
@ -39,7 +39,7 @@ internal class OlmSessionStore @Inject constructor(private val store: IMXCryptoS
|
|||
* Store a session between our own device and another device.
|
||||
* This will be called after the session has been created but also every time it has been used
|
||||
* in order to persist the correct state for next run
|
||||
* @param olmSessionWrapper the end-to-end session.
|
||||
* @param olmSessionWrapper the end-to-end session.
|
||||
* @param deviceKey the public key of the other device.
|
||||
*/
|
||||
@Synchronized
|
||||
|
|
|
@ -49,7 +49,7 @@ internal class RoomDecryptorProvider @Inject constructor(
|
|||
* If we already have a decryptor for the given room and algorithm, return
|
||||
* it. Otherwise try to instantiate it.
|
||||
*
|
||||
* @param roomId the room id
|
||||
* @param roomId the room id
|
||||
* @param algorithm the crypto algorithm
|
||||
* @return the decryptor
|
||||
* // TODO Create another method for the case of roomId is null
|
||||
|
|
|
@ -29,7 +29,7 @@ internal class EnsureOlmSessionsForUsersAction @Inject constructor(private val o
|
|||
|
||||
/**
|
||||
* Try to make sure we have established olm sessions for the given users.
|
||||
* @param users a list of user ids.
|
||||
* @param users a list of user ids.
|
||||
*/
|
||||
suspend fun handle(users: List<String>): MXUsersDevicesMap<MXOlmSessionResult> {
|
||||
Timber.v("## ensureOlmSessionsForUsers() : ensureOlmSessionsForUsers $users")
|
||||
|
|
|
@ -45,8 +45,8 @@ internal class MegolmSessionDataImporter @Inject constructor(private val olmDevi
|
|||
* Must be call on the crypto coroutine thread
|
||||
*
|
||||
* @param megolmSessionsData megolm sessions.
|
||||
* @param fromBackup true if the imported keys are already backed up on the server.
|
||||
* @param progressListener the progress listener
|
||||
* @param fromBackup true if the imported keys are already backed up on the server.
|
||||
* @param progressListener the progress listener
|
||||
* @return import room keys result
|
||||
*/
|
||||
@WorkerThread
|
||||
|
|
|
@ -42,7 +42,7 @@ internal class MessageEncrypter @Inject constructor(
|
|||
* This method must be called from the getCryptoHandler() thread.
|
||||
*
|
||||
* @param payloadFields fields to include in the encrypted payload.
|
||||
* @param deviceInfos list of device infos to encrypt for.
|
||||
* @param deviceInfos list of device infos to encrypt for.
|
||||
* @return the content for an m.room.encrypted event.
|
||||
*/
|
||||
suspend fun encryptMessage(payloadFields: Content, deviceInfos: List<CryptoDeviceInfo>): EncryptedMessage {
|
||||
|
|
|
@ -29,7 +29,7 @@ internal interface IMXDecrypting {
|
|||
/**
|
||||
* Decrypt an event.
|
||||
*
|
||||
* @param event the raw event.
|
||||
* @param event the raw event.
|
||||
* @param timeline the id of the timeline where the event is decrypted. It is used to prevent replay attack.
|
||||
* @return the decryption information, or an error
|
||||
*/
|
||||
|
@ -40,6 +40,7 @@ internal interface IMXDecrypting {
|
|||
* Handle a key event.
|
||||
*
|
||||
* @param event the key event.
|
||||
* @param defaultKeysBackupService the keys backup service
|
||||
*/
|
||||
fun onRoomKeyEvent(event: Event, defaultKeysBackupService: DefaultKeysBackupService) {}
|
||||
}
|
||||
|
|
|
@ -27,8 +27,8 @@ internal interface IMXEncrypting {
|
|||
* Encrypt an event content according to the configuration of the room.
|
||||
*
|
||||
* @param eventContent the content of the event.
|
||||
* @param eventType the type of the event.
|
||||
* @param userIds the room members the event will be sent to.
|
||||
* @param eventType the type of the event.
|
||||
* @param userIds the room members the event will be sent to.
|
||||
* @return the encrypted content
|
||||
*/
|
||||
suspend fun encryptEventContent(eventContent: Content, eventType: String, userIds: List<String>): Content
|
||||
|
|
|
@ -38,7 +38,7 @@ internal interface IMXGroupEncryption {
|
|||
* Re-shares a session key with devices if the key has already been
|
||||
* sent to them.
|
||||
*
|
||||
* @param sessionId The id of the outbound session to share.
|
||||
* @param groupSessionId The id of the outbound session to share.
|
||||
* @param userId The id of the user who owns the target device.
|
||||
* @param deviceId The id of the target device.
|
||||
* @param senderKey The key of the originating device for the session.
|
||||
|
|
|
@ -78,6 +78,7 @@ internal class MXMegolmDecryption(
|
|||
encryptedEventContent.ciphertext,
|
||||
event.roomId,
|
||||
timeline,
|
||||
eventId = event.eventId.orEmpty(),
|
||||
encryptedEventContent.sessionId,
|
||||
encryptedEventContent.senderKey
|
||||
)
|
||||
|
@ -176,6 +177,7 @@ internal class MXMegolmDecryption(
|
|||
* Handle a key event.
|
||||
*
|
||||
* @param event the key event.
|
||||
* @param defaultKeysBackupService the keys backup service
|
||||
*/
|
||||
override fun onRoomKeyEvent(event: Event, defaultKeysBackupService: DefaultKeysBackupService) {
|
||||
Timber.tag(loggerTag.value).v("onRoomKeyEvent()")
|
||||
|
|
|
@ -198,7 +198,7 @@ internal class MXMegolmEncryption(
|
|||
/**
|
||||
* Share the device key to a list of users.
|
||||
*
|
||||
* @param session the session info
|
||||
* @param session the session info
|
||||
* @param devicesByUsers the devices map
|
||||
*/
|
||||
private suspend fun shareKey(session: MXOutboundSessionInfo,
|
||||
|
@ -227,7 +227,7 @@ internal class MXMegolmEncryption(
|
|||
/**
|
||||
* Share the device keys of a an user.
|
||||
*
|
||||
* @param session the session info
|
||||
* @param session the session info
|
||||
* @param devicesByUser the devices map
|
||||
*/
|
||||
private suspend fun shareUserDevicesKey(session: MXOutboundSessionInfo,
|
||||
|
@ -387,7 +387,7 @@ internal class MXMegolmEncryption(
|
|||
* Get the list of devices which can encrypt data to.
|
||||
* This method must be called in getDecryptingThreadHandler() thread.
|
||||
*
|
||||
* @param userIds the user ids whose devices must be checked.
|
||||
* @param userIds the user ids whose devices must be checked.
|
||||
*/
|
||||
private suspend fun getDevicesInRoom(userIds: List<String>): DeviceInRoomInfo {
|
||||
// We are happy to use a cached version here: we assume that if we already
|
||||
|
|
|
@ -180,8 +180,8 @@ internal class MXOlmDecryption(
|
|||
/**
|
||||
* Attempt to decrypt an Olm message.
|
||||
*
|
||||
* @param message message object, with 'type' and 'body' fields.
|
||||
* @param theirDeviceIdentityKey the Curve25519 identity key of the sender.
|
||||
* @param message message object, with 'type' and 'body' fields.
|
||||
* @return payload, if decrypted successfully.
|
||||
*/
|
||||
private suspend fun decryptMessage(message: JsonDict, theirDeviceIdentityKey: String): String? {
|
||||
|
|
|
@ -70,7 +70,7 @@ internal class MXOlmEncryption(
|
|||
/**
|
||||
* Ensure that the session.
|
||||
*
|
||||
* @param users the user ids list
|
||||
* @param users the user ids list
|
||||
*/
|
||||
private suspend fun ensureSession(users: List<String>) {
|
||||
deviceListManager.downloadKeys(users, false)
|
||||
|
|
|
@ -103,7 +103,7 @@ internal interface CryptoApi {
|
|||
* Claim one-time keys.
|
||||
* Doc: https://matrix.org/docs/spec/client_server/r0.4.0.html#post-matrix-client-r0-keys-claim
|
||||
*
|
||||
* @param params the params.
|
||||
* @param body the Json body.
|
||||
*/
|
||||
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "keys/claim")
|
||||
suspend fun claimOneTimeKeysForUsersDevices(@Body body: KeysClaimBody): KeysClaimResponse
|
||||
|
@ -112,9 +112,9 @@ internal interface CryptoApi {
|
|||
* Send an event to a specific list of devices
|
||||
* Doc: https://matrix.org/docs/spec/client_server/r0.4.0.html#put-matrix-client-r0-sendtodevice-eventtype-txnid
|
||||
*
|
||||
* @param eventType the type of event to send
|
||||
* @param eventType the type of event to send
|
||||
* @param transactionId the transaction ID for this event
|
||||
* @param body the body
|
||||
* @param body the body
|
||||
*/
|
||||
@PUT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "sendToDevice/{eventType}/{txnId}")
|
||||
suspend fun sendToDevice(@Path("eventType") eventType: String,
|
||||
|
@ -126,7 +126,7 @@ internal interface CryptoApi {
|
|||
* Doc: https://matrix.org/docs/spec/client_server/r0.4.0.html#delete-matrix-client-r0-devices-deviceid
|
||||
*
|
||||
* @param deviceId the device id
|
||||
* @param params the deletion parameters
|
||||
* @param params the deletion parameters
|
||||
*/
|
||||
@HTTP(path = NetworkConstants.URI_API_PREFIX_PATH_R0 + "devices/{device_id}", method = "DELETE", hasBody = true)
|
||||
suspend fun deleteDevice(@Path("device_id") deviceId: String,
|
||||
|
@ -137,7 +137,7 @@ internal interface CryptoApi {
|
|||
* Doc: https://matrix.org/docs/spec/client_server/r0.4.0.html#put-matrix-client-r0-devices-deviceid
|
||||
*
|
||||
* @param deviceId the device id
|
||||
* @param params the params
|
||||
* @param params the params
|
||||
*/
|
||||
@PUT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "devices/{device_id}")
|
||||
suspend fun updateDeviceInfo(@Path("device_id") deviceId: String,
|
||||
|
|
|
@ -159,6 +159,7 @@ internal object MXEncryptedAttachments {
|
|||
* Encrypt an attachment stream.
|
||||
* DO NOT USE for big files, it will load all in memory
|
||||
* @param attachmentStream the attachment stream. Will be closed after this method call.
|
||||
* @param clock a clock to retrieve current time
|
||||
* @return the encryption file info
|
||||
*/
|
||||
fun encryptAttachment(attachmentStream: InputStream, clock: Clock): EncryptionResult {
|
||||
|
@ -231,7 +232,8 @@ internal object MXEncryptedAttachments {
|
|||
*
|
||||
* @param attachmentStream the attachment stream. Will be closed after this method call.
|
||||
* @param elementToDecrypt the elementToDecrypt info
|
||||
* @param outputStream the outputStream where the decrypted attachment will be write.
|
||||
* @param outputStream the outputStream where the decrypted attachment will be write.
|
||||
* @param clock a clock to retrieve current time
|
||||
* @return true in case of success, false in case of error
|
||||
*/
|
||||
fun decryptAttachment(attachmentStream: InputStream?,
|
||||
|
|
|
@ -1105,6 +1105,7 @@ internal class DefaultKeysBackupService @Inject constructor(
|
|||
*
|
||||
* @param password the password.
|
||||
* @param keysBackupData the backup and its auth data.
|
||||
* @param progressListener listener to track progress
|
||||
*
|
||||
* @return the recovery key if successful, null in other cases
|
||||
*/
|
||||
|
|
|
@ -44,6 +44,7 @@ internal data class GeneratePrivateKeyResult(
|
|||
* Compute a private key from a password.
|
||||
*
|
||||
* @param password the password to use.
|
||||
* @param progressListener a listener to track progress
|
||||
*
|
||||
* @return a {privateKey, salt, iterations} tuple.
|
||||
*/
|
||||
|
|
|
@ -60,19 +60,19 @@ internal interface RoomKeysApi {
|
|||
* Get information about the given version.
|
||||
* If not supported by the server, an error is returned: {"errcode":"M_NOT_FOUND","error":"No backup found"}
|
||||
*
|
||||
* @param version version
|
||||
* @param version version
|
||||
*/
|
||||
@GET(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/version/{version}")
|
||||
suspend fun getKeysBackupVersion(@Path("version") version: String): KeysVersionResult
|
||||
|
||||
/**
|
||||
* Update information about the given version.
|
||||
* @param version version
|
||||
* @param version version
|
||||
* @param updateKeysBackupVersionBody the body
|
||||
*/
|
||||
@PUT(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/version/{version}")
|
||||
suspend fun updateKeysBackupVersion(@Path("version") version: String,
|
||||
@Body keysBackupVersionBody: UpdateKeysBackupVersionBody)
|
||||
@Body updateKeysBackupVersionBody: UpdateKeysBackupVersionBody)
|
||||
|
||||
/* ==========================================================================================
|
||||
* Storing keys
|
||||
|
@ -87,9 +87,9 @@ internal interface RoomKeysApi {
|
|||
* flag (true is better than false), then by the first_message_index (a lower number is better), and finally by
|
||||
* forwarded_count (a lower number is better).
|
||||
*
|
||||
* @param roomId the room id
|
||||
* @param sessionId the session id
|
||||
* @param version the version of the backup
|
||||
* @param roomId the room id
|
||||
* @param sessionId the session id
|
||||
* @param version the version of the backup
|
||||
* @param keyBackupData the data to send
|
||||
*/
|
||||
@PUT(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/keys/{roomId}/{sessionId}")
|
||||
|
@ -101,8 +101,8 @@ internal interface RoomKeysApi {
|
|||
/**
|
||||
* Store several keys for the given room, using the given backup version.
|
||||
*
|
||||
* @param roomId the room id
|
||||
* @param version the version of the backup
|
||||
* @param roomId the room id
|
||||
* @param version the version of the backup
|
||||
* @param roomKeysBackupData the data to send
|
||||
*/
|
||||
@PUT(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/keys/{roomId}")
|
||||
|
@ -113,7 +113,7 @@ internal interface RoomKeysApi {
|
|||
/**
|
||||
* Store several keys, using the given backup version.
|
||||
*
|
||||
* @param version the version of the backup
|
||||
* @param version the version of the backup
|
||||
* @param keysBackupData the data to send
|
||||
*/
|
||||
@PUT(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/keys")
|
||||
|
@ -127,9 +127,9 @@ internal interface RoomKeysApi {
|
|||
/**
|
||||
* Retrieve the key for the given session in the given room from the backup.
|
||||
*
|
||||
* @param roomId the room id
|
||||
* @param roomId the room id
|
||||
* @param sessionId the session id
|
||||
* @param version the version of the backup, or empty String to retrieve the last version
|
||||
* @param version the version of the backup, or empty String to retrieve the last version
|
||||
*/
|
||||
@GET(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/keys/{roomId}/{sessionId}")
|
||||
suspend fun getRoomSessionData(@Path("roomId") roomId: String,
|
||||
|
@ -139,8 +139,8 @@ internal interface RoomKeysApi {
|
|||
/**
|
||||
* Retrieve all the keys for the given room from the backup.
|
||||
*
|
||||
* @param roomId the room id
|
||||
* @param version the version of the backup, or empty String to retrieve the last version
|
||||
* @param roomId the room id
|
||||
* @param version the version of the backup, or empty String to retrieve the last version
|
||||
*/
|
||||
@GET(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/keys/{roomId}")
|
||||
suspend fun getRoomSessionsData(@Path("roomId") roomId: String,
|
||||
|
@ -149,7 +149,7 @@ internal interface RoomKeysApi {
|
|||
/**
|
||||
* Retrieve all the keys from the backup.
|
||||
*
|
||||
* @param version the version of the backup, or empty String to retrieve the last version
|
||||
* @param version the version of the backup, or empty String to retrieve the last version
|
||||
*/
|
||||
@GET(NetworkConstants.URI_API_PREFIX_PATH_UNSTABLE + "room_keys/keys")
|
||||
suspend fun getSessionsData(@Query("version") version: String): KeysBackupData
|
||||
|
|
|
@ -59,7 +59,7 @@ internal data class MXKey(
|
|||
/**
|
||||
* Returns a signature for an user Id and a signkey.
|
||||
*
|
||||
* @param userId the user id
|
||||
* @param userId the user id
|
||||
* @param signkey the sign key
|
||||
* @return the signature
|
||||
*/
|
||||
|
|
|
@ -164,16 +164,14 @@ internal interface IMXCryptoStore {
|
|||
|
||||
/**
|
||||
* Store the end to end account for the logged-in user.
|
||||
*
|
||||
* @param account the account to save
|
||||
*/
|
||||
fun saveOlmAccount()
|
||||
|
||||
/**
|
||||
* Retrieve a device for a user.
|
||||
*
|
||||
* @param userId the user's id.
|
||||
* @param deviceId the device id.
|
||||
* @param userId the user's id.
|
||||
* @return the device
|
||||
*/
|
||||
fun getUserDevice(userId: String, deviceId: String): CryptoDeviceInfo?
|
||||
|
@ -189,7 +187,7 @@ internal interface IMXCryptoStore {
|
|||
/**
|
||||
* Store the known devices for a user.
|
||||
*
|
||||
* @param userId The user's id.
|
||||
* @param userId The user's id.
|
||||
* @param devices A map from device id to 'MXDevice' object for the device.
|
||||
*/
|
||||
fun storeUserDevices(userId: String, devices: Map<String, CryptoDeviceInfo>?)
|
||||
|
@ -225,7 +223,7 @@ internal interface IMXCryptoStore {
|
|||
/**
|
||||
* Store the crypto algorithm for a room.
|
||||
*
|
||||
* @param roomId the id of the room.
|
||||
* @param roomId the id of the room.
|
||||
* @param algorithm the algorithm.
|
||||
*/
|
||||
fun storeRoomAlgorithm(roomId: String, algorithm: String?)
|
||||
|
@ -253,7 +251,7 @@ internal interface IMXCryptoStore {
|
|||
/**
|
||||
* Store a session between the logged-in user and another device.
|
||||
*
|
||||
* @param olmSessionWrapper the end-to-end session.
|
||||
* @param olmSessionWrapper the end-to-end session.
|
||||
* @param deviceKey the public key of the other device.
|
||||
*/
|
||||
fun storeSession(olmSessionWrapper: OlmSessionWrapper, deviceKey: String)
|
||||
|
@ -331,7 +329,7 @@ internal interface IMXCryptoStore {
|
|||
/**
|
||||
* Mark inbound group sessions as backed up on the user homeserver.
|
||||
*
|
||||
* @param sessions the sessions
|
||||
* @param olmInboundGroupSessionWrappers the sessions
|
||||
*/
|
||||
fun markBackupDoneForInboundGroupSessions(olmInboundGroupSessionWrappers: List<OlmInboundGroupSessionWrapper2>)
|
||||
|
||||
|
@ -361,7 +359,7 @@ internal interface IMXCryptoStore {
|
|||
/**
|
||||
* Get the tracking status of a specified userId devices.
|
||||
*
|
||||
* @param userId the user id
|
||||
* @param userId the user id
|
||||
* @param defaultValue the default value
|
||||
* @return the tracking status
|
||||
*/
|
||||
|
@ -380,7 +378,9 @@ internal interface IMXCryptoStore {
|
|||
/**
|
||||
* Look for an existing outgoing room key request, and if none is found, add a new one.
|
||||
*
|
||||
* @param request the request
|
||||
* @param requestBody the request
|
||||
* @param recipients list of recipients
|
||||
* @param fromIndex start index
|
||||
* @return either the same instance as passed in, or the existing one.
|
||||
*/
|
||||
fun getOrAddOutgoingRoomKeyRequest(requestBody: RoomKeyRequestBody, recipients: Map<String, List<String>>, fromIndex: Int): OutgoingKeyRequest
|
||||
|
|
|
@ -35,7 +35,7 @@ internal object HkdfSha256 {
|
|||
/**
|
||||
* HkdfSha256-Extract(salt, IKM) -> PRK.
|
||||
*
|
||||
* @param salt optional salt value (a non-secret random value);
|
||||
* @param salt optional salt value (a non-secret random value);
|
||||
* if not provided, it is set to a string of HashLen (size in octets) zeros.
|
||||
* @param ikm input keying material
|
||||
*/
|
||||
|
|
|
@ -35,6 +35,11 @@ internal interface VerificationTransport {
|
|||
onDone: (() -> Unit)?)
|
||||
|
||||
/**
|
||||
* @param supportedMethods list of supported method by this client
|
||||
* @param localId a local Id
|
||||
* @param otherUserId the user id to send the verification request to
|
||||
* @param roomId a room Id to use to send verification message
|
||||
* @param toDevices list of device Ids
|
||||
* @param callback will be called with eventId and ValidVerificationInfoRequest in case of success
|
||||
*/
|
||||
fun sendVerificationRequest(supportedMethods: List<String>,
|
||||
|
|
|
@ -96,7 +96,9 @@ internal fun EventEntity.markEventAsRoot(
|
|||
/**
|
||||
* Count the number of threads for the provided root thread eventId, and finds the latest event message.
|
||||
* Note: Redactions are handled by RedactionEventProcessor.
|
||||
* @param realm the realm database
|
||||
* @param rootThreadEventId The root eventId that will find the number of threads
|
||||
* @param chunkEntity the chunk entity
|
||||
* @return A ThreadSummary containing the counted threads and the latest event message
|
||||
*/
|
||||
internal fun EventEntity.threadSummaryInThread(realm: Realm, rootThreadEventId: String, chunkEntity: ChunkEntity?): Summary {
|
||||
|
@ -184,6 +186,7 @@ private fun findLatestSortedChunkEvent(chunk: ChunkEntity, rootThreadEventId: St
|
|||
|
||||
/**
|
||||
* Find all TimelineEventEntity that are root threads for the specified room.
|
||||
* @param realm the realm instance
|
||||
* @param roomId The room that all stored root threads will be returned
|
||||
*/
|
||||
internal fun TimelineEventEntity.Companion.findAllThreadsForRoomId(realm: Realm, roomId: String): RealmQuery<TimelineEventEntity> =
|
||||
|
@ -218,6 +221,7 @@ internal fun List<TimelineEvent>.mapEventsWithEdition(realm: Realm, roomId: Stri
|
|||
|
||||
/**
|
||||
* Returns a list of all the marked unread threads that exists for the specified room.
|
||||
* @param realm the realm instance
|
||||
* @param roomId The roomId that the user is currently in
|
||||
*/
|
||||
internal fun TimelineEventEntity.Companion.findAllLocalThreadNotificationsForRoomId(realm: Realm, roomId: String): RealmQuery<TimelineEventEntity> =
|
||||
|
@ -232,6 +236,7 @@ internal fun TimelineEventEntity.Companion.findAllLocalThreadNotificationsForRoo
|
|||
|
||||
/**
|
||||
* Returns whether or not the given user is participating in a current thread.
|
||||
* @param realm the realm instance
|
||||
* @param roomId the room that the thread exists
|
||||
* @param rootThreadEventId the thread that the search will be done
|
||||
* @param senderId the user that will try to find participation
|
||||
|
@ -247,6 +252,7 @@ internal fun TimelineEventEntity.Companion.isUserParticipatingInThread(realm: Re
|
|||
|
||||
/**
|
||||
* Returns whether or not the given user is mentioned in a current thread.
|
||||
* @param realm the realm instance
|
||||
* @param roomId the room that the thread exists
|
||||
* @param rootThreadEventId the thread that the search will be done
|
||||
* @param userId the user that will try to find if there is a mention
|
||||
|
|
|
@ -303,6 +303,7 @@ private fun getLatestEvent(rootThreadEvent: Event): Event? {
|
|||
/**
|
||||
* Find all ThreadSummaryEntity for the specified roomId, sorted by origin server.
|
||||
* note: Sorting cannot be provided by server, so we have to use that unstable property.
|
||||
* @param realm the realm instance
|
||||
* @param roomId The id of the room
|
||||
*/
|
||||
internal fun ThreadSummaryEntity.Companion.findAllThreadsForRoomId(realm: Realm, roomId: String): RealmQuery<ThreadSummaryEntity> =
|
||||
|
|
|
@ -31,6 +31,9 @@ internal open class LiveLocationShareAggregatedSummaryEntity(
|
|||
|
||||
var roomId: String = "",
|
||||
|
||||
/**
|
||||
* Indicate whether the live is currently running.
|
||||
*/
|
||||
var isActive: Boolean? = null,
|
||||
|
||||
var endOfLiveTimestampMillis: Long? = null,
|
||||
|
|
|
@ -55,3 +55,11 @@ internal fun LiveLocationShareAggregatedSummaryEntity.Companion.getOrCreate(
|
|||
return LiveLocationShareAggregatedSummaryEntity.where(realm, roomId, eventId).findFirst()
|
||||
?: LiveLocationShareAggregatedSummaryEntity.create(realm, roomId, eventId)
|
||||
}
|
||||
|
||||
internal fun LiveLocationShareAggregatedSummaryEntity.Companion.get(
|
||||
realm: Realm,
|
||||
roomId: String,
|
||||
eventId: String,
|
||||
): LiveLocationShareAggregatedSummaryEntity? {
|
||||
return LiveLocationShareAggregatedSummaryEntity.where(realm, roomId, eventId).findFirst()
|
||||
}
|
||||
|
|
|
@ -612,7 +612,7 @@ public class HomeServerConnectionConfig {
|
|||
* - https://www.ssi.gouv.fr/uploads/2017/02/security-recommendations-for-tls_v1.1.pdf
|
||||
* - https://developer.android.com/reference/javax/net/ssl/SSLEngine
|
||||
*
|
||||
* @param tlsLimitations true to use Tls limitations
|
||||
* @param tlsLimitations true to use Tls limitations
|
||||
* @param enableCompatibilityMode set to true for Android < 20
|
||||
* @return this builder
|
||||
*/
|
||||
|
@ -649,7 +649,7 @@ public class HomeServerConnectionConfig {
|
|||
|
||||
/**
|
||||
* @param proxyHostname Proxy Hostname
|
||||
* @param proxyPort Proxy Port
|
||||
* @param proxyPort Proxy Port
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder withProxy(@Nullable String proxyHostname, int proxyPort) {
|
||||
|
|
|
@ -32,6 +32,7 @@ import java.io.IOException
|
|||
* Execute a request from the requestBlock and handle some of the Exception it could generate
|
||||
* Ref: https://github.com/matrix-org/matrix-js-sdk/blob/develop/src/scheduler.js#L138-L175
|
||||
*
|
||||
* @param DATA type of data return by the [requestBlock]
|
||||
* @param globalErrorReceiver will be use to notify error such as invalid token error. See [GlobalError]
|
||||
* @param canRetry if set to true, the request will be executed again in case of error, after a delay
|
||||
* @param maxDelayBeforeRetry the max delay to wait before a retry. Note that in the case of a 429, if the provided delay exceeds this value, the error will
|
||||
|
|
|
@ -119,9 +119,11 @@ internal class RuntimeJsonAdapterFactory<T>(
|
|||
|
||||
companion object {
|
||||
/**
|
||||
* @param T the generic type to pass to [RuntimeJsonAdapterFactory]
|
||||
* @param baseType The base type for which this factory will create adapters. Cannot be Object.
|
||||
* @param labelKey The key in the JSON object whose value determines the type to which to map the
|
||||
* JSON object.
|
||||
* @param fallbackType alternative Type to try in case of the serialization fails
|
||||
*/
|
||||
@CheckReturnValue
|
||||
fun <T> of(baseType: Class<T>, labelKey: String, fallbackType: Class<out T>): RuntimeJsonAdapterFactory<T> {
|
||||
|
|
|
@ -94,6 +94,7 @@ internal object CertUtil {
|
|||
* Convert the fingerprint to an hexa string.
|
||||
*
|
||||
* @param fingerprint the fingerprint
|
||||
* @param sep the separator character, default to space
|
||||
* @return the hexa string.
|
||||
*/
|
||||
fun fingerprintToHexString(fingerprint: ByteArray, sep: Char = ' '): String {
|
||||
|
|
|
@ -24,11 +24,9 @@ import javax.net.ssl.X509TrustManager
|
|||
/**
|
||||
* Implements a TrustManager that checks Certificates against an explicit list of known
|
||||
* fingerprints.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param fingerprints Not empty array of SHA256 cert fingerprints
|
||||
* @param defaultTrustManager Optional trust manager to fall back on if cert does not match
|
||||
*
|
||||
* @property fingerprints Not empty array of SHA256 cert fingerprints
|
||||
* @property defaultTrustManager Optional trust manager to fall back on if cert does not match
|
||||
* any of the fingerprints. Can be null.
|
||||
*/
|
||||
internal class PinnedTrustManager(private val fingerprints: List<Fingerprint>,
|
||||
|
|
|
@ -28,11 +28,9 @@ import javax.net.ssl.X509ExtendedTrustManager
|
|||
/**
|
||||
* Implements a TrustManager that checks Certificates against an explicit list of known
|
||||
* fingerprints.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param fingerprints An array of SHA256 cert fingerprints
|
||||
* @param defaultTrustManager Optional trust manager to fall back on if cert does not match
|
||||
*
|
||||
* @property fingerprints An array of SHA256 cert fingerprints
|
||||
* @property defaultTrustManager Optional trust manager to fall back on if cert does not match
|
||||
* any of the fingerprints. Can be null.
|
||||
*/
|
||||
@RequiresApi(Build.VERSION_CODES.N)
|
||||
|
|
|
@ -46,6 +46,7 @@ import org.matrix.android.sdk.internal.session.profile.ProfileModule
|
|||
import org.matrix.android.sdk.internal.session.pushers.AddPusherWorker
|
||||
import org.matrix.android.sdk.internal.session.pushers.PushersModule
|
||||
import org.matrix.android.sdk.internal.session.room.RoomModule
|
||||
import org.matrix.android.sdk.internal.session.room.aggregation.livelocation.DeactivateLiveLocationShareWorker
|
||||
import org.matrix.android.sdk.internal.session.room.send.MultipleEventSendingDispatcherWorker
|
||||
import org.matrix.android.sdk.internal.session.room.send.RedactEventWorker
|
||||
import org.matrix.android.sdk.internal.session.room.send.SendEventWorker
|
||||
|
@ -131,6 +132,8 @@ internal interface SessionComponent {
|
|||
|
||||
fun inject(worker: UpdateTrustWorker)
|
||||
|
||||
fun inject(worker: DeactivateLiveLocationShareWorker)
|
||||
|
||||
@Component.Factory
|
||||
interface Factory {
|
||||
fun create(
|
||||
|
|
|
@ -87,6 +87,8 @@ import org.matrix.android.sdk.internal.session.integrationmanager.IntegrationMan
|
|||
import org.matrix.android.sdk.internal.session.openid.DefaultOpenIdService
|
||||
import org.matrix.android.sdk.internal.session.permalinks.DefaultPermalinkService
|
||||
import org.matrix.android.sdk.internal.session.room.EventRelationsAggregationProcessor
|
||||
import org.matrix.android.sdk.internal.session.room.aggregation.poll.DefaultPollAggregationProcessor
|
||||
import org.matrix.android.sdk.internal.session.room.aggregation.poll.PollAggregationProcessor
|
||||
import org.matrix.android.sdk.internal.session.room.create.RoomCreateEventProcessor
|
||||
import org.matrix.android.sdk.internal.session.room.prune.RedactionEventProcessor
|
||||
import org.matrix.android.sdk.internal.session.room.send.queue.EventSenderProcessor
|
||||
|
@ -385,4 +387,7 @@ internal abstract class SessionModule {
|
|||
|
||||
@Binds
|
||||
abstract fun bindEventSenderProcessor(processor: EventSenderProcessorCoroutine): EventSenderProcessor
|
||||
|
||||
@Binds
|
||||
abstract fun bindPollAggregationProcessor(processor: DefaultPollAggregationProcessor): PollAggregationProcessor
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ internal interface DirectoryAPI {
|
|||
/**
|
||||
* Add alias to the room.
|
||||
* @param roomAlias the room alias.
|
||||
* @param body the Json body
|
||||
*/
|
||||
@PUT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "directory/room/{roomAlias}")
|
||||
suspend fun addRoomAlias(@Path("roomAlias") roomAlias: String,
|
||||
|
|
|
@ -28,7 +28,7 @@ internal interface FilterApi {
|
|||
* Upload FilterBody to get a filter_id which can be used for /sync requests.
|
||||
*
|
||||
* @param userId the user id
|
||||
* @param body the Json representation of a FilterBody object
|
||||
* @param body the Json representation of a FilterBody object
|
||||
*/
|
||||
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "user/{userId}/filter")
|
||||
suspend fun uploadFilter(@Path("userId") userId: String,
|
||||
|
@ -37,7 +37,7 @@ internal interface FilterApi {
|
|||
/**
|
||||
* Gets a filter with a given filterId from the homeserver.
|
||||
*
|
||||
* @param userId the user id
|
||||
* @param userId the user id
|
||||
* @param filterId the filterID
|
||||
* @return Filter
|
||||
*/
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue