diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index ba20cbea2d..6906953232 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -136,7 +136,12 @@ class RustMatrixClient constructor( override fun didRefreshTokens() { Timber.w("didRefreshTokens()") appCoroutineScope.launch { - sessionStore.updateData(client.session().toSessionData()) + val existingData = sessionStore.getSession(client.userId()) ?: return@launch + val newData = client.session().toSessionData( + isTokenValid = existingData.isTokenValid, + loginType = existingData.loginType, + ) + sessionStore.updateData(newData) } } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt index f2acb0b1be..af0c335dda 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt @@ -30,6 +30,7 @@ import io.element.android.libraries.matrix.impl.RustMatrixClientFactory import io.element.android.libraries.matrix.impl.exception.mapClientException import io.element.android.libraries.matrix.impl.mapper.toSessionData import io.element.android.libraries.network.useragent.UserAgentProvider +import io.element.android.libraries.sessionstorage.api.LoginType import io.element.android.libraries.sessionstorage.api.SessionStore import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow @@ -102,7 +103,12 @@ class RustMatrixAuthenticationService @Inject constructor( withContext(coroutineDispatchers.io) { runCatching { val client = authService.login(username, password, "Element X Android", null) - val sessionData = client.use { it.session().toSessionData() } + val sessionData = client.use { + it.session().toSessionData( + isTokenValid = true, + loginType = LoginType.PASSWORD, + ) + } sessionStore.storeData(sessionData) SessionId(sessionData.userId) }.mapFailure { failure -> @@ -144,7 +150,12 @@ class RustMatrixAuthenticationService @Inject constructor( runCatching { val urlForOidcLogin = pendingOidcAuthenticationData ?: error("You need to call `getOidcUrl()` first") val client = authService.loginWithOidcCallback(urlForOidcLogin, callbackUrl) - val sessionData = client.use { it.session().toSessionData() } + val sessionData = client.use { + it.session().toSessionData( + isTokenValid = true, + loginType = LoginType.OIDC, + ) + } pendingOidcAuthenticationData?.close() pendingOidcAuthenticationData = null sessionStore.storeData(sessionData) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/mapper/Session.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/mapper/Session.kt index 825c6f4397..fe21a460c8 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/mapper/Session.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/mapper/Session.kt @@ -16,11 +16,15 @@ package io.element.android.libraries.matrix.impl.mapper +import io.element.android.libraries.sessionstorage.api.LoginType import io.element.android.libraries.sessionstorage.api.SessionData import org.matrix.rustcomponents.sdk.Session import java.util.Date -internal fun Session.toSessionData() = SessionData( +internal fun Session.toSessionData( + isTokenValid: Boolean, + loginType: LoginType, +) = SessionData( userId = userId, deviceId = deviceId, accessToken = accessToken, @@ -29,4 +33,6 @@ internal fun Session.toSessionData() = SessionData( oidcData = oidcData, slidingSyncProxy = slidingSyncProxy, loginTimestamp = Date(), + isTokenValid = isTokenValid, + loginType = loginType, ) diff --git a/libraries/session-storage/api/src/main/kotlin/io/element/android/libraries/sessionstorage/api/LoginType.kt b/libraries/session-storage/api/src/main/kotlin/io/element/android/libraries/sessionstorage/api/LoginType.kt new file mode 100644 index 0000000000..a1e4400797 --- /dev/null +++ b/libraries/session-storage/api/src/main/kotlin/io/element/android/libraries/sessionstorage/api/LoginType.kt @@ -0,0 +1,43 @@ +/* + * 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 io.element.android.libraries.sessionstorage.api + +// Imported from Element Android, to be able to migrate from EA to EXA. +enum class LoginType { + PASSWORD, + OIDC, + SSO, + UNSUPPORTED, + CUSTOM, + DIRECT, + UNKNOWN, + QR; + + companion object { + + fun fromName(name: String) = when (name) { + PASSWORD.name -> PASSWORD + OIDC.name -> OIDC + SSO.name -> SSO + UNSUPPORTED.name -> UNSUPPORTED + CUSTOM.name -> CUSTOM + DIRECT.name -> DIRECT + QR.name -> QR + else -> UNKNOWN + } + } +} diff --git a/libraries/session-storage/api/src/main/kotlin/io/element/android/libraries/sessionstorage/api/SessionData.kt b/libraries/session-storage/api/src/main/kotlin/io/element/android/libraries/sessionstorage/api/SessionData.kt index e14c3feeab..25a48c0efe 100644 --- a/libraries/session-storage/api/src/main/kotlin/io/element/android/libraries/sessionstorage/api/SessionData.kt +++ b/libraries/session-storage/api/src/main/kotlin/io/element/android/libraries/sessionstorage/api/SessionData.kt @@ -27,4 +27,6 @@ data class SessionData( val oidcData: String?, val slidingSyncProxy: String?, val loginTimestamp: Date?, + val isTokenValid: Boolean, + val loginType: LoginType, ) diff --git a/libraries/session-storage/impl/src/main/kotlin/io/element/android/libraries/sessionstorage/impl/SessionDataMapper.kt b/libraries/session-storage/impl/src/main/kotlin/io/element/android/libraries/sessionstorage/impl/SessionDataMapper.kt index d0c89d9896..7c00d98f91 100644 --- a/libraries/session-storage/impl/src/main/kotlin/io/element/android/libraries/sessionstorage/impl/SessionDataMapper.kt +++ b/libraries/session-storage/impl/src/main/kotlin/io/element/android/libraries/sessionstorage/impl/SessionDataMapper.kt @@ -16,6 +16,7 @@ package io.element.android.libraries.sessionstorage.impl +import io.element.android.libraries.sessionstorage.api.LoginType import io.element.android.libraries.sessionstorage.api.SessionData import java.util.Date import io.element.android.libraries.matrix.session.SessionData as DbSessionData @@ -30,6 +31,8 @@ internal fun SessionData.toDbModel(): DbSessionData { oidcData = oidcData, slidingSyncProxy = slidingSyncProxy, loginTimestamp = loginTimestamp?.time, + isTokenValid = if (isTokenValid) 1L else 0L, + loginType = loginType.name, ) } @@ -42,6 +45,8 @@ internal fun DbSessionData.toApiModel(): SessionData { homeserverUrl = homeserverUrl, oidcData = oidcData, slidingSyncProxy = slidingSyncProxy, - loginTimestamp = loginTimestamp?.let { Date(it) } + loginTimestamp = loginTimestamp?.let { Date(it) }, + isTokenValid = (isTokenValid ?: 1) == 1L, + loginType = LoginType.fromName(loginType ?: LoginType.UNKNOWN.name), ) } diff --git a/libraries/session-storage/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseSessionStoreTests.kt b/libraries/session-storage/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseSessionStoreTests.kt index e035ff9ae1..b24543e9d9 100644 --- a/libraries/session-storage/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseSessionStoreTests.kt +++ b/libraries/session-storage/impl/src/test/kotlin/io/element/android/libraries/sessionstorage/impl/DatabaseSessionStoreTests.kt @@ -38,6 +38,8 @@ class DatabaseSessionStoreTests { slidingSyncProxy = null, loginTimestamp = null, oidcData = "aOidcData", + isTokenValid = null, + loginType = null, ) @Before @@ -121,6 +123,8 @@ class DatabaseSessionStoreTests { slidingSyncProxy = "slidingSyncProxy", loginTimestamp = 1, oidcData = "aOidcData", + isTokenValid = null, + loginType = null, ) val secondSessionData = SessionData( userId = "userId", @@ -131,6 +135,8 @@ class DatabaseSessionStoreTests { slidingSyncProxy = "slidingSyncProxyAltered", loginTimestamp = 2, oidcData = "aOidcDataAltered", + isTokenValid = null, + loginType = null, ) assertThat(firstSessionData.userId).isEqualTo(secondSessionData.userId) assertThat(firstSessionData.loginTimestamp).isNotEqualTo(secondSessionData.loginTimestamp)