Merge branch 'test/jme/base-path-migration' into feature/fga/update_rust_sdk_0.2.25

This commit is contained in:
ganfra 2024-06-12 11:44:57 +02:00
commit 1803e11942
16 changed files with 113 additions and 37 deletions

View file

@ -63,7 +63,7 @@ import io.element.android.libraries.matrix.impl.roomlist.RustRoomListService
import io.element.android.libraries.matrix.impl.sync.RustSyncService
import io.element.android.libraries.matrix.impl.usersearch.UserProfileMapper
import io.element.android.libraries.matrix.impl.usersearch.UserSearchResultMapper
import io.element.android.libraries.matrix.impl.util.SessionDirectoryNameProvider
import io.element.android.libraries.matrix.impl.util.SessionDirectoryProvider
import io.element.android.libraries.matrix.impl.util.cancelAndDestroy
import io.element.android.libraries.matrix.impl.util.mxCallbackFlow
import io.element.android.libraries.matrix.impl.verification.RustSessionVerificationService
@ -152,7 +152,7 @@ class RustMatrixClient(
sessionDispatcher = sessionDispatcher,
)
private val sessionDirectoryNameProvider = SessionDirectoryNameProvider()
private val sessionDirectoryProvider = SessionDirectoryProvider(sessionStore)
private val isLoggingOut = AtomicBoolean(false)
@ -172,6 +172,7 @@ class RustMatrixClient(
isTokenValid = false,
loginType = existingData.loginType,
passphrase = existingData.passphrase,
sessionPath = existingData.sessionPath,
)
sessionStore.updateData(newData)
Timber.d("Removed session data with token: '...$anonymizedToken'.")
@ -199,6 +200,7 @@ class RustMatrixClient(
isTokenValid = true,
loginType = existingData.loginType,
passphrase = existingData.passphrase,
sessionPath = existingData.sessionPath,
)
sessionStore.updateData(newData)
Timber.d("Saved new session data with token: '...$anonymizedToken'.")
@ -483,7 +485,7 @@ class RustMatrixClient(
override suspend fun clearCache() {
close()
baseDirectory.deleteSessionDirectory(deleteCryptoDb = false)
deleteSessionDirectory(deleteCryptoDb = false)
}
override suspend fun logout(ignoreSdkError: Boolean): String? = doLogout(
@ -513,7 +515,7 @@ class RustMatrixClient(
}
}
close()
baseDirectory.deleteSessionDirectory(deleteCryptoDb = true)
deleteSessionDirectory(deleteCryptoDb = true)
if (removeSession) {
sessionStore.removeSession(sessionId.value)
}
@ -570,8 +572,7 @@ class RustMatrixClient(
private suspend fun File.getCacheSize(
includeCryptoDb: Boolean = false,
): Long = withContext(sessionDispatcher) {
val sessionDirectoryName = sessionDirectoryNameProvider.provides(sessionId)
val sessionDirectory = File(this@getCacheSize, sessionDirectoryName)
val sessionDirectory = sessionDirectoryProvider.provides(sessionId) ?: return@withContext 0L
if (includeCryptoDb) {
sessionDirectory.getSizeOfFiles()
} else {
@ -587,11 +588,10 @@ class RustMatrixClient(
}
}
private suspend fun File.deleteSessionDirectory(
private suspend fun deleteSessionDirectory(
deleteCryptoDb: Boolean = false,
): Boolean = withContext(sessionDispatcher) {
val sessionDirectoryName = sessionDirectoryNameProvider.provides(sessionId)
val sessionDirectory = File(this@deleteSessionDirectory, sessionDirectoryName)
val sessionDirectory = sessionDirectoryProvider.provides(sessionId) ?: return@withContext false
if (deleteCryptoDb) {
// Delete the folder and all its content
sessionDirectory.deleteRecursively()

View file

@ -46,7 +46,7 @@ class RustMatrixClientFactory @Inject constructor(
private val utdTracker: UtdTracker,
) {
suspend fun create(sessionData: SessionData): RustMatrixClient = withContext(coroutineDispatchers.io) {
val client = getBaseClientBuilder()
val client = getBaseClientBuilder(sessionData.sessionPath)
.homeserverUrl(sessionData.homeserverUrl)
.username(sessionData.userId)
.passphrase(sessionData.passphrase)
@ -71,9 +71,9 @@ class RustMatrixClientFactory @Inject constructor(
)
}
internal fun getBaseClientBuilder(): ClientBuilder {
internal fun getBaseClientBuilder(sessionPath: String): ClientBuilder {
return ClientBuilder()
.basePath(baseDirectory.absolutePath)
.sessionPath(sessionPath)
.userAgent(userAgentProvider.provide())
.addRootCertificates(userCertificatesProvider.provides())
.serverVersions(listOf("v1.0", "v1.1", "v1.2", "v1.3", "v1.4", "v1.5"))

View file

@ -18,19 +18,26 @@ package io.element.android.libraries.matrix.impl.auth
import io.element.android.libraries.matrix.api.auth.OidcConfig
import org.matrix.rustcomponents.sdk.OidcConfiguration
import java.io.File
import javax.inject.Inject
val oidcConfiguration: OidcConfiguration = OidcConfiguration(
clientName = "Element",
redirectUri = OidcConfig.REDIRECT_URI,
clientUri = "https://element.io",
logoUri = "https://element.io/mobile-icon.png",
tosUri = "https://element.io/acceptable-use-policy-terms",
policyUri = "https://element.io/privacy",
contacts = listOf(
"support@element.io",
),
// Some homeservers/auth issuers don't support dynamic client registration, and have to be registered manually
staticRegistrations = mapOf(
"https://id.thirdroom.io/realms/thirdroom" to "elementx",
),
)
class OidConfigurationProvider @Inject constructor(
private val baseDirectory: File,
) {
fun get(): OidcConfiguration = OidcConfiguration(
clientName = "Element",
redirectUri = OidcConfig.REDIRECT_URI,
clientUri = "https://element.io",
logoUri = "https://element.io/mobile-icon.png",
tosUri = "https://element.io/acceptable-use-policy-terms",
policyUri = "https://element.io/privacy",
contacts = listOf(
"support@element.io",
),
// Some homeservers/auth issuers don't support dynamic client registration, and have to be registered manually
staticRegistrations = mapOf(
"https://id.thirdroom.io/realms/thirdroom" to "elementx",
),
dynamicRegistrationsFile = File(baseDirectory, "oidc/registrations.json").absolutePath,
)
}

View file

@ -54,6 +54,7 @@ import org.matrix.rustcomponents.sdk.QrLoginProgressListener
import org.matrix.rustcomponents.sdk.use
import timber.log.Timber
import java.io.File
import java.util.UUID
import javax.inject.Inject
import org.matrix.rustcomponents.sdk.AuthenticationService as RustAuthenticationService
@ -68,17 +69,19 @@ class RustMatrixAuthenticationService @Inject constructor(
private val passphraseGenerator: PassphraseGenerator,
userCertificatesProvider: UserCertificatesProvider,
proxyProvider: ProxyProvider,
private val oidConfigurationProvider: OidConfigurationProvider,
) : 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(
basePath = baseDirectory.absolutePath,
sessionPath = sessionPath,
passphrase = pendingPassphrase,
proxy = proxyProvider.provides(),
userAgent = userAgentProvider.provide(),
additionalRootCertificates = userCertificatesProvider.provides(),
oidcConfiguration = oidcConfiguration,
oidcConfiguration = oidConfigurationProvider.get(),
customSlidingSyncProxy = null,
sessionDelegate = null,
crossProcessRefreshLockId = null,
@ -148,6 +151,7 @@ class RustMatrixAuthenticationService @Inject constructor(
isTokenValid = true,
loginType = LoginType.PASSWORD,
passphrase = pendingPassphrase,
sessionPath = sessionPath,
)
}
sessionStore.storeData(sessionData)
@ -196,6 +200,7 @@ class RustMatrixAuthenticationService @Inject constructor(
isTokenValid = true,
loginType = LoginType.OIDC,
passphrase = pendingPassphrase,
sessionPath = sessionPath,
)
}
pendingOidcAuthenticationData?.close()
@ -211,11 +216,11 @@ class RustMatrixAuthenticationService @Inject constructor(
override suspend fun loginWithQrCode(qrCodeData: MatrixQrCodeLoginData, progress: (QrCodeLoginStep) -> Unit) =
withContext(coroutineDispatchers.io) {
runCatching {
val client = rustMatrixClientFactory.getBaseClientBuilder()
val client = rustMatrixClientFactory.getBaseClientBuilder(sessionPath)
.passphrase(pendingPassphrase)
.buildWithQrCode(
qrCodeData = (qrCodeData as SdkQrCodeLoginData).rustQrCodeData,
oidcConfiguration = oidcConfiguration,
oidcConfiguration = oidConfigurationProvider.get(),
progressListener = object : QrLoginProgressListener {
override fun onUpdate(state: QrLoginProgress) {
Timber.d("QR Code login progress: $state")
@ -229,6 +234,7 @@ class RustMatrixAuthenticationService @Inject constructor(
isTokenValid = true,
loginType = LoginType.QR,
passphrase = pendingPassphrase,
sessionPath = sessionPath,
)
sessionStore.storeData(sessionData)
SessionId(sessionData.userId)

View file

@ -25,6 +25,7 @@ internal fun Session.toSessionData(
isTokenValid: Boolean,
loginType: LoginType,
passphrase: String?,
sessionPath: String,
) = SessionData(
userId = userId,
deviceId = deviceId,
@ -37,4 +38,5 @@ internal fun Session.toSessionData(
isTokenValid = isTokenValid,
loginType = loginType,
passphrase = passphrase,
sessionPath = sessionPath,
)

View file

@ -281,6 +281,7 @@ class RustTimeline(
messageEventContentFromParts(body, htmlBody).withMentions(mentions.map()).use { content ->
runCatching<Unit> {
inner.send(content)
Unit
}
}
}

View file

@ -17,10 +17,15 @@
package io.element.android.libraries.matrix.impl.util
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.sessionstorage.api.SessionStore
import java.io.File
import javax.inject.Inject
class SessionDirectoryNameProvider {
// Rust sanitises the user ID replacing invalid characters with an _
fun provides(sessionId: SessionId): String {
return sessionId.value.replace(":", "_")
class SessionDirectoryProvider @Inject constructor(
private val sessionStore: SessionStore,
) {
suspend fun provides(sessionId: SessionId): File? {
val path = sessionStore.getSession(sessionId.value)?.sessionPath ?: return null
return File(path)
}
}