diff --git a/CHANGES.md b/CHANGES.md index 1a684ee56f..3362588cf8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,6 +19,7 @@ Improvements 🙌: - Fix quick click action (#3127) - Get Event after a Push for a faster notification display in some conditions - Always try to retry Http requests in case of 429 (#1300) + - registration availability endpoint added to matrix-sdk Bugfix 🐛: - Fix bad theme change for the MainActivity diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationAvailability.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationAvailability.kt new file mode 100644 index 0000000000..f9a7ace7ba --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationAvailability.kt @@ -0,0 +1,24 @@ +/* + * 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. + */ + +package org.matrix.android.sdk.api.auth.registration + +import org.matrix.android.sdk.api.failure.Failure + +sealed class RegistrationAvailability { + object Available : RegistrationAvailability() + data class NotAvailable(val failure: Failure.ServerError) : RegistrationAvailability() +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationWizard.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationWizard.kt index d00c9a0c82..38a5a77291 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationWizard.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationWizard.kt @@ -36,6 +36,8 @@ interface RegistrationWizard { suspend fun checkIfEmailHasBeenValidated(delayMillis: Long): RegistrationResult + suspend fun registrationAvailable(userName: String): RegistrationAvailability + val currentThreePid: String? // True when login and password has been sent with success to the homeserver diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt index 17362ff8d7..0ba61e5890 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt @@ -65,13 +65,16 @@ fun Throwable.isInvalidUIAAuth(): Boolean { * Try to convert to a RegistrationFlowResponse. Return null in the cases it's not possible */ fun Throwable.toRegistrationFlowResponse(): RegistrationFlowResponse? { - return if (this is Failure.OtherServerError && httpCode == 401) { + return if (this is Failure.OtherServerError + && httpCode == HttpsURLConnection.HTTP_UNAUTHORIZED /* 401 */) { tryOrNull { MoshiProvider.providesMoshi() .adapter(RegistrationFlowResponse::class.java) .fromJson(errorBody) } - } else if (this is Failure.ServerError && httpCode == 401 && error.code == MatrixError.M_FORBIDDEN) { + } else if (this is Failure.ServerError + && httpCode == HttpsURLConnection.HTTP_UNAUTHORIZED /* 401 */ + && error.code == MatrixError.M_FORBIDDEN) { // This happens when the submission for this stage was bad (like bad password) if (error.session != null && error.flows != null) { RegistrationFlowResponse( @@ -87,3 +90,11 @@ fun Throwable.toRegistrationFlowResponse(): RegistrationFlowResponse? { null } } + +fun Throwable.isRegistrationAvailabilityError(): Boolean { + return this is Failure.ServerError + && httpCode == HttpsURLConnection.HTTP_BAD_REQUEST /* 400 */ + && (error.code == MatrixError.M_USER_IN_USE + || error.code == MatrixError.M_INVALID_USERNAME + || error.code == MatrixError.M_EXCLUSIVE) +} 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 2ce5c67a94..f93f285c6e 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 @@ -17,6 +17,7 @@ package org.matrix.android.sdk.internal.auth import org.matrix.android.sdk.api.auth.data.Credentials +import org.matrix.android.sdk.internal.auth.data.Availability import org.matrix.android.sdk.internal.auth.data.LoginFlowResponse import org.matrix.android.sdk.internal.auth.data.PasswordLoginParams import org.matrix.android.sdk.internal.auth.data.RiotConfig @@ -34,6 +35,7 @@ import retrofit2.http.GET import retrofit2.http.Headers import retrofit2.http.POST import retrofit2.http.Path +import retrofit2.http.Query import retrofit2.http.Url /** @@ -65,6 +67,12 @@ internal interface AuthAPI { @POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "register") suspend fun register(@Body registrationParams: RegistrationParams): Credentials + /** + * Checks to see if a username is available, and valid, for the server. + */ + @GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "register/available") + suspend fun registerAvailable(@Query("username") username: String): Availability + /** * Add 3Pid during registration * Ref: https://gist.github.com/jryans/839a09bf0c5a70e2f36ed990d50ed928 diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/Availability.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/Availability.kt new file mode 100644 index 0000000000..5ef3c0d06a --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/Availability.kt @@ -0,0 +1,29 @@ +/* + * 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. + */ + +package org.matrix.android.sdk.internal.auth.data + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +internal data class Availability( + /** + * A flag to indicate that the username is available. This should always be true when the server replies with 200 OK. + */ + @Json(name = "available") + val available: Boolean? = null +) 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 91e414e689..4a3d53a8fc 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 @@ -19,6 +19,7 @@ package org.matrix.android.sdk.internal.auth.registration import kotlinx.coroutines.delay import org.matrix.android.sdk.api.auth.data.LoginFlowTypes import org.matrix.android.sdk.api.auth.registration.RegisterThreePid +import org.matrix.android.sdk.api.auth.registration.RegistrationAvailability import org.matrix.android.sdk.api.auth.registration.RegistrationResult import org.matrix.android.sdk.api.auth.registration.RegistrationWizard import org.matrix.android.sdk.api.auth.registration.toFlowResult @@ -40,9 +41,10 @@ internal class DefaultRegistrationWizard( private var pendingSessionData: PendingSessionData = pendingSessionStore.getPendingSessionData() ?: error("Pending session data should exist here") - private val registerTask = DefaultRegisterTask(authAPI) - private val registerAddThreePidTask = DefaultRegisterAddThreePidTask(authAPI) - private val validateCodeTask = DefaultValidateCodeTask(authAPI) + private val registerTask: RegisterTask = DefaultRegisterTask(authAPI) + private val registerAvailableTask: RegisterAvailableTask = DefaultRegisterAvailableTask(authAPI) + private val registerAddThreePidTask: RegisterAddThreePidTask = DefaultRegisterAddThreePidTask(authAPI) + private val validateCodeTask: ValidateCodeTask = DefaultValidateCodeTask(authAPI) override val currentThreePid: String? get() { @@ -203,4 +205,8 @@ internal class DefaultRegistrationWizard( val session = sessionCreator.createSession(credentials, pendingSessionData.homeServerConnectionConfig) return RegistrationResult.Success(session) } + + override suspend fun registrationAvailable(userName: String): RegistrationAvailability { + return registerAvailableTask.execute(RegisterAvailableTask.Params(userName)) + } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/RegisterAvailableTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/RegisterAvailableTask.kt new file mode 100644 index 0000000000..314a24dad4 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/RegisterAvailableTask.kt @@ -0,0 +1,47 @@ +/* + * 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. + */ + +package org.matrix.android.sdk.internal.auth.registration + +import org.matrix.android.sdk.api.auth.registration.RegistrationAvailability +import org.matrix.android.sdk.api.failure.Failure +import org.matrix.android.sdk.api.failure.isRegistrationAvailabilityError +import org.matrix.android.sdk.internal.auth.AuthAPI +import org.matrix.android.sdk.internal.network.executeRequest +import org.matrix.android.sdk.internal.task.Task + +internal interface RegisterAvailableTask : Task { + data class Params( + val userName: String + ) +} + +internal class DefaultRegisterAvailableTask(private val authAPI: AuthAPI) : RegisterAvailableTask { + override suspend fun execute(params: RegisterAvailableTask.Params): RegistrationAvailability { + return try { + executeRequest(null) { + authAPI.registerAvailable(params.userName) + } + RegistrationAvailability.Available + } catch (exception: Throwable) { + if (exception.isRegistrationAvailabilityError()) { + RegistrationAvailability.NotAvailable(exception as Failure.ServerError) + } else { + throw exception + } + } + } +}