diff --git a/.idea/misc.xml b/.idea/misc.xml index 360e6d41e364d4aebf23e7f2d3e9cef58a2eb12c..5c9f89fee71360989ca8a39d7324e4a12762142d 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> <component name="ExternalStorageConfigurationManager" enabled="true" /> - <component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="1.8" project-jdk-type="JavaSDK"> + <component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="11" project-jdk-type="JavaSDK"> <output url="file://$PROJECT_DIR$/build/classes" /> </component> <component name="ProjectType"> diff --git a/matrix-sdk-android/gradle-publish.gradle b/matrix-sdk-android/gradle-publish.gradle index 5a32cf4d56590a9e086723f2c8bfa82ac0605492..168c4986d2b13e210b20b1d02e9658fb120182c9 100644 --- a/matrix-sdk-android/gradle-publish.gradle +++ b/matrix-sdk-android/gradle-publish.gradle @@ -3,7 +3,7 @@ apply plugin: 'maven-publish' def groupIdString = "org.matrix.android" def artifactIdString = "matrix-sdk-android" -def versionName = "1.5.1.1" +def versionName = "1.5.1.2" def artifactPath = "$buildDir/outputs/aar/$artifactIdString-release.aar" def publicationName = "release" def projectId = "16" diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/login/LoginWizard.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/login/LoginWizard.kt index 145cdbdc228ad1f405a66f1b60c7f154614ff2eb..07d748b90919680319133b0d261e92801409b766 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/login/LoginWizard.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/login/LoginWizard.kt @@ -16,6 +16,8 @@ package org.matrix.android.sdk.api.auth.login +import org.matrix.android.sdk.api.auth.registration.RegistrationResult +import org.matrix.android.sdk.api.auth.registration.Stage import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.util.JsonDict @@ -77,4 +79,14 @@ interface LoginWizard { * if [org.matrix.android.sdk.api.auth.data.LoginFlowResult.isLogoutDevicesSupported] is true. */ suspend fun resetPasswordMailConfirmed(newPassword: String, logoutAllDevices: Boolean = true) + + //Added to support few login flows + suspend fun getAllLoginFlows(): List<List<Stage>> + + /** + * Perform custom login stage by sending a custom JsonDict. + * Current login "session" param will be included into authParams by default. + * The authParams should contain at least one entry "type" with a String value. + */ + suspend fun loginStageCustom(authParams: JsonDict): RegistrationResult } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthAPI.kt index 6f1778ce384623b0f56efa07eb26afe35aa11097..73da2fddbb02f0e6199ab91b9f507ce2e1daf4e6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthAPI.kt @@ -19,6 +19,7 @@ package org.matrix.android.sdk.internal.auth import org.matrix.android.sdk.api.auth.data.Credentials import org.matrix.android.sdk.api.util.JsonDict import org.matrix.android.sdk.internal.auth.data.* +import org.matrix.android.sdk.internal.auth.login.LoginFlowParams import org.matrix.android.sdk.internal.auth.login.ResetPasswordMailConfirmed import org.matrix.android.sdk.internal.auth.registration.AddThreePidRegistrationParams import org.matrix.android.sdk.internal.auth.registration.AddThreePidRegistrationResponse @@ -140,4 +141,7 @@ internal interface AuthAPI { */ @POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "account/password") suspend fun resetPasswordMailConfirmed(@Body params: ResetPasswordMailConfirmed) + + @POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "login") + suspend fun login(@Body loginFlowParams: LoginFlowParams): Credentials } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/StageExtension.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/StageExtension.kt new file mode 100644 index 0000000000000000000000000000000000000000..4f34a37fb6b37a86d7495225d3d84670e9039a6b --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/StageExtension.kt @@ -0,0 +1,14 @@ +package org.matrix.android.sdk.internal.auth + +import org.matrix.android.sdk.api.auth.data.LoginFlowTypes +import org.matrix.android.sdk.api.auth.registration.Stage + +//Added to support few registration flows +fun List<Stage>.findStageForType(type: String): Stage? = when (type) { + LoginFlowTypes.RECAPTCHA -> firstOrNull { it is Stage.ReCaptcha } + LoginFlowTypes.DUMMY -> firstOrNull { it is Stage.Dummy } + LoginFlowTypes.TERMS -> firstOrNull { it is Stage.Terms } + LoginFlowTypes.EMAIL_IDENTITY -> firstOrNull { it is Stage.Email } + LoginFlowTypes.MSISDN -> firstOrNull { it is Stage.Msisdn } + else -> firstOrNull { (it as? Stage.Other)?.type == type } +} \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/DefaultLoginWizard.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/DefaultLoginWizard.kt index 468e998407cac4e38d06ebf256221053cf0e80fd..e1b212f207d04e5cf4a28f8f4ba88193656cbe43 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/DefaultLoginWizard.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/DefaultLoginWizard.kt @@ -17,10 +17,16 @@ package org.matrix.android.sdk.internal.auth.login import android.util.Patterns +import kotlinx.coroutines.delay import org.matrix.android.sdk.api.auth.LoginType +import org.matrix.android.sdk.api.auth.data.Credentials import org.matrix.android.sdk.api.auth.login.LoginProfileInfo import org.matrix.android.sdk.api.auth.login.LoginWizard import org.matrix.android.sdk.api.auth.registration.RegisterThreePid +import org.matrix.android.sdk.api.auth.registration.RegistrationResult +import org.matrix.android.sdk.api.auth.registration.Stage +import org.matrix.android.sdk.api.auth.registration.toFlowResult +import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.util.JsonDict import org.matrix.android.sdk.internal.auth.AuthAPI @@ -30,8 +36,13 @@ import org.matrix.android.sdk.internal.auth.data.PasswordLoginParams import org.matrix.android.sdk.internal.auth.data.ThreePidMedium import org.matrix.android.sdk.internal.auth.data.TokenLoginParams import org.matrix.android.sdk.internal.auth.db.PendingSessionData +import org.matrix.android.sdk.internal.auth.findStageForType import org.matrix.android.sdk.internal.auth.registration.AddThreePidRegistrationParams +import org.matrix.android.sdk.internal.auth.registration.DefaultRegisterTask import org.matrix.android.sdk.internal.auth.registration.RegisterAddThreePidTask +import org.matrix.android.sdk.internal.auth.registration.RegisterTask +import org.matrix.android.sdk.internal.auth.registration.RegistrationCustomParams +import org.matrix.android.sdk.internal.auth.registration.RegistrationParams import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.content.DefaultContentUrlResolver import org.matrix.android.sdk.internal.session.contentscanner.DisabledContentScannerService @@ -49,6 +60,8 @@ internal class DefaultLoginWizard( DefaultContentUrlResolver(pendingSessionData.homeServerConnectionConfig, DisabledContentScannerService()) ) + private val loginFlowTask: LoginFlowTask = DefaultLoginFlowTask(authAPI) + override suspend fun getProfileInfo(matrixId: String): LoginProfileInfo { return getProfileTask.execute(GetProfileTask.Params(matrixId)) } @@ -138,4 +151,71 @@ internal class DefaultLoginWizard( // Set to null? // resetPasswordData = null } + + //Added to support few login flows + override suspend fun getAllLoginFlows(): List<List<Stage>> { + try { + loginFlowTask.execute(LoginFlowTask.Params(LoginFlowParams())) + } catch (exception: Throwable) { + return if (exception is Failure.RegistrationFlowError) { + pendingSessionData = + pendingSessionData.copy(currentSession = exception.registrationFlowResponse.session) + .also { pendingSessionStore.savePendingSessionData(it) } + val flowResponse = exception.registrationFlowResponse + val missingStages = flowResponse.toFlowResult().missingStages + + val flowsWithStages = flowResponse.flows?.mapNotNull { it.stages }?.map { flow -> + flow.mapNotNull { type -> missingStages.findStageForType(type) } + } ?: emptyList() + + flowsWithStages + } else { + emptyList() + } + } + return emptyList() + } + + //Added to support few login flows + override suspend fun loginStageCustom( + authParams: JsonDict + ): RegistrationResult { + val safeSession = pendingSessionData.currentSession + ?: throw IllegalStateException("developer error, call createAccount() method first") + + val mutableParams = authParams.toMutableMap() + mutableParams["session"] = safeSession + + val params = LoginFlowParams(auth = mutableParams) + return performRegistrationRequest(LoginType.CUSTOM, params) + } + + private suspend fun performRegistrationRequest( + loginType: LoginType, + loginParams: LoginFlowParams + ): RegistrationResult { + return login(loginType) { loginFlowTask.execute(LoginFlowTask.Params(loginParams)) } + } + + //Added to support few login flows + private suspend fun login( + loginType: LoginType, + execute: suspend () -> Credentials, + ): RegistrationResult { + val credentials = try { + execute.invoke() + } catch (exception: Throwable) { + if (exception is Failure.RegistrationFlowError) { + pendingSessionData = + pendingSessionData.copy(currentSession = exception.registrationFlowResponse.session) + .also { pendingSessionStore.savePendingSessionData(it) } + return RegistrationResult.FlowResponse(exception.registrationFlowResponse.toFlowResult()) + } else { + throw exception + } + } + + val session = sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig, loginType) + return RegistrationResult.Success(session) + } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/LoginFlowParams.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/LoginFlowParams.kt new file mode 100644 index 0000000000000000000000000000000000000000..3515b56eeae6ee366042e3566772b6df2ffde63c --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/LoginFlowParams.kt @@ -0,0 +1,31 @@ +package org.matrix.android.sdk.internal.auth.login + +/* + * Copyright 2021 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. + */ + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.util.JsonDict + +/** + * Class to pass parameters to the custom login types for /login. + */ +@JsonClass(generateAdapter = true) +internal data class LoginFlowParams( + // authentication parameters + @Json(name = "auth") + val auth: JsonDict? = null +) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/LoginFlowTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/LoginFlowTask.kt new file mode 100644 index 0000000000000000000000000000000000000000..c8ae22c936ae32f3f3fb7f7d572b1b63bc543571 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/LoginFlowTask.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2020 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 + +import org.matrix.android.sdk.api.auth.data.Credentials +import org.matrix.android.sdk.api.failure.Failure +import org.matrix.android.sdk.api.failure.toRegistrationFlowResponse +import org.matrix.android.sdk.internal.auth.AuthAPI +import org.matrix.android.sdk.internal.auth.registration.RegisterTask +import org.matrix.android.sdk.internal.auth.registration.RegistrationParams +import org.matrix.android.sdk.internal.network.executeRequest +import org.matrix.android.sdk.internal.task.Task + +internal interface LoginFlowTask : Task<LoginFlowTask.Params, Credentials> { + data class Params( + val loginParams: LoginFlowParams + ) +} + +internal class DefaultLoginFlowTask( + private val authAPI: AuthAPI +) : LoginFlowTask { + + override suspend fun execute(params: LoginFlowTask.Params): Credentials { + try { + return executeRequest(null) { + authAPI.login(params.loginParams) + } + } catch (throwable: Throwable) { + throw throwable.toRegistrationFlowResponse() + ?.let { Failure.RegistrationFlowError(it) } + ?: throwable + } + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt index 63bf1b0a260819c0767ade9f5fb908e79ee5b841..8401db7fbb8d014ebf019952265ed227e38696ea 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/DefaultRegistrationWizard.kt @@ -33,6 +33,7 @@ import org.matrix.android.sdk.internal.auth.AuthAPI import org.matrix.android.sdk.internal.auth.PendingSessionStore import org.matrix.android.sdk.internal.auth.SessionCreator import org.matrix.android.sdk.internal.auth.db.PendingSessionData +import org.matrix.android.sdk.internal.auth.findStageForType /** * This class execute the registration request and is responsible to keep the session of interactive authentication. @@ -295,16 +296,6 @@ internal class DefaultRegistrationWizard( return emptyList() } - //Added to support few registration flows - private fun List<Stage>.findStageForType(type: String): Stage? = when (type) { - LoginFlowTypes.RECAPTCHA -> firstOrNull { it is Stage.ReCaptcha } - LoginFlowTypes.DUMMY -> firstOrNull { it is Stage.Dummy } - LoginFlowTypes.TERMS -> firstOrNull { it is Stage.Terms } - LoginFlowTypes.EMAIL_IDENTITY -> firstOrNull { it is Stage.Email } - LoginFlowTypes.MSISDN -> firstOrNull { it is Stage.Msisdn } - else -> firstOrNull { (it as? Stage.Other)?.type == type } - } - override suspend fun registrationSwiclops( authParams: JsonDict, userName: String?,