Check homeserver when login using qr code (#4708)
* Login with Qr code: check homeserver validity * QrCode login, unauthorized homeserver: update copy. * Update screenshots * Add unit test on SdkQrCodeLoginData * Remove default param value. * Remember imageAnalysis --------- Co-authored-by: ElementBot <android@element.io>
This commit is contained in:
parent
9825469912
commit
f1ca70fb9a
22 changed files with 208 additions and 30 deletions
|
|
@ -21,8 +21,10 @@ open class AccountProviderProvider : PreviewParameterProvider<AccountProvider> {
|
|||
)
|
||||
}
|
||||
|
||||
fun anAccountProvider() = AccountProvider(
|
||||
url = AuthenticationConfig.MATRIX_ORG_URL,
|
||||
fun anAccountProvider(
|
||||
url: String = AuthenticationConfig.MATRIX_ORG_URL,
|
||||
) = AccountProvider(
|
||||
url = url,
|
||||
subtitle = "Matrix.org is an open network for secure, decentralized communication.",
|
||||
isPublic = true,
|
||||
isMatrixOrg = true,
|
||||
|
|
|
|||
|
|
@ -56,7 +56,10 @@ class ChangeServerPresenter @Inject constructor(
|
|||
) = launch {
|
||||
suspend {
|
||||
if (enterpriseService.isAllowedToConnectToHomeserver(data.url).not()) {
|
||||
throw UnauthorizedAccountProviderException(data)
|
||||
throw UnauthorizedAccountProviderException(
|
||||
unauthorisedAccountProviderTitle = data.title,
|
||||
authorisedAccountProviderTitles = listOfNotNull(enterpriseService.defaultHomeserver())
|
||||
)
|
||||
}
|
||||
authenticationService.setHomeserver(data.url).map {
|
||||
authenticationService.getHomeserverDetails().value!!
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
package io.element.android.features.login.impl.changeserver
|
||||
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import io.element.android.features.login.impl.accountprovider.anAccountProvider
|
||||
import io.element.android.features.login.impl.error.ChangeServerError
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
|
@ -19,7 +18,14 @@ open class ChangeServerStateProvider : PreviewParameterProvider<ChangeServerStat
|
|||
aChangeServerState(),
|
||||
aChangeServerState(changeServerAction = AsyncData.Failure(ChangeServerError.Error(CommonStrings.error_unknown))),
|
||||
aChangeServerState(changeServerAction = AsyncData.Failure(ChangeServerError.SlidingSyncAlert)),
|
||||
aChangeServerState(changeServerAction = AsyncData.Failure(ChangeServerError.UnauthorizedAccountProvider(anAccountProvider()))),
|
||||
aChangeServerState(
|
||||
changeServerAction = AsyncData.Failure(
|
||||
ChangeServerError.UnauthorizedAccountProvider(
|
||||
unauthorisedAccountProviderTitle = "example.com",
|
||||
authorisedAccountProviderTitles = listOf("element.io", "element.org"),
|
||||
)
|
||||
)
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ fun ChangeServerView(
|
|||
content = stringResource(
|
||||
id = R.string.screen_change_server_error_unauthorized_homeserver,
|
||||
LocalBuildMeta.current.applicationName,
|
||||
error.accountProvider.title,
|
||||
error.unauthorisedAccountProviderTitle,
|
||||
),
|
||||
onSubmit = {
|
||||
eventSink.invoke(ChangeServerEvents.ClearError)
|
||||
|
|
|
|||
|
|
@ -7,8 +7,7 @@
|
|||
|
||||
package io.element.android.features.login.impl.changeserver
|
||||
|
||||
import io.element.android.features.login.impl.accountprovider.AccountProvider
|
||||
|
||||
class UnauthorizedAccountProviderException(
|
||||
val accountProvider: AccountProvider,
|
||||
val unauthorisedAccountProviderTitle: String,
|
||||
val authorisedAccountProviderTitles: List<String>,
|
||||
) : Exception()
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import androidx.annotation.StringRes
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import io.element.android.features.login.impl.R
|
||||
import io.element.android.features.login.impl.accountprovider.AccountProvider
|
||||
import io.element.android.features.login.impl.changeserver.UnauthorizedAccountProviderException
|
||||
import io.element.android.libraries.matrix.api.auth.AuthenticationException
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
|
@ -26,7 +25,8 @@ sealed class ChangeServerError : Throwable() {
|
|||
}
|
||||
|
||||
data class UnauthorizedAccountProvider(
|
||||
val accountProvider: AccountProvider,
|
||||
val unauthorisedAccountProviderTitle: String,
|
||||
val authorisedAccountProviderTitles: List<String>,
|
||||
) : ChangeServerError()
|
||||
|
||||
data object SlidingSyncAlert : ChangeServerError()
|
||||
|
|
@ -35,7 +35,10 @@ sealed class ChangeServerError : Throwable() {
|
|||
fun from(error: Throwable): ChangeServerError = when (error) {
|
||||
is AuthenticationException.SlidingSyncVersion -> SlidingSyncAlert
|
||||
is AuthenticationException.Oidc -> Error(messageStr = error.message)
|
||||
is UnauthorizedAccountProviderException -> UnauthorizedAccountProvider(error.accountProvider)
|
||||
is UnauthorizedAccountProviderException -> UnauthorizedAccountProvider(
|
||||
unauthorisedAccountProviderTitle = error.unauthorisedAccountProviderTitle,
|
||||
authorisedAccountProviderTitles = error.authorisedAccountProviderTitles,
|
||||
)
|
||||
else -> Error(messageId = R.string.screen_change_server_error_invalid_homeserver)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ import androidx.compose.runtime.mutableStateOf
|
|||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import io.element.android.features.enterprise.api.EnterpriseService
|
||||
import io.element.android.features.login.impl.changeserver.UnauthorizedAccountProviderException
|
||||
import io.element.android.features.login.impl.qrcode.QrCodeLoginManager
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
|
|
@ -36,6 +38,7 @@ class QrCodeScanPresenter @Inject constructor(
|
|||
private val qrCodeLoginDataFactory: MatrixQrCodeLoginDataFactory,
|
||||
private val qrCodeLoginManager: QrCodeLoginManager,
|
||||
private val coroutineDispatchers: CoroutineDispatchers,
|
||||
private val enterpriseService: EnterpriseService,
|
||||
) : Presenter<QrCodeScanState> {
|
||||
private var isScanning by mutableStateOf(true)
|
||||
|
||||
|
|
@ -90,9 +93,17 @@ class QrCodeScanPresenter @Inject constructor(
|
|||
|
||||
launch(coroutineDispatchers.computation) {
|
||||
suspend {
|
||||
qrCodeLoginDataFactory.parseQrCodeData(code).onFailure {
|
||||
val data = qrCodeLoginDataFactory.parseQrCodeData(code).onFailure {
|
||||
Timber.e(it, "Error parsing QR code data")
|
||||
}.getOrThrow()
|
||||
val serverName = data.serverName()
|
||||
if (serverName != null && enterpriseService.isAllowedToConnectToHomeserver(serverName).not()) {
|
||||
throw UnauthorizedAccountProviderException(
|
||||
unauthorisedAccountProviderTitle = serverName,
|
||||
authorisedAccountProviderTitles = listOfNotNull(enterpriseService.defaultHomeserver())
|
||||
)
|
||||
}
|
||||
data
|
||||
}.runCatchingUpdatingState(codeScannedAction)
|
||||
}.invokeOnCompletion {
|
||||
isProcessingCode.set(false)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
package io.element.android.features.login.impl.screens.qrcode.scan
|
||||
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import io.element.android.features.login.impl.changeserver.UnauthorizedAccountProviderException
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.matrix.api.auth.qrlogin.MatrixQrCodeLoginData
|
||||
import io.element.android.libraries.matrix.api.auth.qrlogin.QrLoginException
|
||||
|
|
@ -19,6 +20,15 @@ open class QrCodeScanStateProvider : PreviewParameterProvider<QrCodeScanState> {
|
|||
aQrCodeScanState(isScanning = false, authenticationAction = AsyncAction.Loading),
|
||||
aQrCodeScanState(isScanning = false, authenticationAction = AsyncAction.Failure(Exception("Error"))),
|
||||
aQrCodeScanState(isScanning = false, authenticationAction = AsyncAction.Failure(QrLoginException.OtherDeviceNotSignedIn)),
|
||||
aQrCodeScanState(
|
||||
isScanning = false,
|
||||
authenticationAction = AsyncAction.Failure(
|
||||
UnauthorizedAccountProviderException(
|
||||
unauthorisedAccountProviderTitle = "example.com",
|
||||
authorisedAccountProviderTitles = listOf("element.io", "element.org"),
|
||||
)
|
||||
)
|
||||
),
|
||||
// Add other state here
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import androidx.compose.ui.unit.dp
|
|||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.compound.tokens.generated.CompoundIcons
|
||||
import io.element.android.features.login.impl.R
|
||||
import io.element.android.features.login.impl.changeserver.UnauthorizedAccountProviderException
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.designsystem.atomic.pages.FlowStepPage
|
||||
import io.element.android.libraries.designsystem.components.BigIcon
|
||||
|
|
@ -144,6 +145,12 @@ private fun ColumnScope.Buttons(
|
|||
Spacer(modifier = Modifier.width(4.dp))
|
||||
Text(
|
||||
text = when (error) {
|
||||
is UnauthorizedAccountProviderException -> {
|
||||
stringResource(
|
||||
id = R.string.screen_change_server_error_unauthorized_homeserver_title,
|
||||
error.unauthorisedAccountProviderTitle,
|
||||
)
|
||||
}
|
||||
is QrLoginException.OtherDeviceNotSignedIn -> {
|
||||
stringResource(R.string.screen_qr_code_login_device_not_signed_in_scan_state_subtitle)
|
||||
}
|
||||
|
|
@ -156,6 +163,12 @@ private fun ColumnScope.Buttons(
|
|||
}
|
||||
Text(
|
||||
text = when (error) {
|
||||
is UnauthorizedAccountProviderException -> {
|
||||
stringResource(
|
||||
id = R.string.screen_change_server_error_unauthorized_homeserver_content,
|
||||
error.authorisedAccountProviderTitles.joinToString(),
|
||||
)
|
||||
}
|
||||
is QrLoginException.OtherDeviceNotSignedIn -> {
|
||||
stringResource(R.string.screen_qr_code_login_device_not_signed_in_scan_state_description)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@
|
|||
%1$s"</string>
|
||||
<string name="screen_change_server_error_no_sliding_sync_message">"The selected account provider does not support sliding sync. An upgrade to the server is needed to use %1$s."</string>
|
||||
<string name="screen_change_server_error_unauthorized_homeserver">"%1$s is not allowed to connect to %2$s."</string>
|
||||
<string name="screen_change_server_error_unauthorized_homeserver_content">"This app has been configured to allow: %1$s."</string>
|
||||
<string name="screen_change_server_error_unauthorized_homeserver_title">"Account provider %1$s not allowed."</string>
|
||||
<string name="screen_change_server_form_header">"Homeserver URL"</string>
|
||||
<string name="screen_change_server_form_notice">"Enter a domain address."</string>
|
||||
<string name="screen_change_server_subtitle">"What is the address of your server?"</string>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue