mirror of
https://github.com/element-hq/element-android
synced 2024-11-23 18:05:36 +03:00
parent
391d3cb6b5
commit
f00db49bda
11 changed files with 230 additions and 5 deletions
|
@ -2,6 +2,7 @@ Changes in RiotX 0.19.0 (2020-XX-XX)
|
|||
===================================================
|
||||
|
||||
Features ✨:
|
||||
- Change password (#528)
|
||||
- Cross-Signing | Support SSSS secret sharing (#944)
|
||||
- Cross-Signing | Verify new session from existing session (#1134)
|
||||
- Cross-Signing | Bootstraping cross signing with 4S from mobile (#985)
|
||||
|
|
|
@ -22,6 +22,7 @@ import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
|||
import im.vector.matrix.android.api.auth.data.LoginFlowResult
|
||||
import im.vector.matrix.android.api.auth.data.SessionParams
|
||||
import im.vector.matrix.android.api.auth.login.LoginWizard
|
||||
import im.vector.matrix.android.api.auth.password.PasswordWizard
|
||||
import im.vector.matrix.android.api.auth.registration.RegistrationWizard
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
|
@ -89,4 +90,9 @@ interface AuthenticationService {
|
|||
fun createSessionFromSso(homeServerConnectionConfig: HomeServerConnectionConfig,
|
||||
credentials: Credentials,
|
||||
callback: MatrixCallback<Session>): Cancelable
|
||||
|
||||
/**
|
||||
* Return a PasswordWizard, to update password.
|
||||
*/
|
||||
fun getPasswordWizard(): PasswordWizard
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* 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 im.vector.matrix.android.api.auth.password
|
||||
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
|
||||
interface PasswordWizard {
|
||||
|
||||
/**
|
||||
* Ask the homeserver to update the password with the provided new password.
|
||||
*/
|
||||
fun updatePassword(sessionId: String, userId: String, oldPassword: String, newPassword: String, callback: MatrixCallback<Unit>): Cancelable
|
||||
}
|
|
@ -31,3 +31,8 @@ fun Throwable.shouldBeRetried(): Boolean {
|
|||
return this is Failure.NetworkConnection
|
||||
|| (this is Failure.ServerError && error.code == MatrixError.M_LIMIT_EXCEEDED)
|
||||
}
|
||||
|
||||
fun Throwable.isInvalidPassword(): Boolean {
|
||||
return this is Failure.ServerError
|
||||
&& error.message == "Invalid password"
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import im.vector.matrix.android.internal.auth.data.LoginFlowResponse
|
|||
import im.vector.matrix.android.internal.auth.data.PasswordLoginParams
|
||||
import im.vector.matrix.android.internal.auth.data.RiotConfig
|
||||
import im.vector.matrix.android.internal.auth.login.ResetPasswordMailConfirmed
|
||||
import im.vector.matrix.android.internal.auth.data.UpdatePasswordParams
|
||||
import im.vector.matrix.android.internal.auth.registration.AddThreePidRegistrationParams
|
||||
import im.vector.matrix.android.internal.auth.registration.AddThreePidRegistrationResponse
|
||||
import im.vector.matrix.android.internal.auth.registration.RegistrationParams
|
||||
|
@ -102,4 +103,10 @@ internal interface AuthAPI {
|
|||
*/
|
||||
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "account/password")
|
||||
fun resetPasswordMailConfirmed(@Body params: ResetPasswordMailConfirmed): Call<Unit>
|
||||
|
||||
/**
|
||||
* Ask the homeserver to update the password with the provided new password.
|
||||
*/
|
||||
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "account/password")
|
||||
fun updatePassword(@Body params: UpdatePasswordParams): Call<Unit>
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import im.vector.matrix.android.api.auth.data.Versions
|
|||
import im.vector.matrix.android.api.auth.data.isLoginAndRegistrationSupportedBySdk
|
||||
import im.vector.matrix.android.api.auth.data.isSupportedBySdk
|
||||
import im.vector.matrix.android.api.auth.login.LoginWizard
|
||||
import im.vector.matrix.android.api.auth.password.PasswordWizard
|
||||
import im.vector.matrix.android.api.auth.registration.RegistrationWizard
|
||||
import im.vector.matrix.android.api.failure.Failure
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
|
@ -37,6 +38,7 @@ import im.vector.matrix.android.internal.auth.data.LoginFlowResponse
|
|||
import im.vector.matrix.android.internal.auth.data.RiotConfig
|
||||
import im.vector.matrix.android.internal.auth.db.PendingSessionData
|
||||
import im.vector.matrix.android.internal.auth.login.DefaultLoginWizard
|
||||
import im.vector.matrix.android.internal.auth.password.DefaultPasswordWizard
|
||||
import im.vector.matrix.android.internal.auth.registration.DefaultRegistrationWizard
|
||||
import im.vector.matrix.android.internal.di.Unauthenticated
|
||||
import im.vector.matrix.android.internal.network.RetrofitFactory
|
||||
|
@ -66,6 +68,7 @@ internal class DefaultAuthenticationService @Inject constructor(
|
|||
|
||||
private var currentLoginWizard: LoginWizard? = null
|
||||
private var currentRegistrationWizard: RegistrationWizard? = null
|
||||
private var currentPasswordWizard: PasswordWizard? = null
|
||||
|
||||
override fun hasAuthenticatedSessions(): Boolean {
|
||||
return sessionParamsStore.getLast() != null
|
||||
|
@ -221,6 +224,22 @@ internal class DefaultAuthenticationService @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override fun getPasswordWizard(): PasswordWizard {
|
||||
return currentPasswordWizard
|
||||
?: let {
|
||||
sessionParamsStore.getLast()?.homeServerConnectionConfig?.let {
|
||||
DefaultPasswordWizard(
|
||||
okHttpClient,
|
||||
retrofitFactory,
|
||||
coroutineDispatchers,
|
||||
it
|
||||
).also {
|
||||
currentPasswordWizard = it
|
||||
}
|
||||
} ?: error("HomeServerConnectionConfig is null")
|
||||
}
|
||||
}
|
||||
|
||||
override fun cancelPendingLoginOrRegistration() {
|
||||
currentLoginWizard = null
|
||||
currentRegistrationWizard = null
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* 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 im.vector.matrix.android.internal.auth.data
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.UserPasswordAuth
|
||||
|
||||
/**
|
||||
* Class to pass request parameters to update the password.
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class UpdatePasswordParams(
|
||||
@Json(name = "auth")
|
||||
val auth: UserPasswordAuth? = null,
|
||||
|
||||
@Json(name = "new_password")
|
||||
val newPassword: String? = null
|
||||
) {
|
||||
companion object {
|
||||
fun create(sessionId: String, userId: String, oldPassword: String, newPassword: String): UpdatePasswordParams {
|
||||
return UpdatePasswordParams(
|
||||
auth = UserPasswordAuth(session = sessionId, user = userId, password = oldPassword),
|
||||
newPassword = newPassword
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* 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 im.vector.matrix.android.internal.auth.password
|
||||
|
||||
import dagger.Lazy
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
||||
import im.vector.matrix.android.api.auth.password.PasswordWizard
|
||||
import im.vector.matrix.android.api.failure.Failure
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
import im.vector.matrix.android.internal.auth.AuthAPI
|
||||
import im.vector.matrix.android.internal.auth.data.UpdatePasswordParams
|
||||
import im.vector.matrix.android.internal.auth.registration.RegistrationFlowResponse
|
||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||
import im.vector.matrix.android.internal.network.RetrofitFactory
|
||||
import im.vector.matrix.android.internal.network.executeRequest
|
||||
import im.vector.matrix.android.internal.task.launchToCallback
|
||||
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import okhttp3.OkHttpClient
|
||||
import timber.log.Timber
|
||||
|
||||
internal class DefaultPasswordWizard(
|
||||
okHttpClient: Lazy<OkHttpClient>,
|
||||
retrofitFactory: RetrofitFactory,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
private val homeServerConnectionConfig: HomeServerConnectionConfig
|
||||
) : PasswordWizard {
|
||||
|
||||
private val authAPI = retrofitFactory.create(okHttpClient, homeServerConnectionConfig.homeServerUri.toString())
|
||||
.create(AuthAPI::class.java)
|
||||
|
||||
override fun updatePassword(sessionId: String, userId: String, oldPassword: String, newPassword: String, callback: MatrixCallback<Unit>): Cancelable {
|
||||
return GlobalScope.launchToCallback(coroutineDispatchers.main, callback) {
|
||||
updatePasswordInternal(sessionId, userId, oldPassword, newPassword)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun updatePasswordInternal(sessionId: String, userId: String, oldPassword: String, newPassword: String) {
|
||||
val params = UpdatePasswordParams.create(sessionId, userId, oldPassword, newPassword)
|
||||
try {
|
||||
executeRequest<Unit>(null) {
|
||||
apiCall = authAPI.updatePassword(params)
|
||||
}
|
||||
} catch (throwable: Throwable) {
|
||||
if (throwable is Failure.OtherServerError
|
||||
&& throwable.httpCode == 401
|
||||
/* Avoid infinite loop */
|
||||
&& params.auth?.session == null) {
|
||||
try {
|
||||
MoshiProvider.providesMoshi()
|
||||
.adapter(RegistrationFlowResponse::class.java)
|
||||
.fromJson(throwable.errorBody)
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}?.let {
|
||||
// Retry with authentication
|
||||
try {
|
||||
executeRequest<Unit>(null) {
|
||||
apiCall = authAPI.updatePassword(
|
||||
params.copy(auth = params.auth?.copy(session = it.session))
|
||||
)
|
||||
}
|
||||
return
|
||||
} catch (failure: Throwable) {
|
||||
throw failure
|
||||
}
|
||||
}
|
||||
}
|
||||
throw throwable
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@ import com.squareup.moshi.JsonClass
|
|||
import im.vector.matrix.android.internal.auth.data.LoginFlowTypes
|
||||
|
||||
/**
|
||||
* This class provides the authentication data to delete a device
|
||||
* This class provides the authentication data by using user and password
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class UserPasswordAuth(
|
||||
|
|
|
@ -74,6 +74,7 @@ import im.vector.riotx.features.roomprofile.RoomProfileFragment
|
|||
import im.vector.riotx.features.roomprofile.members.RoomMemberListFragment
|
||||
import im.vector.riotx.features.roomprofile.settings.RoomSettingsFragment
|
||||
import im.vector.riotx.features.settings.VectorSettingsAdvancedNotificationPreferenceFragment
|
||||
import im.vector.riotx.features.settings.VectorSettingsGeneralFragment
|
||||
import im.vector.riotx.features.settings.VectorSettingsHelpAboutFragment
|
||||
import im.vector.riotx.features.settings.VectorSettingsLabsFragment
|
||||
import im.vector.riotx.features.settings.VectorSettingsNotificationPreferenceFragment
|
||||
|
@ -280,6 +281,11 @@ interface FragmentModule {
|
|||
@FragmentKey(VectorSettingsDevicesFragment::class)
|
||||
fun bindVectorSettingsDevicesFragment(fragment: VectorSettingsDevicesFragment): Fragment
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FragmentKey(VectorSettingsGeneralFragment::class)
|
||||
fun bindVectorSettingsGeneralFragment(fragment: VectorSettingsGeneralFragment): Fragment
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FragmentKey(PublicRoomsFragment::class)
|
||||
|
|
|
@ -35,6 +35,9 @@ import com.bumptech.glide.Glide
|
|||
import com.bumptech.glide.load.engine.cache.DiskCache
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.auth.AuthenticationService
|
||||
import im.vector.matrix.android.api.failure.isInvalidPassword
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.extensions.hideKeyboard
|
||||
import im.vector.riotx.core.extensions.showPassword
|
||||
|
@ -56,8 +59,11 @@ import kotlinx.coroutines.GlobalScope
|
|||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
|
||||
class VectorSettingsGeneralFragment : VectorSettingsBaseFragment() {
|
||||
class VectorSettingsGeneralFragment @Inject constructor(
|
||||
private val authenticationService: AuthenticationService
|
||||
) : VectorSettingsBaseFragment() {
|
||||
|
||||
override var titleRes = R.string.settings_general_title
|
||||
override val preferenceXmlRes = R.xml.vector_settings_general
|
||||
|
@ -109,8 +115,7 @@ class VectorSettingsGeneralFragment : VectorSettingsBaseFragment() {
|
|||
|
||||
// Password
|
||||
mPasswordPreference.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
notImplemented()
|
||||
// onPasswordUpdateClick()
|
||||
onPasswordUpdateClick()
|
||||
false
|
||||
}
|
||||
|
||||
|
@ -771,7 +776,26 @@ class VectorSettingsGeneralFragment : VectorSettingsBaseFragment() {
|
|||
val oldPwd = oldPasswordText.text.toString().trim()
|
||||
val newPwd = newPasswordText.text.toString().trim()
|
||||
|
||||
notImplemented()
|
||||
authenticationService.getLastAuthenticatedSession()?.let {
|
||||
showPasswordLoadingView(true)
|
||||
authenticationService.getPasswordWizard().updatePassword(it.sessionId, it.myUserId, oldPwd, newPwd, object : MatrixCallback<Unit> {
|
||||
override fun onSuccess(data: Unit) {
|
||||
showPasswordLoadingView(false)
|
||||
dialog.dismiss()
|
||||
activity.toast(R.string.settings_password_updated)
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
showPasswordLoadingView(false)
|
||||
if (failure.isInvalidPassword()) {
|
||||
activity.toast(R.string.settings_fail_to_update_password_invalid_current_password)
|
||||
} else {
|
||||
activity.toast(R.string.settings_fail_to_update_password)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/* TODO
|
||||
showPasswordLoadingView(true)
|
||||
|
||||
|
|
Loading…
Reference in a new issue