From 8edecf5937980bf51bd2a3298ef2f4e6d897ac91 Mon Sep 17 00:00:00 2001
From: Benoit Marty <benoit@matrix.org>
Date: Mon, 21 Sep 2020 16:03:59 +0200
Subject: [PATCH] Allow using an outdated homeserver, at user's risk (#1972)

Just warn the user using a non blocking popup
---
 CHANGES.md                                    |  1 +
 .../sdk/api/auth/data/LoginFlowResult.kt      |  6 +--
 .../auth/DefaultAuthenticationService.kt      | 18 ++++-----
 .../app/features/login/LoginActivity.kt       |  4 +-
 .../app/features/login/LoginViewModel.kt      | 39 +++++++------------
 .../signout/soft/SoftLogoutViewModel.kt       | 35 +++++------------
 vector/src/main/res/values/strings.xml        |  1 +
 7 files changed, 37 insertions(+), 67 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index 5f61c3569d..7067edbb1b 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -9,6 +9,7 @@ Improvements 🙌:
  - Visually disable call buttons in menu and prohibit calling when permissions are insufficient (#2112)
  - Add a setting to show timestamp for all messages (#2123)
  - Use cache for user color
+ - Allow using an outdated homeserver, at user's risk (#1972)
 
 Bugfix 🐛:
  - Long message cannot be sent/takes infinite time & blocks other messages #1397
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/LoginFlowResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/LoginFlowResult.kt
index c3686da7dd..13693e5bf1 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/LoginFlowResult.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/LoginFlowResult.kt
@@ -17,13 +17,11 @@
 
 package org.matrix.android.sdk.api.auth.data
 
-// Either a list of supported login types, or an error if the homeserver is outdated
 sealed class LoginFlowResult {
     data class Success(
             val supportedLoginTypes: List<String>,
             val isLoginAndRegistrationSupported: Boolean,
-            val homeServerUrl: String
+            val homeServerUrl: String,
+            val isOutdatedHomeserver: Boolean
     ) : LoginFlowResult()
-
-    object OutdatedHomeserver : LoginFlowResult()
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt
index 02c48dab07..3313a3e86f 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt
@@ -273,16 +273,16 @@ internal class DefaultAuthenticationService @Inject constructor(
     }
 
     private suspend fun getLoginFlowResult(authAPI: AuthAPI, versions: Versions, homeServerUrl: String): LoginFlowResult {
-        return if (versions.isSupportedBySdk()) {
-            // Get the login flow
-            val loginFlowResponse = executeRequest<LoginFlowResponse>(null) {
-                apiCall = authAPI.getLoginFlows()
-            }
-            LoginFlowResult.Success(loginFlowResponse.flows.orEmpty().mapNotNull { it.type }, versions.isLoginAndRegistrationSupportedBySdk(), homeServerUrl)
-        } else {
-            // Not supported
-            LoginFlowResult.OutdatedHomeserver
+        // Get the login flow
+        val loginFlowResponse = executeRequest<LoginFlowResponse>(null) {
+            apiCall = authAPI.getLoginFlows()
         }
+        return LoginFlowResult.Success(
+                loginFlowResponse.flows.orEmpty().mapNotNull { it.type },
+                versions.isLoginAndRegistrationSupportedBySdk(),
+                homeServerUrl,
+                !versions.isSupportedBySdk()
+        )
     }
 
     override fun getRegistrationWizard(): RegistrationWizard {
diff --git a/vector/src/main/java/im/vector/app/features/login/LoginActivity.kt b/vector/src/main/java/im/vector/app/features/login/LoginActivity.kt
index da63ca529d..735521fc3c 100644
--- a/vector/src/main/java/im/vector/app/features/login/LoginActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/login/LoginActivity.kt
@@ -42,10 +42,10 @@ import im.vector.app.features.login.terms.LoginTermsFragment
 import im.vector.app.features.login.terms.LoginTermsFragmentArgument
 import im.vector.app.features.login.terms.toLocalizedLoginTerms
 import im.vector.app.features.pin.UnlockedActivity
+import kotlinx.android.synthetic.main.activity_login.*
 import org.matrix.android.sdk.api.auth.registration.FlowResult
 import org.matrix.android.sdk.api.auth.registration.Stage
 import org.matrix.android.sdk.api.extensions.tryOrNull
-import kotlinx.android.synthetic.main.activity_login.*
 import javax.inject.Inject
 
 /**
@@ -127,7 +127,7 @@ open class LoginActivity : VectorBaseActivity(), ToolbarConfigurable, UnlockedAc
             is LoginViewEvents.OutdatedHomeserver                         -> {
                 AlertDialog.Builder(this)
                         .setTitle(R.string.login_error_outdated_homeserver_title)
-                        .setMessage(R.string.login_error_outdated_homeserver_content)
+                        .setMessage(R.string.login_error_outdated_homeserver_warning_content)
                         .setPositiveButton(R.string.ok, null)
                         .show()
                 Unit
diff --git a/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt b/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt
index aed186bcd6..f986227961 100644
--- a/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt
@@ -748,34 +748,21 @@ class LoginViewModel @AssistedInject constructor(
                             else                                                       -> LoginMode.Unsupported
                         }
 
-                        if (loginMode == LoginMode.Password && !data.isLoginAndRegistrationSupported) {
-                            notSupported()
-                        } else {
-                            // FIXME We should post a view event here normally?
-                            setState {
-                                copy(
-                                        asyncHomeServerLoginFlowRequest = Uninitialized,
-                                        homeServerUrl = data.homeServerUrl,
-                                        loginMode = loginMode,
-                                        loginModeSupportedTypes = data.supportedLoginTypes.toList()
-                                )
-                            }
+                        // FIXME We should post a view event here normally?
+                        setState {
+                            copy(
+                                    asyncHomeServerLoginFlowRequest = Uninitialized,
+                                    homeServerUrl = data.homeServerUrl,
+                                    loginMode = loginMode,
+                                    loginModeSupportedTypes = data.supportedLoginTypes.toList()
+                            )
+                        }
+                        if ((loginMode == LoginMode.Password && !data.isLoginAndRegistrationSupported)
+                                || data.isOutdatedHomeserver) {
+                            // Notify the UI
+                            _viewEvents.post(LoginViewEvents.OutdatedHomeserver)
                         }
                     }
-                    is LoginFlowResult.OutdatedHomeserver -> {
-                        notSupported()
-                    }
-                }
-            }
-
-            private fun notSupported() {
-                // Notify the UI
-                _viewEvents.post(LoginViewEvents.OutdatedHomeserver)
-
-                setState {
-                    copy(
-                            asyncHomeServerLoginFlowRequest = Uninitialized
-                    )
                 }
             }
         })
diff --git a/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutViewModel.kt b/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutViewModel.kt
index 94caf70a11..4f6110aab1 100644
--- a/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/signout/soft/SoftLogoutViewModel.kt
@@ -25,16 +25,16 @@ import com.airbnb.mvrx.Uninitialized
 import com.airbnb.mvrx.ViewModelContext
 import com.squareup.inject.assisted.Assisted
 import com.squareup.inject.assisted.AssistedInject
+import im.vector.app.core.di.ActiveSessionHolder
+import im.vector.app.core.extensions.hasUnsavedKeys
+import im.vector.app.core.platform.VectorViewModel
+import im.vector.app.features.login.LoginMode
 import org.matrix.android.sdk.api.MatrixCallback
 import org.matrix.android.sdk.api.auth.AuthenticationService
 import org.matrix.android.sdk.api.auth.data.LoginFlowResult
 import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
 import org.matrix.android.sdk.api.session.Session
 import org.matrix.android.sdk.api.util.Cancelable
-import im.vector.app.core.di.ActiveSessionHolder
-import im.vector.app.core.extensions.hasUnsavedKeys
-import im.vector.app.core.platform.VectorViewModel
-import im.vector.app.features.login.LoginMode
 import timber.log.Timber
 
 /**
@@ -102,7 +102,7 @@ class SoftLogoutViewModel @AssistedInject constructor(
 
             override fun onSuccess(data: LoginFlowResult) {
                 when (data) {
-                    is LoginFlowResult.Success            -> {
+                    is LoginFlowResult.Success -> {
                         val loginMode = when {
                             // SSO login is taken first
                             data.supportedLoginTypes.contains(LoginFlowTypes.SSO)      -> LoginMode.Sso
@@ -110,29 +110,12 @@ class SoftLogoutViewModel @AssistedInject constructor(
                             else                                                       -> LoginMode.Unsupported
                         }
 
-                        if (loginMode == LoginMode.Password && !data.isLoginAndRegistrationSupported) {
-                            notSupported()
-                        } else {
-                            setState {
-                                copy(
-                                        asyncHomeServerLoginFlowRequest = Success(loginMode)
-                                )
-                            }
+                        setState {
+                            copy(
+                                    asyncHomeServerLoginFlowRequest = Success(loginMode)
+                            )
                         }
                     }
-                    is LoginFlowResult.OutdatedHomeserver -> {
-                        notSupported()
-                    }
-                }
-            }
-
-            private fun notSupported() {
-                // Should not happen since it's a re-logout
-                // Notify the UI
-                setState {
-                    copy(
-                            asyncHomeServerLoginFlowRequest = Fail(IllegalStateException("Should not happen"))
-                    )
                 }
             }
         })
diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml
index 3d945f3cfd..61580a66d4 100644
--- a/vector/src/main/res/values/strings.xml
+++ b/vector/src/main/res/values/strings.xml
@@ -1988,6 +1988,7 @@
     <string name="login_validation_code_is_not_correct">The entered code is not correct. Please check.</string>
     <string name="login_error_outdated_homeserver_title">Outdated homeserver</string>
     <string name="login_error_outdated_homeserver_content">This homeserver is running too old a version to connect to. Ask your homeserver admin to upgrade.</string>
+    <string name="login_error_outdated_homeserver_warning_content">This homeserver is running an old version. Ask your homeserver admin to upgrade. You can continue, but some features may not work correctly.</string>
 
     <plurals name="login_error_limit_exceeded_retry_after">
         <item quantity="one">Too many requests have been sent. You can retry in %1$d second…</item>