Bump Rust SDK version and adapt our code (#3068)
* Use the new SDK version * Adapt the authentication service to the new Rust SDK APIs * Remove `Timeline.enterSpecialMode(...)` as it's no longer necessary
This commit is contained in:
committed by
GitHub
parent
f163852c4b
commit
cdbb46fa22
@@ -19,6 +19,18 @@ package io.element.android.appconfig
|
||||
object AuthenticationConfig {
|
||||
const val MATRIX_ORG_URL = "https://matrix.org"
|
||||
|
||||
/**
|
||||
* Default homeserver url to sign in with, unless the user selects a different one.
|
||||
*/
|
||||
const val DEFAULT_HOMESERVER_URL = MATRIX_ORG_URL
|
||||
|
||||
/**
|
||||
* URL with some docs that explain what's sliding sync and how to add it to your home server.
|
||||
*/
|
||||
const val SLIDING_SYNC_READ_MORE_URL = "https://github.com/matrix-org/sliding-sync/blob/main/docs/Landing.md"
|
||||
|
||||
/**
|
||||
* Force a sliding sync proxy url, if not null, the proxy url in the .well-known file will be ignored.
|
||||
*/
|
||||
val SLIDING_SYNC_PROXY_URL: String? = null
|
||||
}
|
||||
|
||||
1
changelog.d/3068.misc
Normal file
1
changelog.d/3068.misc
Normal file
@@ -0,0 +1 @@
|
||||
Updated Rust SDK to `v0.2.28`. Fixed incompatibilities.
|
||||
@@ -621,16 +621,8 @@ class MessageComposerPresenter @Inject constructor(
|
||||
) = launch {
|
||||
messageComposerContext.composerMode = composerMode
|
||||
when (composerMode) {
|
||||
is MessageComposerMode.Reply -> {
|
||||
timelineController.invokeOnCurrentTimeline {
|
||||
enterSpecialMode(composerMode.eventId)
|
||||
}
|
||||
}
|
||||
is MessageComposerMode.Edit -> {
|
||||
setText(composerMode.content, markdownTextEditorState, richTextEditorState)
|
||||
timelineController.invokeOnCurrentTimeline {
|
||||
enterSpecialMode(composerMode.eventId)
|
||||
}
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ jsoup = "org.jsoup:jsoup:1.17.2"
|
||||
appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" }
|
||||
molecule-runtime = "app.cash.molecule:molecule-runtime:2.0.0"
|
||||
timber = "com.jakewharton.timber:timber:5.0.1"
|
||||
matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.27"
|
||||
matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.28"
|
||||
matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" }
|
||||
matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" }
|
||||
sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" }
|
||||
|
||||
@@ -17,10 +17,7 @@
|
||||
package io.element.android.libraries.matrix.api.auth
|
||||
|
||||
sealed class AuthenticationException(message: String) : Exception(message) {
|
||||
class ClientMissing(message: String) : AuthenticationException(message)
|
||||
class InvalidServerName(message: String) : AuthenticationException(message)
|
||||
class SlidingSyncNotAvailable(message: String) : AuthenticationException(message)
|
||||
class SessionMissing(message: String) : AuthenticationException(message)
|
||||
class Generic(message: String) : AuthenticationException(message)
|
||||
data class OidcError(val type: String, override val message: String) : AuthenticationException(message)
|
||||
}
|
||||
|
||||
@@ -56,8 +56,6 @@ interface Timeline : AutoCloseable {
|
||||
|
||||
suspend fun editMessage(originalEventId: EventId?, transactionId: TransactionId?, body: String, htmlBody: String?, mentions: List<Mention>): Result<Unit>
|
||||
|
||||
suspend fun enterSpecialMode(eventId: EventId?): Result<Unit>
|
||||
|
||||
suspend fun replyMessage(
|
||||
eventId: EventId,
|
||||
body: String,
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package io.element.android.libraries.matrix.impl
|
||||
|
||||
import io.element.android.appconfig.AuthenticationConfig
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.di.CacheDirectory
|
||||
import io.element.android.libraries.matrix.impl.analytics.UtdTracker
|
||||
@@ -46,11 +47,9 @@ class RustMatrixClientFactory @Inject constructor(
|
||||
private val utdTracker: UtdTracker,
|
||||
) {
|
||||
suspend fun create(sessionData: SessionData): RustMatrixClient = withContext(coroutineDispatchers.io) {
|
||||
val client = getBaseClientBuilder(sessionData.sessionPath)
|
||||
.homeserverUrl(sessionData.homeserverUrl)
|
||||
val client = getBaseClientBuilder(sessionData.sessionPath, sessionData.passphrase)
|
||||
.serverNameOrHomeserverUrl(sessionData.homeserverUrl)
|
||||
.username(sessionData.userId)
|
||||
.passphrase(sessionData.passphrase)
|
||||
// FIXME Quick and dirty fix for stopping version requests on startup https://github.com/matrix-org/matrix-rust-sdk/pull/1376
|
||||
.use { it.build() }
|
||||
|
||||
client.restoreSession(sessionData.toSession())
|
||||
@@ -71,21 +70,20 @@ class RustMatrixClientFactory @Inject constructor(
|
||||
)
|
||||
}
|
||||
|
||||
internal fun getBaseClientBuilder(sessionPath: String): ClientBuilder {
|
||||
internal fun getBaseClientBuilder(sessionPath: String, passphrase: String?): ClientBuilder {
|
||||
return ClientBuilder()
|
||||
.sessionPath(sessionPath)
|
||||
.passphrase(passphrase)
|
||||
.slidingSyncProxy(AuthenticationConfig.SLIDING_SYNC_PROXY_URL)
|
||||
.userAgent(userAgentProvider.provide())
|
||||
.addRootCertificates(userCertificatesProvider.provides())
|
||||
.autoEnableBackups(true)
|
||||
.autoEnableCrossSigning(true)
|
||||
// FIXME Quick and dirty fix for stopping version requests on startup https://github.com/matrix-org/matrix-rust-sdk/pull/1376
|
||||
.serverVersions(listOf("v1.0", "v1.1", "v1.2", "v1.3", "v1.4", "v1.5"))
|
||||
.let {
|
||||
// Sadly ClientBuilder.proxy() does not accept null :/
|
||||
// Tracked by https://github.com/matrix-org/matrix-rust-sdk/issues/3159
|
||||
val proxy = proxyProvider.provides()
|
||||
if (proxy != null) {
|
||||
it.proxy(proxy)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
.run {
|
||||
// Workaround for non-nullable proxy parameter in the SDK, since each call to the ClientBuilder returns a new reference we need to keep
|
||||
proxyProvider.provides()?.let { proxy(it) } ?: this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,22 +17,14 @@
|
||||
package io.element.android.libraries.matrix.impl.auth
|
||||
|
||||
import io.element.android.libraries.matrix.api.auth.AuthenticationException
|
||||
import org.matrix.rustcomponents.sdk.AuthenticationException as RustAuthenticationException
|
||||
import org.matrix.rustcomponents.sdk.ClientBuildException as RustAuthenticationException
|
||||
|
||||
fun Throwable.mapAuthenticationException(): AuthenticationException {
|
||||
val message = this.message ?: "Unknown error"
|
||||
return when (this) {
|
||||
is RustAuthenticationException.ClientMissing -> AuthenticationException.ClientMissing(message)
|
||||
is RustAuthenticationException.Generic -> AuthenticationException.Generic(message)
|
||||
is RustAuthenticationException.InvalidServerName -> AuthenticationException.InvalidServerName(message)
|
||||
is RustAuthenticationException.SessionMissing -> AuthenticationException.SessionMissing(message)
|
||||
is RustAuthenticationException.SlidingSyncNotAvailable -> AuthenticationException.SlidingSyncNotAvailable(message)
|
||||
is RustAuthenticationException.OidcException -> AuthenticationException.OidcError("OidcException", message)
|
||||
is RustAuthenticationException.OidcMetadataInvalid -> AuthenticationException.OidcError("OidcMetadataInvalid", message)
|
||||
is RustAuthenticationException.OidcMetadataMissing -> AuthenticationException.OidcError("OidcMetadataMissing", message)
|
||||
is RustAuthenticationException.OidcNotSupported -> AuthenticationException.OidcError("OidcNotSupported", message)
|
||||
is RustAuthenticationException.OidcCancelled -> AuthenticationException.OidcError("OidcCancelled", message)
|
||||
is RustAuthenticationException.OidcCallbackUrlInvalid -> AuthenticationException.OidcError("OidcCallbackUrlInvalid", message)
|
||||
else -> AuthenticationException.Generic(message)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,12 +32,9 @@ import io.element.android.libraries.matrix.impl.RustMatrixClientFactory
|
||||
import io.element.android.libraries.matrix.impl.auth.qrlogin.QrErrorMapper
|
||||
import io.element.android.libraries.matrix.impl.auth.qrlogin.SdkQrCodeLoginData
|
||||
import io.element.android.libraries.matrix.impl.auth.qrlogin.toStep
|
||||
import io.element.android.libraries.matrix.impl.certificates.UserCertificatesProvider
|
||||
import io.element.android.libraries.matrix.impl.exception.mapClientException
|
||||
import io.element.android.libraries.matrix.impl.keys.PassphraseGenerator
|
||||
import io.element.android.libraries.matrix.impl.mapper.toSessionData
|
||||
import io.element.android.libraries.matrix.impl.proxy.ProxyProvider
|
||||
import io.element.android.libraries.network.useragent.UserAgentProvider
|
||||
import io.element.android.libraries.sessionstorage.api.LoggedInState
|
||||
import io.element.android.libraries.sessionstorage.api.LoginType
|
||||
import io.element.android.libraries.sessionstorage.api.SessionStore
|
||||
@@ -46,17 +43,17 @@ import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.rustcomponents.sdk.Client
|
||||
import org.matrix.rustcomponents.sdk.HumanQrLoginException
|
||||
import org.matrix.rustcomponents.sdk.OidcAuthenticationData
|
||||
import org.matrix.rustcomponents.sdk.QrCodeDecodeException
|
||||
import org.matrix.rustcomponents.sdk.QrLoginProgress
|
||||
import org.matrix.rustcomponents.sdk.QrLoginProgressListener
|
||||
import org.matrix.rustcomponents.sdk.use
|
||||
import timber.log.Timber
|
||||
import uniffi.matrix_sdk.OidcAuthorizationData
|
||||
import java.io.File
|
||||
import java.util.UUID
|
||||
import javax.inject.Inject
|
||||
import org.matrix.rustcomponents.sdk.AuthenticationService as RustAuthenticationService
|
||||
|
||||
@ContributesBinding(AppScope::class)
|
||||
@SingleIn(AppScope::class)
|
||||
@@ -64,28 +61,15 @@ class RustMatrixAuthenticationService @Inject constructor(
|
||||
baseDirectory: File,
|
||||
private val coroutineDispatchers: CoroutineDispatchers,
|
||||
private val sessionStore: SessionStore,
|
||||
userAgentProvider: UserAgentProvider,
|
||||
private val rustMatrixClientFactory: RustMatrixClientFactory,
|
||||
private val passphraseGenerator: PassphraseGenerator,
|
||||
userCertificatesProvider: UserCertificatesProvider,
|
||||
proxyProvider: ProxyProvider,
|
||||
private val oidcConfigurationProvider: OidcConfigurationProvider,
|
||||
) : MatrixAuthenticationService {
|
||||
// Passphrase which will be used for new sessions. Existing sessions will use the passphrase
|
||||
// stored in the SessionData.
|
||||
private val pendingPassphrase = getDatabasePassphrase()
|
||||
private val sessionPath = File(baseDirectory, UUID.randomUUID().toString()).absolutePath
|
||||
private val authService: RustAuthenticationService = RustAuthenticationService(
|
||||
sessionPath = sessionPath,
|
||||
passphrase = pendingPassphrase,
|
||||
proxy = proxyProvider.provides(),
|
||||
userAgent = userAgentProvider.provide(),
|
||||
additionalRootCertificates = userCertificatesProvider.provides(),
|
||||
oidcConfiguration = oidcConfigurationProvider.get(),
|
||||
customSlidingSyncProxy = null,
|
||||
sessionDelegate = null,
|
||||
crossProcessRefreshLockId = null,
|
||||
)
|
||||
private var currentClient: Client? = null
|
||||
private var currentHomeserver = MutableStateFlow<MatrixHomeServerDetails?>(null)
|
||||
|
||||
override fun loggedInStateFlow(): Flow<LoggedInState> {
|
||||
@@ -132,11 +116,14 @@ class RustMatrixAuthenticationService @Inject constructor(
|
||||
override suspend fun setHomeserver(homeserver: String): Result<Unit> =
|
||||
withContext(coroutineDispatchers.io) {
|
||||
runCatching {
|
||||
authService.configureHomeserver(homeserver)
|
||||
val homeServerDetails = authService.homeserverDetails()?.map()
|
||||
if (homeServerDetails != null) {
|
||||
currentHomeserver.value = homeServerDetails.copy(url = homeserver)
|
||||
}
|
||||
val client = getBaseClientBuilder()
|
||||
.serverNameOrHomeserverUrl(homeserver)
|
||||
.build()
|
||||
currentClient = client
|
||||
val homeServerDetails = client.homeserverLoginDetails().map()
|
||||
currentHomeserver.value = homeServerDetails.copy(url = homeserver)
|
||||
}.onFailure {
|
||||
clear()
|
||||
}.mapFailure { failure ->
|
||||
failure.mapAuthenticationException()
|
||||
}
|
||||
@@ -145,15 +132,16 @@ class RustMatrixAuthenticationService @Inject constructor(
|
||||
override suspend fun login(username: String, password: String): Result<SessionId> =
|
||||
withContext(coroutineDispatchers.io) {
|
||||
runCatching {
|
||||
val client = authService.login(username, password, "Element X Android", null)
|
||||
val sessionData = client.use {
|
||||
it.session().toSessionData(
|
||||
val client = currentClient ?: error("You need to call `setHomeserver()` first")
|
||||
client.login(username, password, "Element X Android", null)
|
||||
val sessionData = client.session()
|
||||
.toSessionData(
|
||||
isTokenValid = true,
|
||||
loginType = LoginType.PASSWORD,
|
||||
passphrase = pendingPassphrase,
|
||||
sessionPath = sessionPath,
|
||||
)
|
||||
}
|
||||
clear()
|
||||
sessionStore.storeData(sessionData)
|
||||
SessionId(sessionData.userId)
|
||||
}.mapFailure { failure ->
|
||||
@@ -161,14 +149,15 @@ class RustMatrixAuthenticationService @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private var pendingOidcAuthenticationData: OidcAuthenticationData? = null
|
||||
private var pendingOidcAuthorizationData: OidcAuthorizationData? = null
|
||||
|
||||
override suspend fun getOidcUrl(): Result<OidcDetails> {
|
||||
return withContext(coroutineDispatchers.io) {
|
||||
runCatching {
|
||||
val oidcAuthenticationData = authService.urlForOidcLogin()
|
||||
val client = currentClient ?: error("You need to call `setHomeserver()` first")
|
||||
val oidcAuthenticationData = client.urlForOidcLogin(oidcConfigurationProvider.get())
|
||||
val url = oidcAuthenticationData.loginUrl()
|
||||
pendingOidcAuthenticationData = oidcAuthenticationData
|
||||
pendingOidcAuthorizationData = oidcAuthenticationData
|
||||
OidcDetails(url)
|
||||
}.mapFailure { failure ->
|
||||
failure.mapAuthenticationException()
|
||||
@@ -179,8 +168,8 @@ class RustMatrixAuthenticationService @Inject constructor(
|
||||
override suspend fun cancelOidcLogin(): Result<Unit> {
|
||||
return withContext(coroutineDispatchers.io) {
|
||||
runCatching {
|
||||
pendingOidcAuthenticationData?.close()
|
||||
pendingOidcAuthenticationData = null
|
||||
pendingOidcAuthorizationData?.close()
|
||||
pendingOidcAuthorizationData = null
|
||||
}.mapFailure { failure ->
|
||||
failure.mapAuthenticationException()
|
||||
}
|
||||
@@ -193,18 +182,18 @@ class RustMatrixAuthenticationService @Inject constructor(
|
||||
override suspend fun loginWithOidc(callbackUrl: String): Result<SessionId> {
|
||||
return withContext(coroutineDispatchers.io) {
|
||||
runCatching {
|
||||
val urlForOidcLogin = pendingOidcAuthenticationData ?: error("You need to call `getOidcUrl()` first")
|
||||
val client = authService.loginWithOidcCallback(urlForOidcLogin, callbackUrl)
|
||||
val sessionData = client.use {
|
||||
it.session().toSessionData(
|
||||
isTokenValid = true,
|
||||
loginType = LoginType.OIDC,
|
||||
passphrase = pendingPassphrase,
|
||||
sessionPath = sessionPath,
|
||||
)
|
||||
}
|
||||
pendingOidcAuthenticationData?.close()
|
||||
pendingOidcAuthenticationData = null
|
||||
val client = currentClient ?: error("You need to call `setHomeserver()` first")
|
||||
val urlForOidcLogin = pendingOidcAuthorizationData ?: error("You need to call `getOidcUrl()` first")
|
||||
client.loginWithOidcCallback(urlForOidcLogin, callbackUrl)
|
||||
val sessionData = client.session().toSessionData(
|
||||
isTokenValid = true,
|
||||
loginType = LoginType.OIDC,
|
||||
passphrase = pendingPassphrase,
|
||||
sessionPath = sessionPath,
|
||||
)
|
||||
clear()
|
||||
pendingOidcAuthorizationData?.close()
|
||||
pendingOidcAuthorizationData = null
|
||||
sessionStore.storeData(sessionData)
|
||||
SessionId(sessionData.userId)
|
||||
}.mapFailure { failure ->
|
||||
@@ -216,8 +205,7 @@ class RustMatrixAuthenticationService @Inject constructor(
|
||||
override suspend fun loginWithQrCode(qrCodeData: MatrixQrCodeLoginData, progress: (QrCodeLoginStep) -> Unit) =
|
||||
withContext(coroutineDispatchers.io) {
|
||||
runCatching {
|
||||
val client = rustMatrixClientFactory.getBaseClientBuilder(sessionPath)
|
||||
.passphrase(pendingPassphrase)
|
||||
val client = rustMatrixClientFactory.getBaseClientBuilder(sessionPath, pendingPassphrase)
|
||||
.buildWithQrCode(
|
||||
qrCodeData = (qrCodeData as SdkQrCodeLoginData).rustQrCodeData,
|
||||
oidcConfiguration = oidcConfigurationProvider.get(),
|
||||
@@ -252,4 +240,13 @@ class RustMatrixAuthenticationService @Inject constructor(
|
||||
Timber.e(throwable, "Failed to login with QR code")
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBaseClientBuilder() = rustMatrixClientFactory
|
||||
.getBaseClientBuilder(sessionPath, pendingPassphrase)
|
||||
.requiresSlidingSync()
|
||||
|
||||
private fun clear() {
|
||||
currentClient?.close()
|
||||
currentClient = null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,12 +26,13 @@ internal fun Session.toSessionData(
|
||||
loginType: LoginType,
|
||||
passphrase: String?,
|
||||
sessionPath: String,
|
||||
homeserverUrl: String? = null,
|
||||
) = SessionData(
|
||||
userId = userId,
|
||||
deviceId = deviceId,
|
||||
accessToken = accessToken,
|
||||
refreshToken = refreshToken,
|
||||
homeserverUrl = homeserverUrl,
|
||||
homeserverUrl = homeserverUrl ?: this.homeserverUrl,
|
||||
oidcData = oidcData,
|
||||
slidingSyncProxy = slidingSyncProxy,
|
||||
loginTimestamp = Date(),
|
||||
|
||||
@@ -68,7 +68,6 @@ import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.rustcomponents.sdk.EventTimelineItem
|
||||
import org.matrix.rustcomponents.sdk.FormattedBody
|
||||
import org.matrix.rustcomponents.sdk.MessageFormat
|
||||
import org.matrix.rustcomponents.sdk.RoomMessageEventContentWithoutRelation
|
||||
@@ -252,7 +251,6 @@ class RustTimeline(
|
||||
|
||||
override fun close() {
|
||||
inner.close()
|
||||
specialModeEventTimelineItem?.destroy()
|
||||
}
|
||||
|
||||
private suspend fun fetchMembers() = withContext(dispatcher) {
|
||||
@@ -329,14 +327,10 @@ class RustTimeline(
|
||||
runCatching<Unit> {
|
||||
when {
|
||||
originalEventId != null -> {
|
||||
val editedEvent = specialModeEventTimelineItem ?: inner.getEventTimelineItemByEventId(originalEventId.value)
|
||||
editedEvent.use {
|
||||
inner.edit(
|
||||
newContent = messageEventContentFromParts(body, htmlBody).withMentions(mentions.map()),
|
||||
editItem = it,
|
||||
)
|
||||
}
|
||||
specialModeEventTimelineItem = null
|
||||
inner.edit(
|
||||
newContent = messageEventContentFromParts(body, htmlBody).withMentions(mentions.map()),
|
||||
eventId = originalEventId.value,
|
||||
)
|
||||
}
|
||||
transactionId != null -> {
|
||||
error("Editing local echo is not supported yet.")
|
||||
@@ -348,18 +342,6 @@ class RustTimeline(
|
||||
}
|
||||
}
|
||||
|
||||
private var specialModeEventTimelineItem: EventTimelineItem? = null
|
||||
|
||||
override suspend fun enterSpecialMode(eventId: EventId?): Result<Unit> = withContext(dispatcher) {
|
||||
runCatching {
|
||||
specialModeEventTimelineItem?.destroy()
|
||||
specialModeEventTimelineItem = null
|
||||
specialModeEventTimelineItem = eventId?.let { inner.getEventTimelineItemByEventId(it.value) }
|
||||
}.onFailure {
|
||||
Timber.e(it, "Unable to retrieve event for special mode. Are you using the correct timeline?")
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun replyMessage(
|
||||
eventId: EventId,
|
||||
body: String,
|
||||
@@ -369,19 +351,7 @@ class RustTimeline(
|
||||
): Result<Unit> = withContext(dispatcher) {
|
||||
runCatching {
|
||||
val msg = messageEventContentFromParts(body, htmlBody).withMentions(mentions.map())
|
||||
if (fromNotification) {
|
||||
// When replying from a notification, do not interfere with `specialModeEventTimelineItem`
|
||||
val inReplyTo = inner.getEventTimelineItemByEventId(eventId.value)
|
||||
inReplyTo.use { eventTimelineItem ->
|
||||
inner.sendReply(msg, eventTimelineItem)
|
||||
}
|
||||
} else {
|
||||
val inReplyTo = specialModeEventTimelineItem ?: inner.getEventTimelineItemByEventId(eventId.value)
|
||||
inReplyTo.use { eventTimelineItem ->
|
||||
inner.sendReply(msg, eventTimelineItem)
|
||||
}
|
||||
specialModeEventTimelineItem = null
|
||||
}
|
||||
inner.sendReply(msg, eventId.value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import com.google.common.truth.ThrowableSubject
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.matrix.api.auth.AuthenticationException
|
||||
import org.junit.Test
|
||||
import org.matrix.rustcomponents.sdk.AuthenticationException as RustAuthenticationException
|
||||
import org.matrix.rustcomponents.sdk.ClientBuildException
|
||||
|
||||
class AuthenticationExceptionMappingTest {
|
||||
@Test
|
||||
@@ -39,64 +39,21 @@ class AuthenticationExceptionMappingTest {
|
||||
|
||||
@Test
|
||||
fun `mapping specific exceptions map to their kotlin counterparts`() {
|
||||
assertThat(RustAuthenticationException.ClientMissing("Client missing").mapAuthenticationException())
|
||||
.isException<AuthenticationException.ClientMissing>("Client missing")
|
||||
assertThat(ClientBuildException.Generic("Unknown error").mapAuthenticationException())
|
||||
.isException<AuthenticationException.Generic>("Unknown error")
|
||||
|
||||
assertThat(RustAuthenticationException.Generic("Generic").mapAuthenticationException()).isException<AuthenticationException.Generic>("Generic")
|
||||
|
||||
assertThat(RustAuthenticationException.InvalidServerName("Invalid server name").mapAuthenticationException())
|
||||
assertThat(ClientBuildException.InvalidServerName("Invalid server name").mapAuthenticationException())
|
||||
.isException<AuthenticationException.InvalidServerName>("Invalid server name")
|
||||
|
||||
assertThat(RustAuthenticationException.SessionMissing("Session missing").mapAuthenticationException())
|
||||
.isException<AuthenticationException.SessionMissing>("Session missing")
|
||||
assertThat(ClientBuildException.Sdk("SDK issue").mapAuthenticationException())
|
||||
.isException<AuthenticationException.Generic>("SDK issue")
|
||||
|
||||
assertThat(RustAuthenticationException.SlidingSyncNotAvailable("Sliding sync not available").mapAuthenticationException())
|
||||
assertThat(ClientBuildException.SlidingSyncNotAvailable("Sliding sync not available").mapAuthenticationException())
|
||||
.isException<AuthenticationException.SlidingSyncNotAvailable>("Sliding sync not available")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `mapping Oidc related exceptions creates an 'OidcError' with different types`() {
|
||||
assertIsOidcError(
|
||||
throwable = RustAuthenticationException.OidcException("Oidc exception"),
|
||||
type = "OidcException",
|
||||
message = "Oidc exception"
|
||||
)
|
||||
assertIsOidcError(
|
||||
throwable = RustAuthenticationException.OidcMetadataInvalid("Oidc metadata invalid"),
|
||||
type = "OidcMetadataInvalid",
|
||||
message = "Oidc metadata invalid"
|
||||
)
|
||||
assertIsOidcError(
|
||||
throwable = RustAuthenticationException.OidcMetadataMissing("Oidc metadata missing"),
|
||||
type = "OidcMetadataMissing",
|
||||
message = "Oidc metadata missing"
|
||||
)
|
||||
assertIsOidcError(
|
||||
throwable = RustAuthenticationException.OidcNotSupported("Oidc not supported"),
|
||||
type = "OidcNotSupported",
|
||||
message = "Oidc not supported"
|
||||
)
|
||||
assertIsOidcError(
|
||||
throwable = RustAuthenticationException.OidcCancelled("Oidc cancelled"),
|
||||
type = "OidcCancelled",
|
||||
message = "Oidc cancelled"
|
||||
)
|
||||
assertIsOidcError(
|
||||
throwable = RustAuthenticationException.OidcCallbackUrlInvalid("Oidc callback url invalid"),
|
||||
type = "OidcCallbackUrlInvalid",
|
||||
message = "Oidc callback url invalid"
|
||||
)
|
||||
}
|
||||
|
||||
private inline fun <reified T> ThrowableSubject.isException(message: String) {
|
||||
isInstanceOf(T::class.java)
|
||||
hasMessageThat().isEqualTo(message)
|
||||
}
|
||||
|
||||
private fun assertIsOidcError(throwable: Throwable, type: String, message: String) {
|
||||
val authenticationException = throwable.mapAuthenticationException()
|
||||
assertThat(authenticationException).isInstanceOf(AuthenticationException.OidcError::class.java)
|
||||
assertThat((authenticationException as? AuthenticationException.OidcError)?.type).isEqualTo(type)
|
||||
assertThat(authenticationException.message).isEqualTo(message)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,12 +104,6 @@ class FakeTimeline(
|
||||
mentions
|
||||
)
|
||||
|
||||
var enterSpecialModeLambda: (eventId: EventId?) -> Result<Unit> = {
|
||||
Result.success(Unit)
|
||||
}
|
||||
|
||||
override suspend fun enterSpecialMode(eventId: EventId?): Result<Unit> = enterSpecialModeLambda(eventId)
|
||||
|
||||
var replyMessageLambda: (
|
||||
eventId: EventId,
|
||||
body: String,
|
||||
|
||||
@@ -51,7 +51,6 @@ class MainActivity : ComponentActivity() {
|
||||
baseDirectory = baseDirectory,
|
||||
coroutineDispatchers = Singleton.coroutineDispatchers,
|
||||
sessionStore = sessionStore,
|
||||
userAgentProvider = userAgentProvider,
|
||||
rustMatrixClientFactory = RustMatrixClientFactory(
|
||||
baseDirectory = baseDirectory,
|
||||
cacheDirectory = applicationContext.cacheDir,
|
||||
@@ -65,8 +64,6 @@ class MainActivity : ComponentActivity() {
|
||||
utdTracker = UtdTracker(NoopAnalyticsService()),
|
||||
),
|
||||
passphraseGenerator = NullPassphraseGenerator(),
|
||||
userCertificatesProvider = userCertificatesProvider,
|
||||
proxyProvider = proxyProvider,
|
||||
oidcConfigurationProvider = OidcConfigurationProvider(baseDirectory),
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user