Merge remote-tracking branch 'origin/develop' into feature/bma/mutliAccountNotification
This commit is contained in:
commit
e96cd9e28f
421 changed files with 4365 additions and 4190 deletions
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.api.auth
|
||||
|
||||
/**
|
||||
* Checks the homeserver's compatibility with Element X.
|
||||
*/
|
||||
interface HomeServerLoginCompatibilityChecker {
|
||||
/**
|
||||
* Performs the compatibility check given the homeserver's [url].
|
||||
* @return a `true` value if the homeserver is compatible, `false` if not, or a failure result if the check unexpectedly failed.
|
||||
*/
|
||||
suspend fun check(url: String): Result<Boolean>
|
||||
}
|
||||
|
|
@ -33,6 +33,7 @@ import org.matrix.rustcomponents.sdk.RequestConfig
|
|||
import org.matrix.rustcomponents.sdk.Session
|
||||
import org.matrix.rustcomponents.sdk.SlidingSyncVersion
|
||||
import org.matrix.rustcomponents.sdk.SlidingSyncVersionBuilder
|
||||
import org.matrix.rustcomponents.sdk.SqliteStoreBuilder
|
||||
import org.matrix.rustcomponents.sdk.use
|
||||
import timber.log.Timber
|
||||
import uniffi.matrix_sdk_crypto.CollectStrategy
|
||||
|
|
@ -105,12 +106,13 @@ class RustMatrixClientFactory(
|
|||
slidingSyncType: ClientBuilderSlidingSync,
|
||||
): ClientBuilder {
|
||||
return clientBuilderProvider.provide()
|
||||
.sessionPaths(
|
||||
dataPath = sessionPaths.fileDirectory.absolutePath,
|
||||
cachePath = sessionPaths.cacheDirectory.absolutePath,
|
||||
.sqliteStore(
|
||||
SqliteStoreBuilder(
|
||||
dataPath = sessionPaths.fileDirectory.absolutePath,
|
||||
cachePath = sessionPaths.cacheDirectory.absolutePath,
|
||||
).passphrase(passphrase)
|
||||
)
|
||||
.setSessionDelegate(sessionDelegate)
|
||||
.sessionPassphrase(passphrase)
|
||||
.userAgent(userAgentProvider.provide())
|
||||
.addRootCertificates(userCertificatesProvider.provides())
|
||||
.autoEnableBackups(true)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.impl.auth
|
||||
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.ContributesBinding
|
||||
import dev.zacsweers.metro.Inject
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.matrix.api.auth.HomeServerLoginCompatibilityChecker
|
||||
import io.element.android.libraries.matrix.impl.ClientBuilderProvider
|
||||
import timber.log.Timber
|
||||
|
||||
@ContributesBinding(AppScope::class)
|
||||
@Inject
|
||||
class RustHomeServerLoginCompatibilityChecker(
|
||||
private val clientBuilderProvider: ClientBuilderProvider,
|
||||
) : HomeServerLoginCompatibilityChecker {
|
||||
override suspend fun check(url: String): Result<Boolean> = runCatchingExceptions {
|
||||
clientBuilderProvider.provide()
|
||||
.inMemoryStore()
|
||||
.serverNameOrHomeserverUrl(url)
|
||||
.build()
|
||||
.use {
|
||||
it.homeserverLoginDetails()
|
||||
}
|
||||
.use {
|
||||
Timber.d("Homeserver $url | OIDC: ${it.supportsOidcLogin()} | Password: ${it.supportsPasswordLogin()} | SSO: ${it.supportsSsoLogin()}")
|
||||
it.supportsOidcLogin() || it.supportsPasswordLogin()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -285,7 +285,6 @@ class RustMatrixAuthenticationService(
|
|||
runCatchingExceptions {
|
||||
val client = makeQrCodeLoginClient(
|
||||
sessionPaths = emptySessionPaths,
|
||||
passphrase = pendingPassphrase,
|
||||
qrCodeData = sdkQrCodeLoginData,
|
||||
)
|
||||
client.loginWithQrCode(
|
||||
|
|
@ -344,7 +343,6 @@ class RustMatrixAuthenticationService(
|
|||
|
||||
private suspend fun makeQrCodeLoginClient(
|
||||
sessionPaths: SessionPaths,
|
||||
passphrase: String?,
|
||||
qrCodeData: QrCodeData,
|
||||
): Client {
|
||||
Timber.d("Creating client for QR Code login with simplified sliding sync")
|
||||
|
|
@ -354,7 +352,6 @@ class RustMatrixAuthenticationService(
|
|||
passphrase = pendingPassphrase,
|
||||
slidingSyncType = ClientBuilderSlidingSync.Discovered,
|
||||
)
|
||||
.sessionPassphrase(passphrase)
|
||||
.serverNameOrHomeserverUrl(qrCodeData.serverName()!!)
|
||||
.build()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ class NotificationMapper(
|
|||
isDirect = item.roomInfo.isDirect,
|
||||
activeMembersCount = item.roomInfo.joinedMembersCount.toInt(),
|
||||
)
|
||||
val timestamp = item.timestamp() ?: clock.epochMillis()
|
||||
NotificationData(
|
||||
sessionId = sessionId,
|
||||
eventId = eventId,
|
||||
|
|
@ -53,8 +54,8 @@ class NotificationMapper(
|
|||
isDm = isDm,
|
||||
isEncrypted = item.roomInfo.isEncrypted.orFalse(),
|
||||
isNoisy = item.isNoisy.orFalse(),
|
||||
timestamp = item.timestamp() ?: clock.epochMillis(),
|
||||
content = item.event.use { notificationContentMapper.map(it) }.getOrThrow(),
|
||||
timestamp = timestamp,
|
||||
content = notificationContentMapper.map(item.event).getOrThrow(),
|
||||
hasMention = item.hasMention.orFalse(),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,8 +25,9 @@ class TimelineEventToNotificationContentMapper {
|
|||
fun map(timelineEvent: TimelineEvent): Result<NotificationContent> {
|
||||
return runCatchingExceptions {
|
||||
timelineEvent.use {
|
||||
val senderId = UserId(timelineEvent.senderId())
|
||||
timelineEvent.eventType().use { eventType ->
|
||||
eventType.toContent(senderId = UserId(timelineEvent.senderId()))
|
||||
eventType.toContent(senderId = senderId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.impl.auth
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.matrix.impl.FakeClientBuilderProvider
|
||||
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiClient
|
||||
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiClientBuilder
|
||||
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiHomeserverLoginDetails
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
class RustHomeserverLoginCompatibilityCheckerTest {
|
||||
@Test
|
||||
fun `check - is valid if it supports OIDC login`() = runTest {
|
||||
val sut = createChecker { FakeFfiHomeserverLoginDetails(supportsOidcLogin = true) }
|
||||
assertThat(sut.check("https://matrix.host.org").getOrNull()).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `check - is valid if it supports password login`() = runTest {
|
||||
val sut = createChecker { FakeFfiHomeserverLoginDetails(supportsPasswordLogin = true) }
|
||||
assertThat(sut.check("https://matrix.host.org").getOrNull()).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `check - is not valid if it only supports SSO login`() = runTest {
|
||||
val sut = createChecker { FakeFfiHomeserverLoginDetails(supportsSsoLogin = true) }
|
||||
assertThat(sut.check("https://matrix.host.org").getOrNull()).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `check - is not valid if fetching the data fails`() = runTest {
|
||||
val sut = createChecker { error("Unexpected error!") }
|
||||
assertThat(sut.check("https://matrix.host.org").isFailure).isTrue()
|
||||
}
|
||||
|
||||
private fun createChecker(
|
||||
result: () -> FakeFfiHomeserverLoginDetails,
|
||||
) = RustHomeServerLoginCompatibilityChecker(
|
||||
clientBuilderProvider = FakeClientBuilderProvider {
|
||||
FakeFfiClientBuilder {
|
||||
FakeFfiClient(homeserverLoginDetailsResult = result)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@ import org.matrix.rustcomponents.sdk.ClientSessionDelegate
|
|||
import org.matrix.rustcomponents.sdk.NoHandle
|
||||
import org.matrix.rustcomponents.sdk.RequestConfig
|
||||
import org.matrix.rustcomponents.sdk.SlidingSyncVersionBuilder
|
||||
import org.matrix.rustcomponents.sdk.SqliteStoreBuilder
|
||||
import uniffi.matrix_sdk.BackupDownloadStrategy
|
||||
import uniffi.matrix_sdk_crypto.CollectStrategy
|
||||
import uniffi.matrix_sdk_crypto.DecryptionSettings
|
||||
|
|
@ -29,7 +30,6 @@ class FakeFfiClientBuilder(
|
|||
override fun decryptionSettings(decryptionSettings: DecryptionSettings): ClientBuilder = this
|
||||
override fun disableSslVerification() = this
|
||||
override fun homeserverUrl(url: String) = this
|
||||
override fun sessionPassphrase(passphrase: String?) = this
|
||||
override fun proxy(url: String) = this
|
||||
override fun requestConfig(config: RequestConfig) = this
|
||||
override fun roomKeyRecipientStrategy(strategy: CollectStrategy) = this
|
||||
|
|
@ -42,5 +42,6 @@ class FakeFfiClientBuilder(
|
|||
override fun username(username: String) = this
|
||||
override fun enableShareHistoryOnInvite(enableShareHistoryOnInvite: Boolean): ClientBuilder = this
|
||||
override fun threadsEnabled(enabled: Boolean, threadSubscriptions: Boolean): ClientBuilder = this
|
||||
override fun sqliteStore(config: SqliteStoreBuilder): ClientBuilder = this
|
||||
override suspend fun build() = buildResult()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,10 +12,12 @@ import org.matrix.rustcomponents.sdk.NoHandle
|
|||
|
||||
class FakeFfiHomeserverLoginDetails(
|
||||
private val url: String = "https://example.org",
|
||||
private val supportsPasswordLogin: Boolean = true,
|
||||
private val supportsOidcLogin: Boolean = false
|
||||
private val supportsPasswordLogin: Boolean = false,
|
||||
private val supportsOidcLogin: Boolean = false,
|
||||
private val supportsSsoLogin: Boolean = false,
|
||||
) : HomeserverLoginDetails(NoHandle) {
|
||||
override fun url(): String = url
|
||||
override fun supportsOidcLogin(): Boolean = supportsOidcLogin
|
||||
override fun supportsPasswordLogin(): Boolean = supportsPasswordLogin
|
||||
override fun supportsSsoLogin(): Boolean = supportsSsoLogin
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.test.auth
|
||||
|
||||
import io.element.android.libraries.matrix.api.auth.HomeServerLoginCompatibilityChecker
|
||||
|
||||
class FakeHomeServerLoginCompatibilityChecker(
|
||||
private val checkResult: (String) -> Result<Boolean>,
|
||||
) : HomeServerLoginCompatibilityChecker {
|
||||
override suspend fun check(url: String): Result<Boolean> {
|
||||
return checkResult(url)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue