Browse Source

Merge pull request #1443 from vector-im/feature/bma/httpHomeserver

Ensure http url entered by the user are provided to the SDK without being altered
pull/1458/head
Benoit Marty 12 months ago committed by GitHub
parent
commit
7b0a8552cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      app/src/main/AndroidManifest.xml
  2. 35
      app/src/main/res/xml/network_security_config.xml
  3. 5
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/accountprovider/AccountProvider.kt
  4. 3
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderProvider.kt
  5. 2
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenter.kt
  6. 3
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderPresenter.kt
  7. 1
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderView.kt
  8. 2
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenter.kt
  9. 2
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderState.kt
  10. 3
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderStateProvider.kt
  11. 7
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderView.kt
  12. 6
      features/login/impl/src/main/kotlin/io/element/android/features/login/impl/util/LoginConstants.kt
  13. 4
      features/login/impl/src/test/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenterTest.kt
  14. 1
      features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderPresenterTest.kt
  15. 2
      samples/minimal/src/main/kotlin/io/element/android/samples/minimal/LoginScreen.kt

10
app/src/main/AndroidManifest.xml

@ -28,6 +28,7 @@ @@ -28,6 +28,7 @@
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.ElementX"
@ -81,11 +82,12 @@ @@ -81,11 +82,12 @@
tools:node="remove" />
<provider
android:authorities="${applicationId}.fileprovider"
android:name="androidx.core.content.FileProvider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_providers" />
</provider>

35
app/src/main/res/xml/network_security_config.xml

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<!-- Ref: https://developer.android.com/training/articles/security-config.html -->
<!-- By default, do not allow clearText traffic -->
<base-config cleartextTrafficPermitted="false" />
<!-- Allow clearText traffic on some specified host -->
<domain-config cleartextTrafficPermitted="true">
<!-- Localhost -->
<domain includeSubdomains="true">localhost</domain>
<domain includeSubdomains="true">127.0.0.1</domain>
<!-- Localhost for Android emulator -->
<domain includeSubdomains="true">10.0.2.2</domain>
<!-- Onion services -->
<domain includeSubdomains="true">onion</domain>
<!-- Domains that are used for LANs -->
<!-- These are IANA recognized special use domain names, see https://www.iana.org/assignments/special-use-domain-names/special-use-domain-names.xhtml -->
<domain includeSubdomains="true">home.arpa</domain>
<domain includeSubdomains="true">local</domain> <!-- Note this has been reserved for use with mDNS -->
<domain includeSubdomains="true">test</domain>
<!-- These are observed in the wild either by convention or RFCs that have not been accepted, and are not currently TLDs -->
<domain includeSubdomains="true">home</domain>
<domain includeSubdomains="true">lan</domain>
<domain includeSubdomains="true">localdomain</domain>
</domain-config>
<debug-overrides>
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
</trust-anchors>
</debug-overrides>
</network-security-config>

5
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/accountprovider/AccountProvider.kt

@ -16,8 +16,9 @@ @@ -16,8 +16,9 @@
package io.element.android.features.login.impl.accountprovider
data class AccountProvider constructor(
val title: String,
data class AccountProvider(
val url: String,
val title: String = url.removePrefix("https://").removePrefix("http://"),
val subtitle: String? = null,
val isPublic: Boolean = false,
val isMatrixOrg: Boolean = false,

3
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderProvider.kt

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
package io.element.android.features.login.impl.accountprovider
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.login.impl.util.LoginConstants
open class AccountProviderProvider : PreviewParameterProvider<AccountProvider> {
override val values: Sequence<AccountProvider>
@ -31,7 +32,7 @@ open class AccountProviderProvider : PreviewParameterProvider<AccountProvider> { @@ -31,7 +32,7 @@ open class AccountProviderProvider : PreviewParameterProvider<AccountProvider> {
}
fun anAccountProvider() = AccountProvider(
title = "matrix.org",
url = LoginConstants.MATRIX_ORG_URL,
subtitle = "Matrix.org is an open network for secure, decentralized communication.",
isPublic = true,
isMatrixOrg = true,

2
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenter.kt

@ -63,7 +63,7 @@ class ChangeServerPresenter @Inject constructor( @@ -63,7 +63,7 @@ class ChangeServerPresenter @Inject constructor(
changeServerAction: MutableState<Async<Unit>>,
) = launch {
suspend {
authenticationService.setHomeserver(data.title).map {
authenticationService.setHomeserver(data.url).map {
authenticationService.getHomeserverDetails().value!!
// Valid, remember user choice
accountProviderDataSource.userSelection(data)

3
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderPresenter.kt

@ -19,6 +19,7 @@ package io.element.android.features.login.impl.screens.changeaccountprovider @@ -19,6 +19,7 @@ package io.element.android.features.login.impl.screens.changeaccountprovider
import androidx.compose.runtime.Composable
import io.element.android.features.login.impl.accountprovider.AccountProvider
import io.element.android.features.login.impl.changeserver.ChangeServerPresenter
import io.element.android.features.login.impl.util.LoginConstants
import io.element.android.libraries.architecture.Presenter
import javax.inject.Inject
@ -33,7 +34,7 @@ class ChangeAccountProviderPresenter @Inject constructor( @@ -33,7 +34,7 @@ class ChangeAccountProviderPresenter @Inject constructor(
// Just matrix.org by default for now
accountProviders = listOf(
AccountProvider(
title = "matrix.org",
url = LoginConstants.MATRIX_ORG_URL,
subtitle = null,
isPublic = true,
isMatrixOrg = true,

1
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderView.kt

@ -109,6 +109,7 @@ fun ChangeAccountProviderView( @@ -109,6 +109,7 @@ fun ChangeAccountProviderView(
// Other
AccountProviderView(
item = AccountProvider(
url = "",
title = stringResource(id = R.string.screen_change_account_provider_other),
),
onClick = onOtherProviderClicked

2
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenter.kt

@ -76,7 +76,7 @@ class ConfirmAccountProviderPresenter @AssistedInject constructor( @@ -76,7 +76,7 @@ class ConfirmAccountProviderPresenter @AssistedInject constructor(
fun handleEvents(event: ConfirmAccountProviderEvents) {
when (event) {
ConfirmAccountProviderEvents.Continue -> {
localCoroutineScope.submit(accountProvider.title, loginFlowAction)
localCoroutineScope.submit(accountProvider.url, loginFlowAction)
}
ConfirmAccountProviderEvents.ClearError -> loginFlowAction.value = Async.Uninitialized
}

2
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderState.kt

@ -27,7 +27,7 @@ data class ConfirmAccountProviderState( @@ -27,7 +27,7 @@ data class ConfirmAccountProviderState(
val loginFlow: Async<LoginFlow>,
val eventSink: (ConfirmAccountProviderEvents) -> Unit
) {
val submitEnabled: Boolean get() = accountProvider.title.isNotEmpty() && (loginFlow is Async.Uninitialized || loginFlow is Async.Loading)
val submitEnabled: Boolean get() = accountProvider.url.isNotEmpty() && (loginFlow is Async.Uninitialized || loginFlow is Async.Loading)
}
sealed interface LoginFlow {

3
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderStateProvider.kt

@ -19,6 +19,7 @@ package io.element.android.features.login.impl.screens.searchaccountprovider @@ -19,6 +19,7 @@ package io.element.android.features.login.impl.screens.searchaccountprovider
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.login.impl.changeserver.aChangeServerState
import io.element.android.features.login.impl.resolver.HomeserverData
import io.element.android.features.login.impl.util.LoginConstants
import io.element.android.libraries.architecture.Async
open class SearchAccountProviderStateProvider : PreviewParameterProvider<SearchAccountProviderState> {
@ -49,7 +50,7 @@ fun aHomeserverDataList(): List<HomeserverData> { @@ -49,7 +50,7 @@ fun aHomeserverDataList(): List<HomeserverData> {
}
fun aHomeserverData(
homeserverUrl: String = "https://matrix.org",
homeserverUrl: String = LoginConstants.MATRIX_ORG_URL,
isWellknownValid: Boolean = true,
supportSlidingSync: Boolean = true,
): HomeserverData {

7
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderView.kt

@ -54,12 +54,13 @@ import io.element.android.features.login.impl.accountprovider.AccountProviderVie @@ -54,12 +54,13 @@ import io.element.android.features.login.impl.accountprovider.AccountProviderVie
import io.element.android.features.login.impl.changeserver.ChangeServerEvents
import io.element.android.features.login.impl.changeserver.ChangeServerView
import io.element.android.features.login.impl.resolver.HomeserverData
import io.element.android.features.login.impl.util.LoginConstants
import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.form.textFieldState
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.IconButton
@ -195,9 +196,9 @@ fun SearchAccountProviderView( @@ -195,9 +196,9 @@ fun SearchAccountProviderView(
@Composable
private fun HomeserverData.toAccountProvider(): AccountProvider {
val isMatrixOrg = homeserverUrl == "https://matrix.org"
val isMatrixOrg = homeserverUrl == LoginConstants.MATRIX_ORG_URL
return AccountProvider(
title = homeserverUrl.removePrefix("http://").removePrefix("https://"),
url = homeserverUrl,
subtitle = if (isMatrixOrg) stringResource(id = R.string.screen_change_account_provider_matrix_org_subtitle) else null,
isPublic = isMatrixOrg, // There is no need to know for other servers right now
isMatrixOrg = isMatrixOrg,

6
features/login/impl/src/main/kotlin/io/element/android/features/login/impl/util/LoginConstants.kt

@ -19,14 +19,14 @@ package io.element.android.features.login.impl.util @@ -19,14 +19,14 @@ package io.element.android.features.login.impl.util
import io.element.android.features.login.impl.accountprovider.AccountProvider
object LoginConstants {
const val MATRIX_ORG_URL = "matrix.org"
const val MATRIX_ORG_URL = "https://matrix.org"
const val DEFAULT_HOMESERVER_URL = "matrix.org"
const val DEFAULT_HOMESERVER_URL = "https://matrix.org"
const val SLIDING_SYNC_READ_MORE_URL = "https://github.com/matrix-org/sliding-sync/blob/main/docs/Landing.md"
}
val defaultAccountProvider = AccountProvider(
title = LoginConstants.DEFAULT_HOMESERVER_URL,
url = LoginConstants.DEFAULT_HOMESERVER_URL,
subtitle = null,
isPublic = LoginConstants.DEFAULT_HOMESERVER_URL == LoginConstants.MATRIX_ORG_URL,
isMatrixOrg = LoginConstants.DEFAULT_HOMESERVER_URL == LoginConstants.MATRIX_ORG_URL,

4
features/login/impl/src/test/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenterTest.kt

@ -63,7 +63,7 @@ class ChangeServerPresenterTest { @@ -63,7 +63,7 @@ class ChangeServerPresenterTest {
val initialState = awaitItem()
assertThat(initialState.changeServerAction).isEqualTo(Async.Uninitialized)
authenticationService.givenHomeserver(A_HOMESERVER)
initialState.eventSink.invoke(ChangeServerEvents.ChangeServer(AccountProvider(A_HOMESERVER_URL)))
initialState.eventSink.invoke(ChangeServerEvents.ChangeServer(AccountProvider(url = A_HOMESERVER_URL)))
val loadingState = awaitItem()
assertThat(loadingState.changeServerAction).isInstanceOf(Async.Loading::class.java)
val successState = awaitItem()
@ -83,7 +83,7 @@ class ChangeServerPresenterTest { @@ -83,7 +83,7 @@ class ChangeServerPresenterTest {
}.test {
val initialState = awaitItem()
assertThat(initialState.changeServerAction).isEqualTo(Async.Uninitialized)
initialState.eventSink.invoke(ChangeServerEvents.ChangeServer(AccountProvider(A_HOMESERVER_URL)))
initialState.eventSink.invoke(ChangeServerEvents.ChangeServer(AccountProvider(url = A_HOMESERVER_URL)))
val loadingState = awaitItem()
assertThat(loadingState.changeServerAction).isInstanceOf(Async.Loading::class.java)
val failureState = awaitItem()

1
features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderPresenterTest.kt

@ -50,6 +50,7 @@ class ChangeAccountProviderPresenterTest { @@ -50,6 +50,7 @@ class ChangeAccountProviderPresenterTest {
assertThat(initialState.accountProviders).isEqualTo(
listOf(
AccountProvider(
url = "https://matrix.org",
title = "matrix.org",
subtitle = null,
isPublic = true,

2
samples/minimal/src/main/kotlin/io/element/android/samples/minimal/LoginScreen.kt

@ -40,7 +40,7 @@ class LoginScreen(private val authenticationService: MatrixAuthenticationService @@ -40,7 +40,7 @@ class LoginScreen(private val authenticationService: MatrixAuthenticationService
}
LaunchedEffect(Unit) {
authenticationService.setHomeserver(defaultAccountProvider.title)
authenticationService.setHomeserver(defaultAccountProvider.url)
}
val state = presenter.present()

Loading…
Cancel
Save