From f08491cee87367b7680bdf031f4963071de57aba Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 15 Apr 2019 18:59:28 -0600 Subject: [PATCH 01/10] Validate default homeserver config before loading the app Implements the process described here: https://github.com/vector-im/riot-web/issues/9290#issuecomment-481966910 The expectation is that later layers (like the react-sdk) will make use of the `validated_discovery_config` option instead of interpreting the config themselves. We intentionally block the UI from loading here to avoid races between discovery and the app loading. --- README.md | 38 ++++---- config.sample.json | 12 ++- src/i18n/strings/en_EN.json | 7 +- src/vector/index.js | 186 ++++++++++++++++++++++++++++++++---- 4 files changed, 205 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 3fea98150f6..a662b3197dc 100644 --- a/README.md +++ b/README.md @@ -109,25 +109,29 @@ You can configure the app by copying `config.sample.json` to For a good example, see https://riot.im/develop/config.json. -1. `default_server_name` sets the default server name to use for authentication. - This will trigger Riot to ask - `https:///.well-known/matrix/client` for the homeserver and - identity server URLs to use. This is the recommended approach for setting a - default server. However, it is also possible to use the following to directly - configure each of the URLs: - * `default_hs_url` sets the default homeserver URL. - * `default_is_url` sets the default identity server URL (this is the server used - for verifying third party identifiers like email addresses). If this is blank, - registering with an email address, adding an email address to your account, - or inviting users via email address will not work. Matrix identity servers are - very simple web services which map third party identifiers (currently only email - addresses) to matrix IDs: see http://matrix.org/docs/spec/identity_service/unstable.html - for more details. Currently the only public matrix identity servers are https://matrix.org - and https://vector.im. In the future, identity servers will be decentralised. - * Riot will report an error if you accidentally configure both `default_server_name` _and_ `default_hs_url` since it's unclear which should take priority. +1. `default_server_config` sets the default homeserver and identity server URL for + Riot to use. The object is the same as returned by [https:///.well-known/matrix/client](https://matrix.org/docs/spec/client_server/latest.html#get-well-known-matrix-client), + with added support for a `server_name` under the `m.homeserver` section to display + a custom homeserver name. Alternatively, the config can contain a `default_server_name` + instead which is where Riot will go to get that same object - see the `.well-known` + link above for more information. + * *Note*: The URLs can also be individually specified as `default_hs_url` and + `default_is_url`, however these are deprecated. They are maintained for backwards + compatibility with older configurations. `default_is_url` is respected only + if `default_hs_url` is used. + * The identity server is used for verifying third party identifiers like emails + and phone numbers. It is not used to store your password or account information. + If not provided, the identity server defaults to vector.im unless `disable_identity_server` + is set to true in the config. Currently the only two public identity servers + are https://matrix.org and https://vector.im, however in future identity servers + will be decentralised. + * Riot will fail to load if a mix of `default_server_config`, `default_server_name`, or + `default_hs_url` is specified. When multiple sources are specified, it is unclear + which should take priority and therefore the application cannot continue. 1. `features`: Lookup of optional features that may be `enable`d, `disable`d, or exposed to the user in the `labs` section of settings. The available optional experimental features vary from - release to release. + release to release. Some of the available features are described in the Labs Feature section + of this README. 1. `brand`: String to pass to your homeserver when configuring email notifications, to let the homeserver know what email template to use when talking to you. 1. `branding`: Configures various branding and logo details, such as: diff --git a/config.sample.json b/config.sample.json index c1aedee0b19..d4eb8df0522 100644 --- a/config.sample.json +++ b/config.sample.json @@ -1,6 +1,14 @@ { - "default_hs_url": "https://matrix.org", - "default_is_url": "https://vector.im", + "default_server_config": { + "m.homeserver": { + "base_url": "https://matrix.org", + "server_name": "matrix.org" + }, + "m.identity_server": { + "base_url": "https://vector.im" + } + }, + "disable_identity_server": false, "disable_custom_urls": false, "disable_guests": false, "disable_login_language_selector": false, diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 9c467cfc2fa..abb82e8f57c 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1,4 +1,7 @@ { + "Unexpected error preparing the app. See console for details.": "Unexpected error preparing the app. See console for details.", + "Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.", + "Unexpected error resolving homeserver configuration": "Unexpected error resolving homeserver configuration", "Riot Desktop on %(platformName)s": "Riot Desktop on %(platformName)s", "Unknown device": "Unknown device", "%(appName)s via %(browserName)s on %(osName)s": "%(appName)s via %(browserName)s on %(osName)s", @@ -15,7 +18,5 @@ "Need help?": "Need help?", "Chat with Riot Bot": "Chat with Riot Bot", "Explore rooms": "Explore rooms", - "Room Directory": "Room Directory", - "Search the room directory": "Search the room directory", - "Get started with some tips from Riot Bot!": "Get started with some tips from Riot Bot!" + "Room Directory": "Room Directory" } diff --git a/src/vector/index.js b/src/vector/index.js index 9d5c1dd4229..1e8c4b6c7a1 100644 --- a/src/vector/index.js +++ b/src/vector/index.js @@ -45,6 +45,8 @@ import VectorConferenceHandler from 'matrix-react-sdk/lib/VectorConferenceHandle import Promise from 'bluebird'; import request from 'browser-request'; import * as languageHandler from 'matrix-react-sdk/lib/languageHandler'; +import {_t, _td} from 'matrix-react-sdk/lib/languageHandler'; +import {AutoDiscovery} from "matrix-js-sdk/lib/autodiscovery"; import url from 'url'; @@ -341,22 +343,37 @@ async function loadApp() { const platform = PlatformPeg.get(); platform.startUpdater(); - const MatrixChat = sdk.getComponent('structures.MatrixChat'); - window.matrixChat = ReactDOM.render( - , - document.getElementById('matrixchat'), - ); + // Don't bother loading the app until the config is verified + verifyServerConfig().then((newConfig) => { + const MatrixChat = sdk.getComponent('structures.MatrixChat'); + window.matrixChat = ReactDOM.render( + , + document.getElementById('matrixchat'), + ); + }).catch(err => { + console.error(err); + + const errorMessage = err.translatedMessage + || _t("Unexpected error preparing the app. See console for details."); + + // Like the compatibility page, AWOOOOOGA at the user + const GenericErrorPage = sdk.getComponent("structures.GenericErrorPage"); + window.matrixChat = ReactDOM.render( + , + document.getElementById('matrixchat'), + ); + }); } else { console.error("Browser is missing required features."); // take to a different landing page to AWOOOOOGA at the user @@ -428,4 +445,141 @@ async function loadLanguage() { } } +async function verifyServerConfig() { + console.log("Verifying homeserver configuration"); + + // Errors which can be returned by .well-known lookups. If autodiscovery fails for unexpected reasons, + // the last thing we want is "missing-translation|en:Your error here". The actual strings are also defined + // in the react-sdk, so we don't need them here. + const discoveryErrors = [ + "Invalid homeserver discovery response", + "Failed to get autodiscovery configuration from server", + "Invalid base_url for m.homeserver", + "Homeserver URL does not appear to be a valid Matrix homeserver", + "Invalid identity server discovery response", + "Invalid base_url for m.identity_server", + "Identity server URL does not appear to be a valid identity server", + "General failure", + ]; + + const config = SdkConfig.get(); + let wkConfig = config['default_server_config']; // overwritten later under some conditions + const serverName = config['default_server_name']; + const hsUrl = config['default_hs_url']; + const isUrl = config['default_is_url']; + + const incompatibleOptions = [wkConfig, serverName, hsUrl].filter(i => !!i); + if (incompatibleOptions.length > 1) { + throw newTranslatableError(_td( + "Invalid configuration: can only specify one of default_server_config, default_server_name, " + + "or default_hs_url.", + )); + } + + if (hsUrl) { + console.log("Config uses a default_hs_url - constructing a default_server_config using this information"); + + wkConfig = { + "m.homeserver": { + "base_url": hsUrl, + }, + }; + if (isUrl) { + wkConfig["m.identity_server"] = { + "base_url": isUrl, + }; + } + } + + let result = null; + + if (wkConfig) { + console.log("Config uses a default_server_config - validating object"); + result = await AutoDiscovery.fromDiscoveryConfig(wkConfig); + } + + if (serverName) { + console.log("Config uses a default_server_name - doing .well-known lookup"); + result = await AutoDiscovery.findClientConfig(serverName); + } + + if (!result || !result["m.homeserver"]) { + // This shouldn't happen without major misconfiguration, so we'll log a bit of information + // in the log so we can find this bit of codee but otherwise tell teh user "it broke". + console.error("Ended up in a state of not knowing which homeserver to connect to."); + throw newTranslatableError(_td("Unexpected error resolving homeserver configuration")); + } + + const hsResult = result['m.homeserver']; + if (hsResult.state !== AutoDiscovery.SUCCESS) { + if (discoveryErrors.indexOf(hsResult.error) !== -1) { + throw newTranslatableError(hsResult.error); + } + throw newTranslatableError(_td("Unexpected error resolving homeserver configuration")); + } + + const isResult = result['m.identity_server']; + let preferredIdentityUrl = "https://vector.im"; + if (isResult && isResult.state === AutoDiscovery.SUCCESS) { + preferredIdentityUrl = isResult["base_url"]; + } else if (isResult && isResult.state !== AutoDiscovery.PROMPT) { + console.error("Error determining preferred identity server URL:", isResult); + throw newTranslatableError(_td("Unexpected error resolving homeserver configuration")); + } + + const preferredHomeserverUrl = hsResult["base_url"]; + let preferredHomeserverName = serverName ? serverName : hsResult["server_name"]; + + const url = new URL(preferredHomeserverUrl); + if (!preferredHomeserverName) preferredHomeserverName = url.hostname; + + // It should have been set by now, so check it + if (!preferredHomeserverName) { + console.error("Failed to parse homeserver name from homeserver URL"); + throw newTranslatableError(_td("Unexpected error resolving homeserver configuration")); + } + + const isServerNameDifferentFromUrl = url.hostname !== preferredHomeserverName; + + console.log("Using homeserver config:", { + isServerNameDifferentFromUrl, + preferredHomeserverName, + preferredHomeserverUrl, + preferredIdentityUrl, + }); + + // Build our own discovery result for distribution within the app + const configResult = { + "m.homeserver": { + "base_url": preferredHomeserverUrl, + "server_name": preferredHomeserverName, + "server_name_different": isServerNameDifferentFromUrl, + }, + "m.identity_server": { + "base_url": preferredIdentityUrl, + "enabled": !SdkConfig.get()['disable_identity_server'], + }, + }; + + // Copy over any other keys that may be of interest + for (const key of Object.keys(result)) { + if (key === "m.homeserver" || key === "m.identity_server") continue; + configResult[key] = JSON.parse(JSON.stringify(result[key])); // deep clone + } + + // Add the newly built config to the actual config for use by the app + console.log("Updating SdkConfig with validated discovery information"); + SdkConfig.add({"validated_discovery_config": configResult}); + + return SdkConfig.get(); +} + +// Helper function to provide English errors in logs, but present translated +// errors to users. +function newTranslatableError(message) { + const error = new Error(message); + error.translatedMessage = _t(message); + return error; +} + loadApp(); From 54456320266c72bb39cc4ee5acaf0e3b4c8c5418 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 15 Apr 2019 22:06:24 -0600 Subject: [PATCH 02/10] Use new js-sdk properties for getting discovery errors Requires https://github.com/matrix-org/matrix-js-sdk/pull/899 --- src/vector/index.js | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/vector/index.js b/src/vector/index.js index 1e8c4b6c7a1..7ef5838d064 100644 --- a/src/vector/index.js +++ b/src/vector/index.js @@ -448,20 +448,6 @@ async function loadLanguage() { async function verifyServerConfig() { console.log("Verifying homeserver configuration"); - // Errors which can be returned by .well-known lookups. If autodiscovery fails for unexpected reasons, - // the last thing we want is "missing-translation|en:Your error here". The actual strings are also defined - // in the react-sdk, so we don't need them here. - const discoveryErrors = [ - "Invalid homeserver discovery response", - "Failed to get autodiscovery configuration from server", - "Invalid base_url for m.homeserver", - "Homeserver URL does not appear to be a valid Matrix homeserver", - "Invalid identity server discovery response", - "Invalid base_url for m.identity_server", - "Identity server URL does not appear to be a valid identity server", - "General failure", - ]; - const config = SdkConfig.get(); let wkConfig = config['default_server_config']; // overwritten later under some conditions const serverName = config['default_server_name']; @@ -512,7 +498,7 @@ async function verifyServerConfig() { const hsResult = result['m.homeserver']; if (hsResult.state !== AutoDiscovery.SUCCESS) { - if (discoveryErrors.indexOf(hsResult.error) !== -1) { + if (AutoDiscovery.ALL_ERRORS.indexOf(hsResult.error) !== -1) { throw newTranslatableError(hsResult.error); } throw newTranslatableError(_td("Unexpected error resolving homeserver configuration")); From 51941eae49edf4639e59b793c091c3a9513ba854 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 17 Apr 2019 10:28:37 -0600 Subject: [PATCH 03/10] Add note to self --- src/vector/index.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vector/index.js b/src/vector/index.js index 7ef5838d064..1b392abbe2c 100644 --- a/src/vector/index.js +++ b/src/vector/index.js @@ -448,6 +448,9 @@ async function loadLanguage() { async function verifyServerConfig() { console.log("Verifying homeserver configuration"); + // TODO: Handle query string arguments for hs_url and is_url + // We probably don't want to handle them unless the user is logged out though? + const config = SdkConfig.get(); let wkConfig = config['default_server_config']; // overwritten later under some conditions const serverName = config['default_server_name']; From c8caf6797db47bda907695a06503f552c8671273 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 17 Apr 2019 21:31:53 -0600 Subject: [PATCH 04/10] Move bulk of discovery processing to react-sdk --- src/i18n/strings/en_EN.json | 1 - src/vector/index.js | 67 +++++-------------------------------- 2 files changed, 9 insertions(+), 59 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index abb82e8f57c..faf3f392732 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1,7 +1,6 @@ { "Unexpected error preparing the app. See console for details.": "Unexpected error preparing the app. See console for details.", "Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.", - "Unexpected error resolving homeserver configuration": "Unexpected error resolving homeserver configuration", "Riot Desktop on %(platformName)s": "Riot Desktop on %(platformName)s", "Unknown device": "Unknown device", "%(appName)s via %(browserName)s on %(osName)s": "%(appName)s via %(browserName)s on %(osName)s", diff --git a/src/vector/index.js b/src/vector/index.js index 1b392abbe2c..e053f8d8914 100644 --- a/src/vector/index.js +++ b/src/vector/index.js @@ -45,7 +45,8 @@ import VectorConferenceHandler from 'matrix-react-sdk/lib/VectorConferenceHandle import Promise from 'bluebird'; import request from 'browser-request'; import * as languageHandler from 'matrix-react-sdk/lib/languageHandler'; -import {_t, _td} from 'matrix-react-sdk/lib/languageHandler'; +import {_t, _td, newTranslatableError} from 'matrix-react-sdk/lib/languageHandler'; +import AutoDiscoveryUtils from 'matrix-react-sdk/lib/utils/AutoDiscoveryUtils'; import {AutoDiscovery} from "matrix-js-sdk/lib/autodiscovery"; import url from 'url'; @@ -492,61 +493,19 @@ async function verifyServerConfig() { result = await AutoDiscovery.findClientConfig(serverName); } - if (!result || !result["m.homeserver"]) { - // This shouldn't happen without major misconfiguration, so we'll log a bit of information - // in the log so we can find this bit of codee but otherwise tell teh user "it broke". - console.error("Ended up in a state of not knowing which homeserver to connect to."); - throw newTranslatableError(_td("Unexpected error resolving homeserver configuration")); - } - - const hsResult = result['m.homeserver']; - if (hsResult.state !== AutoDiscovery.SUCCESS) { - if (AutoDiscovery.ALL_ERRORS.indexOf(hsResult.error) !== -1) { - throw newTranslatableError(hsResult.error); - } - throw newTranslatableError(_td("Unexpected error resolving homeserver configuration")); - } - - const isResult = result['m.identity_server']; - let preferredIdentityUrl = "https://vector.im"; - if (isResult && isResult.state === AutoDiscovery.SUCCESS) { - preferredIdentityUrl = isResult["base_url"]; - } else if (isResult && isResult.state !== AutoDiscovery.PROMPT) { - console.error("Error determining preferred identity server URL:", isResult); - throw newTranslatableError(_td("Unexpected error resolving homeserver configuration")); - } - - const preferredHomeserverUrl = hsResult["base_url"]; - let preferredHomeserverName = serverName ? serverName : hsResult["server_name"]; - - const url = new URL(preferredHomeserverUrl); - if (!preferredHomeserverName) preferredHomeserverName = url.hostname; - - // It should have been set by now, so check it - if (!preferredHomeserverName) { - console.error("Failed to parse homeserver name from homeserver URL"); - throw newTranslatableError(_td("Unexpected error resolving homeserver configuration")); - } - - const isServerNameDifferentFromUrl = url.hostname !== preferredHomeserverName; - - console.log("Using homeserver config:", { - isServerNameDifferentFromUrl, - preferredHomeserverName, - preferredHomeserverUrl, - preferredIdentityUrl, - }); + const validatedConfig = AutoDiscoveryUtils.buildValidatedConfigFromDiscovery(serverName, result); + console.log("Using homeserver config:", validatedConfig); // Build our own discovery result for distribution within the app const configResult = { "m.homeserver": { - "base_url": preferredHomeserverUrl, - "server_name": preferredHomeserverName, - "server_name_different": isServerNameDifferentFromUrl, + "base_url": validatedConfig.hsUrl, + "server_name": validatedConfig.hsName, + "server_name_different": validatedConfig.hsNameIsDifferent, }, "m.identity_server": { - "base_url": preferredIdentityUrl, - "enabled": !SdkConfig.get()['disable_identity_server'], + "base_url": validatedConfig.isUrl, + "enabled": validatedConfig.identityEnabled, }, }; @@ -563,12 +522,4 @@ async function verifyServerConfig() { return SdkConfig.get(); } -// Helper function to provide English errors in logs, but present translated -// errors to users. -function newTranslatableError(message) { - const error = new Error(message); - error.translatedMessage = _t(message); - return error; -} - loadApp(); From e7bf643d8b18db2f69039b6a87a73bd129d372c0 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 17 Apr 2019 21:44:52 -0600 Subject: [PATCH 05/10] Don't repackage the ValidatedDiscoveryConfig It's usable as-is, and we can add things to it when we need to (ie: integrations). --- src/vector/index.js | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/src/vector/index.js b/src/vector/index.js index e053f8d8914..5fff54602bb 100644 --- a/src/vector/index.js +++ b/src/vector/index.js @@ -494,30 +494,13 @@ async function verifyServerConfig() { } const validatedConfig = AutoDiscoveryUtils.buildValidatedConfigFromDiscovery(serverName, result); - console.log("Using homeserver config:", validatedConfig); - - // Build our own discovery result for distribution within the app - const configResult = { - "m.homeserver": { - "base_url": validatedConfig.hsUrl, - "server_name": validatedConfig.hsName, - "server_name_different": validatedConfig.hsNameIsDifferent, - }, - "m.identity_server": { - "base_url": validatedConfig.isUrl, - "enabled": validatedConfig.identityEnabled, - }, - }; - // Copy over any other keys that may be of interest - for (const key of Object.keys(result)) { - if (key === "m.homeserver" || key === "m.identity_server") continue; - configResult[key] = JSON.parse(JSON.stringify(result[key])); // deep clone - } + // Just in case we ever have to debug this + console.log("Using homeserver config:", validatedConfig); // Add the newly built config to the actual config for use by the app console.log("Updating SdkConfig with validated discovery information"); - SdkConfig.add({"validated_discovery_config": configResult}); + SdkConfig.add({"validated_discovery_config": validatedConfig}); return SdkConfig.get(); } From ab6ba0e0d80c552ebc66945d7cb3f6cc1e075188 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 19 Apr 2019 17:10:56 -0600 Subject: [PATCH 06/10] Add some clarity to the config options --- README.md | 4 +++- src/vector/index.js | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a662b3197dc..29c9d84ef62 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,9 @@ For a good example, see https://riot.im/develop/config.json. with added support for a `server_name` under the `m.homeserver` section to display a custom homeserver name. Alternatively, the config can contain a `default_server_name` instead which is where Riot will go to get that same object - see the `.well-known` - link above for more information. + link above for more information. Note that the `default_server_name` is used to get + a complete server configuration whereas the `server_name` in the `default_server_config` + is for display purposes only. * *Note*: The URLs can also be individually specified as `default_hs_url` and `default_is_url`, however these are deprecated. They are maintained for backwards compatibility with older configurations. `default_is_url` is respected only diff --git a/src/vector/index.js b/src/vector/index.js index 5fff54602bb..2ba91e57fe6 100644 --- a/src/vector/index.js +++ b/src/vector/index.js @@ -500,7 +500,7 @@ async function verifyServerConfig() { // Add the newly built config to the actual config for use by the app console.log("Updating SdkConfig with validated discovery information"); - SdkConfig.add({"validated_discovery_config": validatedConfig}); + SdkConfig.add({"validated_server_config": validatedConfig}); return SdkConfig.get(); } From 45caa8baaba206be9c56014ee7639a42e02cc952 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 1 May 2019 22:35:16 -0600 Subject: [PATCH 07/10] Add a couple notes --- src/vector/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vector/index.js b/src/vector/index.js index 2ba91e57fe6..ed22d37b388 100644 --- a/src/vector/index.js +++ b/src/vector/index.js @@ -449,9 +449,11 @@ async function loadLanguage() { async function verifyServerConfig() { console.log("Verifying homeserver configuration"); - // TODO: Handle query string arguments for hs_url and is_url + // TODO: TravisR - Handle query string arguments for hs_url and is_url // We probably don't want to handle them unless the user is logged out though? + // TODO: TravisR - Handle case of no options specified whatsoever + const config = SdkConfig.get(); let wkConfig = config['default_server_config']; // overwritten later under some conditions const serverName = config['default_server_name']; From bf97fd67b406e09549fbee15866b451933b57087 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 2 May 2019 21:55:54 -0600 Subject: [PATCH 08/10] Handle cases of no default server --- src/i18n/strings/en_EN.json | 1 + src/vector/index.js | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index faf3f392732..e84d87ac0df 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1,6 +1,7 @@ { "Unexpected error preparing the app. See console for details.": "Unexpected error preparing the app. See console for details.", "Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.", + "Invalid configuration: no default server specified": "Invalid configuration: no default server specified", "Riot Desktop on %(platformName)s": "Riot Desktop on %(platformName)s", "Unknown device": "Unknown device", "%(appName)s via %(browserName)s on %(osName)s": "%(appName)s via %(browserName)s on %(osName)s", diff --git a/src/vector/index.js b/src/vector/index.js index ed22d37b388..9c5eb061ac7 100644 --- a/src/vector/index.js +++ b/src/vector/index.js @@ -452,8 +452,6 @@ async function verifyServerConfig() { // TODO: TravisR - Handle query string arguments for hs_url and is_url // We probably don't want to handle them unless the user is logged out though? - // TODO: TravisR - Handle case of no options specified whatsoever - const config = SdkConfig.get(); let wkConfig = config['default_server_config']; // overwritten later under some conditions const serverName = config['default_server_name']; @@ -467,6 +465,9 @@ async function verifyServerConfig() { "or default_hs_url.", )); } + if (incompatibleOptions.length < 1) { + throw newTranslatableError(_td("Invalid configuration: no default server specified.")); + } if (hsUrl) { console.log("Config uses a default_hs_url - constructing a default_server_config using this information"); From a5092dc763bb2bc4edb7fe32a7fa04dfede69c1d Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 3 May 2019 00:11:51 -0600 Subject: [PATCH 09/10] Fix tests to use new server config options --- src/i18n/strings/en_EN.json | 2 +- test/app-tests/joining.js | 12 +++++++++++- test/app-tests/loading.js | 7 +++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index e84d87ac0df..10e57592b73 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1,7 +1,7 @@ { "Unexpected error preparing the app. See console for details.": "Unexpected error preparing the app. See console for details.", "Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.", - "Invalid configuration: no default server specified": "Invalid configuration: no default server specified", + "Invalid configuration: no default server specified.": "Invalid configuration: no default server specified.", "Riot Desktop on %(platformName)s": "Riot Desktop on %(platformName)s", "Unknown device": "Unknown device", "%(appName)s via %(browserName)s on %(osName)s": "%(appName)s via %(browserName)s on %(osName)s", diff --git a/test/app-tests/joining.js b/test/app-tests/joining.js index 16b29fcb843..1661e0e6999 100644 --- a/test/app-tests/joining.js +++ b/test/app-tests/joining.js @@ -96,8 +96,18 @@ describe('joining a room', function() { PlatformPeg.set(new WebPlatform()); + const config = { + validated_server_config: { + hsUrl: HS_URL, + hsName: "TEST_ENVIRONMENT", + hsNameIsDifferent: false, // yes, we lie + isUrl: IS_URL, + identityEnabled: true, + }, + }; + const mc = ( - {throw new Error("unimplemented");}} initialScreenAfterLogin={{ screen: 'directory', diff --git a/test/app-tests/loading.js b/test/app-tests/loading.js index b2df82e6e4e..4199495fe76 100644 --- a/test/app-tests/loading.js +++ b/test/app-tests/loading.js @@ -146,6 +146,13 @@ describe('loading:', function() { const config = Object.assign({ default_hs_url: DEFAULT_HS_URL, default_is_url: DEFAULT_IS_URL, + validated_server_config: { + hsUrl: DEFAULT_HS_URL, + hsName: "TEST_ENVIRONMENT", + hsNameIsDifferent: false, // yes, we lie + isUrl: DEFAULT_IS_URL, + identityEnabled: true, + }, embeddedPages: { homeUrl: 'data:text/html;charset=utf-8;base64,PGh0bWw+PC9odG1sPg==', }, From fc5c93ab5f72b5a9806771428cccf5b4dbfb36f2 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 3 May 2019 16:27:41 -0600 Subject: [PATCH 10/10] Fix unit tests for new login Supply a server config to the component and adjust the wait logic to be less of a race. The Login component will noop onPasswordLogin if it is "busy", and it is busy when it requests the login flows. --- test/app-tests/joining.js | 10 +++++++--- test/app-tests/loading.js | 19 ++++++++++++++++--- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/test/app-tests/joining.js b/test/app-tests/joining.js index 1661e0e6999..f348e8989fe 100644 --- a/test/app-tests/joining.js +++ b/test/app-tests/joining.js @@ -37,6 +37,8 @@ const ReactDOM = require('react-dom'); const ReactTestUtils = require('react-addons-test-utils'); const expect = require('expect'); import Promise from 'bluebird'; +import {makeType} from "matrix-react-sdk/lib/utils/TypeUtils"; +import {ValidatedServerConfig} from "matrix-react-sdk/lib/utils/AutoDiscoveryUtils"; const test_utils = require('../test-utils'); const MockHttpBackend = require('matrix-mock-request'); @@ -97,17 +99,19 @@ describe('joining a room', function() { PlatformPeg.set(new WebPlatform()); const config = { - validated_server_config: { + validated_server_config: makeType(ValidatedServerConfig, { hsUrl: HS_URL, hsName: "TEST_ENVIRONMENT", hsNameIsDifferent: false, // yes, we lie isUrl: IS_URL, identityEnabled: true, - }, + }), }; const mc = ( - {throw new Error("unimplemented");}} initialScreenAfterLogin={{ screen: 'directory', diff --git a/test/app-tests/loading.js b/test/app-tests/loading.js index 4199495fe76..8e7a7807e83 100644 --- a/test/app-tests/loading.js +++ b/test/app-tests/loading.js @@ -39,6 +39,8 @@ import dis from 'matrix-react-sdk/lib/dispatcher'; import * as test_utils from '../test-utils'; import MockHttpBackend from 'matrix-mock-request'; import {parseQs, parseQsFromFragment} from '../../src/vector/url_utils'; +import {makeType} from "matrix-react-sdk/lib/utils/TypeUtils"; +import {ValidatedServerConfig} from "matrix-react-sdk/lib/utils/AutoDiscoveryUtils"; const DEFAULT_HS_URL='http://my_server'; const DEFAULT_IS_URL='http://my_is'; @@ -146,13 +148,13 @@ describe('loading:', function() { const config = Object.assign({ default_hs_url: DEFAULT_HS_URL, default_is_url: DEFAULT_IS_URL, - validated_server_config: { + validated_server_config: makeType(ValidatedServerConfig, { hsUrl: DEFAULT_HS_URL, hsName: "TEST_ENVIRONMENT", hsNameIsDifferent: false, // yes, we lie isUrl: DEFAULT_IS_URL, identityEnabled: true, - }, + }), embeddedPages: { homeUrl: 'data:text/html;charset=utf-8;base64,PGh0bWw+PC9odG1sPg==', }, @@ -167,6 +169,7 @@ describe('loading:', function() { component const login = ReactTestUtils.findRenderedComponentWithType( matrixChat, sdk.getComponent('structures.auth.Login')); + // When we switch to the login component, it'll hit the login endpoint + // for proof of life and to get flows. We'll only give it one option. + httpBackend.when('GET', '/login') + .respond(200, {"flows": [{"type": "m.login.password"}]}); + httpBackend.flush(); // We already would have tried the GET /login request + + // Give the component some time to finish processing the login flows before + // continuing. + await Promise.delay(100); + httpBackend.when('POST', '/login').check(function(req) { expect(req.data.type).toEqual('m.login.password'); expect(req.data.identifier.type).toEqual('m.id.user');