mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-02-17 04:20:00 +03:00
First commit to cleanup ReAuthHelper and it's usage
Also add some comment and do some other cleanup
This commit is contained in:
parent
fb13b402af
commit
1cd27d7f67
10 changed files with 165 additions and 86 deletions
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package im.vector.matrix.android.internal.crypto.tasks
|
package im.vector.matrix.android.internal.crypto.tasks
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.auth.data.LoginFlowTypes
|
||||||
import im.vector.matrix.android.api.failure.Failure
|
import im.vector.matrix.android.api.failure.Failure
|
||||||
import im.vector.matrix.android.api.failure.toRegistrationFlowResponse
|
import im.vector.matrix.android.api.failure.toRegistrationFlowResponse
|
||||||
import im.vector.matrix.android.internal.crypto.api.CryptoApi
|
import im.vector.matrix.android.internal.crypto.api.CryptoApi
|
||||||
|
@ -37,6 +38,15 @@ internal interface UploadSigningKeysTask : Task<UploadSigningKeysTask.Params, Un
|
||||||
val userKey: CryptoCrossSigningKey,
|
val userKey: CryptoCrossSigningKey,
|
||||||
// the explicit device_id to use for upload (default is to use the same as that used during auth).
|
// the explicit device_id to use for upload (default is to use the same as that used during auth).
|
||||||
val selfSignedKey: CryptoCrossSigningKey,
|
val selfSignedKey: CryptoCrossSigningKey,
|
||||||
|
/**
|
||||||
|
* - If null:
|
||||||
|
* - no retry will be performed
|
||||||
|
* - If not null, it may or may not contain a sessionId:
|
||||||
|
* - If sessionId is null:
|
||||||
|
* - password should not be null: the task will perform a first request to get a sessionId, and then a second one
|
||||||
|
* - If sessionId is not null:
|
||||||
|
* - password should not be null as well, and no retry will be performed
|
||||||
|
*/
|
||||||
val userPasswordAuth: UserPasswordAuth?
|
val userPasswordAuth: UserPasswordAuth?
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -47,42 +57,41 @@ internal class DefaultUploadSigningKeysTask @Inject constructor(
|
||||||
private val cryptoApi: CryptoApi,
|
private val cryptoApi: CryptoApi,
|
||||||
private val eventBus: EventBus
|
private val eventBus: EventBus
|
||||||
) : UploadSigningKeysTask {
|
) : UploadSigningKeysTask {
|
||||||
|
|
||||||
override suspend fun execute(params: UploadSigningKeysTask.Params) {
|
override suspend fun execute(params: UploadSigningKeysTask.Params) {
|
||||||
|
val paramsHaveSessionId = params.userPasswordAuth?.session != null
|
||||||
|
|
||||||
val uploadQuery = UploadSigningKeysBody(
|
val uploadQuery = UploadSigningKeysBody(
|
||||||
masterKey = params.masterKey.toRest(),
|
masterKey = params.masterKey.toRest(),
|
||||||
userSigningKey = params.userKey.toRest(),
|
userSigningKey = params.userKey.toRest(),
|
||||||
selfSigningKey = params.selfSignedKey.toRest(),
|
selfSigningKey = params.selfSignedKey.toRest(),
|
||||||
auth = params.userPasswordAuth.takeIf { params.userPasswordAuth?.session != null }
|
// If sessionId is provided, use the userPasswordAuth
|
||||||
|
auth = params.userPasswordAuth.takeIf { paramsHaveSessionId }
|
||||||
)
|
)
|
||||||
try {
|
try {
|
||||||
// Make a first request to start user-interactive authentication
|
doRequest(uploadQuery)
|
||||||
val request = executeRequest<KeysQueryResponse>(eventBus) {
|
|
||||||
apiCall = cryptoApi.uploadSigningKeys(uploadQuery)
|
|
||||||
}
|
|
||||||
if (request.failures?.isNotEmpty() == true) {
|
|
||||||
throw UploadSigningKeys(request.failures)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
} catch (throwable: Throwable) {
|
} catch (throwable: Throwable) {
|
||||||
val registrationFlowResponse = throwable.toRegistrationFlowResponse()
|
val registrationFlowResponse = throwable.toRegistrationFlowResponse()
|
||||||
if (registrationFlowResponse != null
|
if (registrationFlowResponse != null
|
||||||
&& params.userPasswordAuth != null
|
&& registrationFlowResponse.flows.orEmpty().any { it.stages?.contains(LoginFlowTypes.PASSWORD) == true }
|
||||||
/* Avoid infinite loop */
|
&& params.userPasswordAuth?.password != null
|
||||||
&& params.userPasswordAuth.session.isNullOrEmpty()
|
&& !paramsHaveSessionId
|
||||||
) {
|
) {
|
||||||
// Retry with authentication
|
// Retry with authentication
|
||||||
val req = executeRequest<KeysQueryResponse>(eventBus) {
|
doRequest(uploadQuery.copy(auth = params.userPasswordAuth.copy(session = registrationFlowResponse.session)))
|
||||||
apiCall = cryptoApi.uploadSigningKeys(
|
|
||||||
uploadQuery.copy(auth = params.userPasswordAuth.copy(session = registrationFlowResponse.session))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if (req.failures?.isNotEmpty() == true) {
|
|
||||||
throw UploadSigningKeys(req.failures)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Other error
|
// Other error
|
||||||
throw throwable
|
throw throwable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun doRequest(uploadQuery: UploadSigningKeysBody) {
|
||||||
|
val keysQueryResponse = executeRequest<KeysQueryResponse>(eventBus) {
|
||||||
|
apiCall = cryptoApi.uploadSigningKeys(uploadQuery)
|
||||||
|
}
|
||||||
|
if (keysQueryResponse.failures?.isNotEmpty() == true) {
|
||||||
|
throw UploadSigningKeys(keysQueryResponse.failures)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* 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.riotx.core.utils
|
||||||
|
|
||||||
|
import org.amshove.kluent.shouldBe
|
||||||
|
import org.junit.Test
|
||||||
|
import java.lang.Thread.sleep
|
||||||
|
|
||||||
|
class TemporaryStoreTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testTemporaryStore() {
|
||||||
|
// Keep the data 30 millis
|
||||||
|
val store = TemporaryStore<String>(30)
|
||||||
|
|
||||||
|
store.data = "test"
|
||||||
|
store.data shouldBe "test"
|
||||||
|
sleep(15)
|
||||||
|
store.data shouldBe "test"
|
||||||
|
sleep(20)
|
||||||
|
store.data shouldBe null
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* 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.riotx.core.utils
|
||||||
|
|
||||||
|
import java.util.Timer
|
||||||
|
import java.util.TimerTask
|
||||||
|
|
||||||
|
const val THREE_MINUTES = 3 * 60_000L
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store an object T for a specific period of time
|
||||||
|
*/
|
||||||
|
open class TemporaryStore<T>(private val delay: Long = THREE_MINUTES) {
|
||||||
|
|
||||||
|
private var timer: Timer? = null
|
||||||
|
|
||||||
|
var data: T? = null
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
timer?.cancel()
|
||||||
|
timer = Timer().also {
|
||||||
|
it.schedule(object : TimerTask() {
|
||||||
|
override fun run() {
|
||||||
|
field = null
|
||||||
|
}
|
||||||
|
}, delay)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -97,7 +97,7 @@ class BackupToQuadSMigrationTask @Inject constructor(
|
||||||
when {
|
when {
|
||||||
params.passphrase?.isNotEmpty() == true -> {
|
params.passphrase?.isNotEmpty() == true -> {
|
||||||
reportProgress(params, R.string.bootstrap_progress_generating_ssss)
|
reportProgress(params, R.string.bootstrap_progress_generating_ssss)
|
||||||
awaitCallback {
|
awaitCallback<SsssKeyCreationInfo> {
|
||||||
quadS.generateKeyWithPassphrase(
|
quadS.generateKeyWithPassphrase(
|
||||||
UUID.randomUUID().toString(),
|
UUID.randomUUID().toString(),
|
||||||
"ssss_key",
|
"ssss_key",
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
|
|
||||||
package im.vector.riotx.features.crypto.recover
|
package im.vector.riotx.features.crypto.recover
|
||||||
|
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.UserPasswordAuth
|
|
||||||
import im.vector.riotx.core.platform.VectorViewModelAction
|
import im.vector.riotx.core.platform.VectorViewModelAction
|
||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
|
|
||||||
|
@ -29,8 +28,8 @@ sealed class BootstrapActions : VectorViewModelAction {
|
||||||
object GoToCompleted : BootstrapActions()
|
object GoToCompleted : BootstrapActions()
|
||||||
object GoToEnterAccountPassword : BootstrapActions()
|
object GoToEnterAccountPassword : BootstrapActions()
|
||||||
|
|
||||||
data class DoInitialize(val passphrase: String, val auth: UserPasswordAuth? = null) : BootstrapActions()
|
data class DoInitialize(val passphrase: String) : BootstrapActions()
|
||||||
data class DoInitializeGeneratedKey(val auth: UserPasswordAuth? = null) : BootstrapActions()
|
object DoInitializeGeneratedKey : BootstrapActions()
|
||||||
object TogglePasswordVisibility : BootstrapActions()
|
object TogglePasswordVisibility : BootstrapActions()
|
||||||
data class UpdateCandidatePassphrase(val pass: String) : BootstrapActions()
|
data class UpdateCandidatePassphrase(val pass: String) : BootstrapActions()
|
||||||
data class UpdateConfirmCandidatePassphrase(val pass: String) : BootstrapActions()
|
data class UpdateConfirmCandidatePassphrase(val pass: String) : BootstrapActions()
|
||||||
|
|
|
@ -90,7 +90,7 @@ class BootstrapBottomSheet : VectorBaseBottomSheetDialogFragment() {
|
||||||
.apply {
|
.apply {
|
||||||
if (genKeyOption) {
|
if (genKeyOption) {
|
||||||
setNeutralButton(R.string.generate_message_key) { _, _ ->
|
setNeutralButton(R.string.generate_message_key) { _, _ ->
|
||||||
viewModel.handle(BootstrapActions.DoInitializeGeneratedKey())
|
viewModel.handle(BootstrapActions.DoInitializeGeneratedKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ sealed class BootstrapResult {
|
||||||
class FailedToStorePrivateKeyInSSSS(failure: Throwable) : Failure(failure.localizedMessage)
|
class FailedToStorePrivateKeyInSSSS(failure: Throwable) : Failure(failure.localizedMessage)
|
||||||
object MissingPrivateKey : Failure(null)
|
object MissingPrivateKey : Failure(null)
|
||||||
|
|
||||||
data class PasswordAuthFlowMissing(val sessionId: String, val userId: String) : Failure(null)
|
data class PasswordAuthFlowMissing(val sessionId: String) : Failure(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BootstrapProgressListener {
|
interface BootstrapProgressListener {
|
||||||
|
@ -232,9 +232,11 @@ class BootstrapCrossSigningTask @Inject constructor(
|
||||||
} else {
|
} else {
|
||||||
val registrationFlowResponse = failure.toRegistrationFlowResponse()
|
val registrationFlowResponse = failure.toRegistrationFlowResponse()
|
||||||
if (registrationFlowResponse != null) {
|
if (registrationFlowResponse != null) {
|
||||||
if (registrationFlowResponse.flows?.any { it.stages?.contains(LoginFlowTypes.PASSWORD) == true } != true) {
|
return if (registrationFlowResponse.flows.orEmpty().any { it.stages?.contains(LoginFlowTypes.PASSWORD) == true }) {
|
||||||
|
BootstrapResult.PasswordAuthFlowMissing(registrationFlowResponse.session ?: "")
|
||||||
|
} else {
|
||||||
// can't do this from here
|
// can't do this from here
|
||||||
return BootstrapResult.UnsupportedAuthFlow()
|
BootstrapResult.UnsupportedAuthFlow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ import com.nulabinc.zxcvbn.Strength
|
||||||
import com.nulabinc.zxcvbn.Zxcvbn
|
import com.nulabinc.zxcvbn.Zxcvbn
|
||||||
import com.squareup.inject.assisted.Assisted
|
import com.squareup.inject.assisted.Assisted
|
||||||
import com.squareup.inject.assisted.AssistedInject
|
import com.squareup.inject.assisted.AssistedInject
|
||||||
|
import im.vector.matrix.android.api.failure.Failure
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
import im.vector.matrix.android.api.session.securestorage.RawBytesKeySpec
|
import im.vector.matrix.android.api.session.securestorage.RawBytesKeySpec
|
||||||
import im.vector.matrix.android.api.session.securestorage.SsssKeyCreationInfo
|
import im.vector.matrix.android.api.session.securestorage.SsssKeyCreationInfo
|
||||||
|
@ -57,7 +58,6 @@ data class BootstrapViewState(
|
||||||
val passphraseConfirmMatch: Async<Unit> = Uninitialized,
|
val passphraseConfirmMatch: Async<Unit> = Uninitialized,
|
||||||
val recoveryKeyCreationInfo: SsssKeyCreationInfo? = null,
|
val recoveryKeyCreationInfo: SsssKeyCreationInfo? = null,
|
||||||
val initializationWaitingViewData: WaitingViewData? = null,
|
val initializationWaitingViewData: WaitingViewData? = null,
|
||||||
val currentReAuth: UserPasswordAuth? = null,
|
|
||||||
val recoverySaveFileProcess: Async<Unit> = Uninitialized
|
val recoverySaveFileProcess: Async<Unit> = Uninitialized
|
||||||
) : MvRxState
|
) : MvRxState
|
||||||
|
|
||||||
|
@ -78,6 +78,8 @@ class BootstrapSharedViewModel @AssistedInject constructor(
|
||||||
fun create(initialState: BootstrapViewState, args: BootstrapBottomSheet.Args): BootstrapSharedViewModel
|
fun create(initialState: BootstrapViewState, args: BootstrapBottomSheet.Args): BootstrapSharedViewModel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var _pendingSession: String? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// need to check if user have an existing keybackup
|
// need to check if user have an existing keybackup
|
||||||
if (args.isNewAccount) {
|
if (args.isNewAccount) {
|
||||||
|
@ -182,15 +184,15 @@ class BootstrapSharedViewModel @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
is BootstrapActions.DoInitialize -> {
|
is BootstrapActions.DoInitialize -> {
|
||||||
if (state.passphrase == state.passphraseRepeat) {
|
if (state.passphrase == state.passphraseRepeat) {
|
||||||
val auth = action.auth ?: reAuthHelper.rememberedAuth()
|
val userPassword = reAuthHelper.data
|
||||||
if (auth == null) {
|
if (userPassword == null) {
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
step = BootstrapStep.AccountPassword(false)
|
step = BootstrapStep.AccountPassword(false)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
startInitializeFlow(action.auth)
|
startInitializeFlow(userPassword)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setState {
|
setState {
|
||||||
|
@ -201,8 +203,8 @@ class BootstrapSharedViewModel @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is BootstrapActions.DoInitializeGeneratedKey -> {
|
is BootstrapActions.DoInitializeGeneratedKey -> {
|
||||||
val auth = action.auth ?: reAuthHelper.rememberedAuth()
|
val userPassword = reAuthHelper.data
|
||||||
if (auth == null) {
|
if (userPassword == null) {
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
passphrase = null,
|
passphrase = null,
|
||||||
|
@ -217,7 +219,7 @@ class BootstrapSharedViewModel @AssistedInject constructor(
|
||||||
passphraseRepeat = null
|
passphraseRepeat = null
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
startInitializeFlow(action.auth)
|
startInitializeFlow(userPassword)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BootstrapActions.RecoveryKeySaved -> {
|
BootstrapActions.RecoveryKeySaved -> {
|
||||||
|
@ -260,10 +262,7 @@ class BootstrapSharedViewModel @AssistedInject constructor(
|
||||||
} else return@withState
|
} else return@withState
|
||||||
}
|
}
|
||||||
is BootstrapActions.ReAuth -> {
|
is BootstrapActions.ReAuth -> {
|
||||||
startInitializeFlow(
|
startInitializeFlow(action.pass)
|
||||||
state.currentReAuth?.copy(password = action.pass)
|
|
||||||
?: UserPasswordAuth(user = session.myUserId, password = action.pass)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
is BootstrapActions.DoMigrateWithPassphrase -> {
|
is BootstrapActions.DoMigrateWithPassphrase -> {
|
||||||
startMigrationFlow(state.step, action.passphrase, null)
|
startMigrationFlow(state.step, action.passphrase, null)
|
||||||
|
@ -322,15 +321,15 @@ class BootstrapSharedViewModel @AssistedInject constructor(
|
||||||
migrationRecoveryKey = recoveryKey
|
migrationRecoveryKey = recoveryKey
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val auth = reAuthHelper.rememberedAuth()
|
val userPassword = reAuthHelper.data
|
||||||
if (auth == null) {
|
if (userPassword == null) {
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
step = BootstrapStep.AccountPassword(false)
|
step = BootstrapStep.AccountPassword(false)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
startInitializeFlow(auth)
|
startInitializeFlow(userPassword)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_viewEvents.post(
|
_viewEvents.post(
|
||||||
|
@ -350,7 +349,7 @@ class BootstrapSharedViewModel @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startInitializeFlow(auth: UserPasswordAuth?) {
|
private fun startInitializeFlow(userPassword: String?) {
|
||||||
setState {
|
setState {
|
||||||
copy(step = BootstrapStep.Initializing)
|
copy(step = BootstrapStep.Initializing)
|
||||||
}
|
}
|
||||||
|
@ -367,25 +366,37 @@ class BootstrapSharedViewModel @AssistedInject constructor(
|
||||||
|
|
||||||
withState { state ->
|
withState { state ->
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
bootstrapTask.invoke(this, Params(
|
val userPasswordAuth = userPassword?.let {
|
||||||
userPasswordAuth = auth ?: reAuthHelper.rememberedAuth(),
|
UserPasswordAuth(
|
||||||
progressListener = progressListener,
|
// Note that _pendingSession may or may not be null, this is OK, it will be managed by the task
|
||||||
passphrase = state.passphrase,
|
session = _pendingSession,
|
||||||
keySpec = state.migrationRecoveryKey?.let { extractCurveKeyFromRecoveryKey(it)?.let { RawBytesKeySpec(it) } }
|
user = session.myUserId,
|
||||||
)) {
|
password = it
|
||||||
when (it) {
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
bootstrapTask.invoke(this,
|
||||||
|
Params(
|
||||||
|
userPasswordAuth = userPasswordAuth,
|
||||||
|
progressListener = progressListener,
|
||||||
|
passphrase = state.passphrase,
|
||||||
|
keySpec = state.migrationRecoveryKey?.let { extractCurveKeyFromRecoveryKey(it)?.let { RawBytesKeySpec(it) } }
|
||||||
|
)
|
||||||
|
) { bootstrapResult ->
|
||||||
|
when (bootstrapResult) {
|
||||||
is BootstrapResult.Success -> {
|
is BootstrapResult.Success -> {
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
recoveryKeyCreationInfo = it.keyInfo,
|
recoveryKeyCreationInfo = bootstrapResult.keyInfo,
|
||||||
step = BootstrapStep.SaveRecoveryKey(false)
|
step = BootstrapStep.SaveRecoveryKey(false)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is BootstrapResult.PasswordAuthFlowMissing -> {
|
is BootstrapResult.PasswordAuthFlowMissing -> {
|
||||||
|
// Ask the password to the user
|
||||||
|
_pendingSession = bootstrapResult.sessionId
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
currentReAuth = UserPasswordAuth(session = it.sessionId, user = it.userId),
|
|
||||||
step = BootstrapStep.AccountPassword(false)
|
step = BootstrapStep.AccountPassword(false)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -396,20 +407,20 @@ class BootstrapSharedViewModel @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
is BootstrapResult.InvalidPasswordError -> {
|
is BootstrapResult.InvalidPasswordError -> {
|
||||||
// it's a bad password
|
// it's a bad password
|
||||||
|
// We clear the auth session, to avoid 'Requested operation has changed during the UI authentication session' error
|
||||||
|
_pendingSession = null
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
// We clear the auth session, to avoid 'Requested operation has changed during the UI authentication session' error
|
|
||||||
currentReAuth = UserPasswordAuth(session = null, user = session.myUserId),
|
|
||||||
step = BootstrapStep.AccountPassword(false, stringProvider.getString(R.string.auth_invalid_login_param))
|
step = BootstrapStep.AccountPassword(false, stringProvider.getString(R.string.auth_invalid_login_param))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is BootstrapResult.Failure -> {
|
is BootstrapResult.Failure -> {
|
||||||
if (it is BootstrapResult.GenericError
|
if (bootstrapResult is BootstrapResult.GenericError
|
||||||
&& it.failure is im.vector.matrix.android.api.failure.Failure.OtherServerError
|
&& bootstrapResult.failure is Failure.OtherServerError
|
||||||
&& it.failure.httpCode == 401) {
|
&& bootstrapResult.failure.httpCode == 401) {
|
||||||
} else {
|
} else {
|
||||||
_viewEvents.post(BootstrapViewEvents.ModalError(it.error ?: stringProvider.getString(R.string.matrix_error)))
|
_viewEvents.post(BootstrapViewEvents.ModalError(bootstrapResult.error ?: stringProvider.getString(R.string.matrix_error)))
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
step = BootstrapStep.ConfirmPassphrase(false)
|
step = BootstrapStep.ConfirmPassphrase(false)
|
||||||
|
|
|
@ -41,7 +41,6 @@ import im.vector.matrix.android.api.auth.registration.Stage
|
||||||
import im.vector.matrix.android.api.auth.wellknown.WellknownResult
|
import im.vector.matrix.android.api.auth.wellknown.WellknownResult
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
import im.vector.matrix.android.api.util.Cancelable
|
import im.vector.matrix.android.api.util.Cancelable
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.UserPasswordAuth
|
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.di.ActiveSessionHolder
|
import im.vector.riotx.core.di.ActiveSessionHolder
|
||||||
import im.vector.riotx.core.extensions.configureAndStart
|
import im.vector.riotx.core.extensions.configureAndStart
|
||||||
|
@ -289,7 +288,7 @@ class LoginViewModel @AssistedInject constructor(
|
||||||
|
|
||||||
private fun handleRegisterWith(action: LoginAction.LoginOrRegister) {
|
private fun handleRegisterWith(action: LoginAction.LoginOrRegister) {
|
||||||
setState { copy(asyncRegistration = Loading()) }
|
setState { copy(asyncRegistration = Loading()) }
|
||||||
reAuthHelper.rememberAuth(UserPasswordAuth(user = action.username, password = action.password))
|
reAuthHelper.data = action.password
|
||||||
currentTask = registrationWizard?.createAccount(
|
currentTask = registrationWizard?.createAccount(
|
||||||
action.username,
|
action.username,
|
||||||
action.password,
|
action.password,
|
||||||
|
|
|
@ -16,33 +16,12 @@
|
||||||
|
|
||||||
package im.vector.riotx.features.login
|
package im.vector.riotx.features.login
|
||||||
|
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.UserPasswordAuth
|
import im.vector.riotx.core.utils.TemporaryStore
|
||||||
import java.util.Timer
|
|
||||||
import java.util.TimerTask
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
const val THREE_MINUTES = 3 * 60_000L
|
/**
|
||||||
|
* Will store the account password for 3 minutes
|
||||||
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
class ReAuthHelper @Inject constructor() {
|
class ReAuthHelper @Inject constructor() : TemporaryStore<String>()
|
||||||
|
|
||||||
private var timer: Timer? = null
|
|
||||||
|
|
||||||
private var rememberedInfo: UserPasswordAuth? = null
|
|
||||||
|
|
||||||
fun rememberAuth(password: UserPasswordAuth?) {
|
|
||||||
timer?.cancel()
|
|
||||||
timer = null
|
|
||||||
rememberedInfo = password
|
|
||||||
timer = Timer().apply {
|
|
||||||
schedule(object : TimerTask() {
|
|
||||||
override fun run() {
|
|
||||||
rememberedInfo = null
|
|
||||||
}
|
|
||||||
}, THREE_MINUTES)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun rememberedAuth() = rememberedInfo
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue