Skip to content
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
dab866d
Forces soft logout to be true for testing
ericdecanini Mar 2, 2022
448e8e0
Reimplements soft logout simulation
ericdecanini Mar 2, 2022
12dc8a8
Tests sso login mode
ericdecanini Mar 2, 2022
209a442
Adds LoginType to SessionParams and its entity
ericdecanini Mar 3, 2022
25e73e5
Adds SessionParamsMapper tests
ericdecanini Mar 3, 2022
187502c
Refactors SessionParamsMapperTest by adding fake moshi
ericdecanini Mar 3, 2022
d33081c
Refactors SessionParamsMapperTest by adding fake json adapters
ericdecanini Mar 3, 2022
dffd568
Adds AuthTo005 realm migration
ericdecanini Mar 3, 2022
b82efe9
Moves test packages
ericdecanini Mar 3, 2022
d3d99dd
Replaces mocks with fixtures in fake json adapters
ericdecanini Mar 3, 2022
47d5d09
Fixes lint errors
ericdecanini Mar 3, 2022
40dee00
Refactors SessionCreator with added tests
ericdecanini Mar 3, 2022
ea53462
Adds loginType to DefaultLegacySessionImporter
ericdecanini Mar 3, 2022
32bde5a
Adds loginType UNSUPPORTED
ericdecanini Mar 4, 2022
2fda593
Adds login types to auth flows
ericdecanini Mar 4, 2022
92f87a3
Adds login type handling to SoftLogoutController
ericdecanini Mar 4, 2022
275505b
Fixes lint errors
ericdecanini Mar 4, 2022
bb2369d
Fixes broken tests due to uninitialised HomeServerConnectionConfig ho…
ericdecanini Mar 4, 2022
bcd802d
Changes login types in wizards
ericdecanini Mar 4, 2022
489670c
Adds validation failed test for SessionParamsCreator
ericdecanini Mar 4, 2022
c996f87
Fixes Uri EMPTY must not be null
ericdecanini Mar 4, 2022
2d07b80
Fixes broken migration test
ericdecanini Mar 4, 2022
7896bf9
Removes HomeServerConnectionConfigFixture
ericdecanini Mar 4, 2022
9bd3254
Removes HomeServerConnectionConfigFixture in fake adapter
ericdecanini Mar 4, 2022
8589238
Adds Uri static mocking
ericdecanini Mar 7, 2022
6338941
Temporarily removes unit tests
ericdecanini Mar 7, 2022
22b21b8
Adds changelog file
ericdecanini Mar 7, 2022
e8432f3
Adds setRequired to migration
ericdecanini Mar 7, 2022
085dd94
Fixes wrong legal comment on LoginType
ericdecanini Mar 7, 2022
0d75273
Adds stubbing and verification for migration setRequired
ericdecanini Mar 7, 2022
e1f227a
Fixes legal comments in matrix sdk files added
ericdecanini Mar 7, 2022
04af8b2
Changes LoginActivity onSignModeSelected SSO case
ericdecanini Mar 7, 2022
6836a12
Fixes legal comments
ericdecanini Mar 7, 2022
ec57ff1
Adds attempt at SSO session restore
ericdecanini Mar 9, 2022
70b5b98
Removes debug global error
ericdecanini Mar 9, 2022
ae54029
Adds custom and direct login types
ericdecanini Mar 15, 2022
a173acc
Replaces use of LoginType.value with name
ericdecanini Mar 15, 2022
ef59faf
Adds error throw for LoginActivity LoginMode Unknown
ericdecanini Mar 15, 2022
21459db
Replaces login type unknown value with name in migration
ericdecanini Mar 15, 2022
5fcae7f
Adds direct and custom types to soft logout disambiguation
ericdecanini Mar 15, 2022
ce579c1
Merge remote-tracking branch 'origin/develop' into bugfix/eric/softlo…
ericdecanini Mar 28, 2022
9b479ca
Merge remote-tracking branch 'origin/develop' into bugfix/eric/softlo…
ericdecanini Apr 20, 2022
92d177a
Makes MigrateAuthTo005 class internal
ericdecanini Apr 20, 2022
b125498
Merge remote-tracking branch 'origin/develop' into bugfix/eric/softlo…
ericdecanini May 17, 2022
6a3044c
Fixes post merge errors
ericdecanini May 17, 2022
61b8053
Moves LoginType to sdk api package
ericdecanini May 18, 2022
a71c50c
Fixes lint error
ericdecanini May 18, 2022
fe27451
Fixes lint error
ericdecanini May 18, 2022
4cf97d4
Merge remote-tracking branch 'origin/develop' into bugfix/eric/softlo…
ericdecanini Jun 29, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/5398.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Adds LoginType to SessionParams to fix soft logout form not showing for SSO and Password type
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package org.matrix.android.sdk.api.auth.data

import org.matrix.android.sdk.internal.auth.login.LoginType

/**
* This data class holds necessary data to open a session.
* You don't have to manually instantiate it.
Expand All @@ -34,7 +36,12 @@ data class SessionParams(
/**
* Set to false if the current token is not valid anymore. Application should not have to use this info.
*/
val isTokenValid: Boolean
val isTokenValid: Boolean,

/**
* Which authentication method was used to create the session
*/
val loginType: LoginType,
) {
/*
* Shortcuts. Usually the application should only need to use these shortcuts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ internal abstract class AuthModule {
@Binds
abstract fun bindSessionCreator(creator: DefaultSessionCreator): SessionCreator

@Binds
abstract fun bindSessionParamsCreator(creator: DefaultSessionParamsCreator): SessionParamsCreator

@Binds
abstract fun bindDirectLoginTask(task: DefaultDirectLoginTask): DirectLoginTask

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import org.matrix.android.sdk.internal.auth.data.WebClientConfig
import org.matrix.android.sdk.internal.auth.db.PendingSessionData
import org.matrix.android.sdk.internal.auth.login.DefaultLoginWizard
import org.matrix.android.sdk.internal.auth.login.DirectLoginTask
import org.matrix.android.sdk.internal.auth.login.LoginType
import org.matrix.android.sdk.internal.auth.registration.DefaultRegistrationWizard
import org.matrix.android.sdk.internal.auth.version.Versions
import org.matrix.android.sdk.internal.auth.version.isLoginAndRegistrationSupportedBySdk
Expand Down Expand Up @@ -370,7 +371,7 @@ internal class DefaultAuthenticationService @Inject constructor(

override suspend fun createSessionFromSso(homeServerConnectionConfig: HomeServerConnectionConfig,
credentials: Credentials): Session {
return sessionCreator.createSession(credentials, homeServerConnectionConfig)
return sessionCreator.createSession(credentials, homeServerConnectionConfig, LoginType.SSO)
}

override suspend fun getWellKnownData(matrixId: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,69 +16,41 @@

package org.matrix.android.sdk.internal.auth

import android.net.Uri
import org.matrix.android.sdk.api.auth.data.Credentials
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
import org.matrix.android.sdk.api.auth.data.SessionParams
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.internal.SessionManager
import timber.log.Timber
import org.matrix.android.sdk.internal.auth.login.LoginType
import javax.inject.Inject

internal interface SessionCreator {
suspend fun createSession(credentials: Credentials, homeServerConnectionConfig: HomeServerConnectionConfig): Session

suspend fun createSession(
credentials: Credentials,
homeServerConnectionConfig: HomeServerConnectionConfig,
loginType: LoginType,
): Session
}

internal class DefaultSessionCreator @Inject constructor(
private val sessionParamsStore: SessionParamsStore,
private val sessionManager: SessionManager,
private val pendingSessionStore: PendingSessionStore,
private val isValidClientServerApiTask: IsValidClientServerApiTask
private val sessionParamsCreator: SessionParamsCreator,
) : SessionCreator {

/**
* Credentials can affect the homeServerConnectionConfig, override homeserver url and/or
* identity server url if provided in the credentials
*/
override suspend fun createSession(credentials: Credentials, homeServerConnectionConfig: HomeServerConnectionConfig): Session {
override suspend fun createSession(
credentials: Credentials,
homeServerConnectionConfig: HomeServerConnectionConfig,
loginType: LoginType,
): Session {
// We can cleanup the pending session params
pendingSessionStore.delete()

val overriddenUrl = credentials.discoveryInformation?.homeServer?.baseURL
// remove trailing "/"
?.trim { it == '/' }
?.takeIf { it.isNotBlank() }
// It can be the same value, so in this case, do not check again the validity
?.takeIf { it != homeServerConnectionConfig.homeServerUriBase.toString() }
?.also { Timber.d("Overriding homeserver url to $it (will check if valid)") }
?.let { Uri.parse(it) }
?.takeIf {
// Validate the URL, if the configuration is wrong server side, do not override
tryOrNull {
isValidClientServerApiTask.execute(
IsValidClientServerApiTask.Params(
homeServerConnectionConfig.copy(homeServerUriBase = it)
)
)
.also { Timber.d("Overriding homeserver url: $it") }
} ?: true // In case of other error (no network, etc.), consider it is valid...
}

val sessionParams = SessionParams(
credentials = credentials,
homeServerConnectionConfig = homeServerConnectionConfig.copy(
homeServerUriBase = overriddenUrl ?: homeServerConnectionConfig.homeServerUriBase,
identityServerUri = credentials.discoveryInformation?.identityServer?.baseURL
// remove trailing "/"
?.trim { it == '/' }
?.takeIf { it.isNotBlank() }
?.also { Timber.d("Overriding identity server url to $it") }
?.let { Uri.parse(it) }
?: homeServerConnectionConfig.identityServerUri
),
isTokenValid = true)

val sessionParams = sessionParamsCreator.create(credentials, homeServerConnectionConfig, loginType)
sessionParamsStore.save(sessionParams)
return sessionManager.getOrCreateSession(sessionParams)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* 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.internal.auth

import android.net.Uri
import org.matrix.android.sdk.api.auth.data.Credentials
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
import org.matrix.android.sdk.api.auth.data.SessionParams
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.internal.auth.login.LoginType
import timber.log.Timber
import javax.inject.Inject

internal interface SessionParamsCreator {

suspend fun create(
credentials: Credentials,
homeServerConnectionConfig: HomeServerConnectionConfig,
loginType: LoginType,
): SessionParams
}

internal class DefaultSessionParamsCreator @Inject constructor(
private val isValidClientServerApiTask: IsValidClientServerApiTask
) : SessionParamsCreator {

override suspend fun create(
credentials: Credentials,
homeServerConnectionConfig: HomeServerConnectionConfig,
loginType: LoginType,
) = SessionParams(
credentials = credentials,
homeServerConnectionConfig = homeServerConnectionConfig.overrideWithCredentials(credentials),
isTokenValid = true,
loginType = loginType,
)

private suspend fun HomeServerConnectionConfig.overrideWithCredentials(credentials: Credentials) = copy(
homeServerUriBase = credentials.getHomeServerUri(this) ?: homeServerUriBase,
identityServerUri = credentials.getIdentityServerUri() ?: identityServerUri
)

private suspend fun Credentials.getHomeServerUri(homeServerConnectionConfig: HomeServerConnectionConfig) =
discoveryInformation?.homeServer?.baseURL
?.trim { it == '/' }
?.takeIf { it.isNotBlank() }
// It can be the same value, so in this case, do not check again the validity
?.takeIf { it != homeServerConnectionConfig.homeServerUriBase.toString() }
?.also { Timber.d("Overriding homeserver url to $it (will check if valid)") }
?.let { Uri.parse(it) }
?.takeIf { validateUri(it, homeServerConnectionConfig) }

private suspend fun validateUri(uri: Uri, homeServerConnectionConfig: HomeServerConnectionConfig) =
// Validate the URL, if the configuration is wrong server side, do not override
tryOrNull {
performClientServerApiValidation(uri, homeServerConnectionConfig)
} ?: true // In case of other error (no network, etc.), consider it is valid...

private suspend fun performClientServerApiValidation(uri: Uri, homeServerConnectionConfig: HomeServerConnectionConfig) =
isValidClientServerApiTask.execute(
IsValidClientServerApiTask.Params(homeServerConnectionConfig.copy(homeServerUriBase = uri))
).also { Timber.d("Overriding homeserver url: $it") }

private fun Credentials.getIdentityServerUri() = discoveryInformation?.identityServer?.baseURL
?.trim { it == '/' }
?.takeIf { it.isNotBlank() }
?.also { Timber.d("Overriding identity server url to $it") }
?.let { Uri.parse(it) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import org.matrix.android.sdk.internal.auth.db.migration.MigrateAuthTo001
import org.matrix.android.sdk.internal.auth.db.migration.MigrateAuthTo002
import org.matrix.android.sdk.internal.auth.db.migration.MigrateAuthTo003
import org.matrix.android.sdk.internal.auth.db.migration.MigrateAuthTo004
import org.matrix.android.sdk.internal.auth.db.migration.MigrateAuthTo005
import timber.log.Timber
import javax.inject.Inject

Expand All @@ -33,7 +34,7 @@ internal class AuthRealmMigration @Inject constructor() : RealmMigration {
override fun equals(other: Any?) = other is AuthRealmMigration
override fun hashCode() = 4000

val schemaVersion = 4L
val schemaVersion = 5L

override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
Timber.d("Migrating Auth Realm from $oldVersion to $newVersion")
Expand All @@ -42,5 +43,6 @@ internal class AuthRealmMigration @Inject constructor() : RealmMigration {
if (oldVersion < 2) MigrateAuthTo002(realm).perform()
if (oldVersion < 3) MigrateAuthTo003(realm).perform()
if (oldVersion < 4) MigrateAuthTo004(realm).perform()
if (oldVersion < 5) MigrateAuthTo005(realm).perform()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ internal open class SessionParamsEntity(
var homeServerConnectionConfigJson: String = "",
// Set to false when the token is invalid and the user has been soft logged out
// In case of hard logout, this object is deleted from DB
var isTokenValid: Boolean = true
var isTokenValid: Boolean = true,
var loginType: String = "",
) : RealmObject()
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import org.matrix.android.sdk.api.auth.data.Credentials
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
import org.matrix.android.sdk.api.auth.data.SessionParams
import org.matrix.android.sdk.api.auth.data.sessionId
import org.matrix.android.sdk.internal.auth.login.LoginType
import javax.inject.Inject

internal class SessionParamsMapper @Inject constructor(moshi: Moshi) {
Expand All @@ -37,7 +38,7 @@ internal class SessionParamsMapper @Inject constructor(moshi: Moshi) {
if (credentials == null || homeServerConnectionConfig == null) {
return null
}
return SessionParams(credentials, homeServerConnectionConfig, entity.isTokenValid)
return SessionParams(credentials, homeServerConnectionConfig, entity.isTokenValid, LoginType.fromName(entity.loginType))
}

fun map(sessionParams: SessionParams?): SessionParamsEntity? {
Expand All @@ -54,6 +55,8 @@ internal class SessionParamsMapper @Inject constructor(moshi: Moshi) {
sessionParams.userId,
credentialsJson,
homeServerConnectionConfigJson,
sessionParams.isTokenValid)
sessionParams.isTokenValid,
sessionParams.loginType.name,
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* 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.internal.auth.db.migration

import io.realm.DynamicRealm
import org.matrix.android.sdk.internal.auth.db.SessionParamsEntityFields
import org.matrix.android.sdk.internal.auth.login.LoginType
import org.matrix.android.sdk.internal.util.database.RealmMigrator
import timber.log.Timber

internal class MigrateAuthTo005(realm: DynamicRealm) : RealmMigrator(realm, 5) {

override fun doMigrate(realm: DynamicRealm) {
Timber.d("Update SessionParamsEntity to add LoginType")

realm.schema.get("SessionParamsEntity")
?.addField(SessionParamsEntityFields.LOGIN_TYPE, String::class.java)
?.setRequired(SessionParamsEntityFields.LOGIN_TYPE, true)
?.transform { it.set(SessionParamsEntityFields.LOGIN_TYPE, LoginType.UNKNOWN.name) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ internal class DefaultLoginWizard(
authAPI.login(loginParams)
}

return sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig)
return sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig, LoginType.PASSWORD)
}

/**
Expand All @@ -90,15 +90,15 @@ internal class DefaultLoginWizard(
authAPI.login(loginParams)
}

return sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig)
return sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig, LoginType.SSO)
}

override suspend fun loginCustom(data: JsonDict): Session {
val credentials = executeRequest(null) {
authAPI.login(data)
}

return sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig)
return sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig, LoginType.CUSTOM)
}

override suspend fun resetPassword(email: String, newPassword: String) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ internal class DefaultDirectLoginTask @Inject constructor(
}
}

return sessionCreator.createSession(credentials, params.homeServerConnectionConfig)
return sessionCreator.createSession(credentials, params.homeServerConnectionConfig, LoginType.DIRECT)
}

private fun buildClient(homeServerConnectionConfig: HomeServerConnectionConfig): OkHttpClient {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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.internal.auth.login

enum class LoginType {
PASSWORD,
SSO,
UNSUPPORTED,
CUSTOM,
DIRECT,
UNKNOWN;

companion object {

fun fromName(name: String) = when (name) {
PASSWORD.name -> PASSWORD
SSO.name -> SSO
UNSUPPORTED.name -> UNSUPPORTED
CUSTOM.name -> CUSTOM
DIRECT.name -> DIRECT
else -> UNKNOWN
}
}
}
Loading