diff --git a/docs/config.md b/docs/config.md index a3f470fe6e..0666f03ccd 100644 --- a/docs/config.md +++ b/docs/config.md @@ -45,8 +45,9 @@ One of the following options **must** be supplied: information. These are the same values seen as `base_url` in the `default_server_config` example, with `default_is_url` being optional. -If a combination of these three methods is used then Element will fail to load. This is because it is unclear which -should be considered "first". +If both `default_server_config` and `default_server_name` are used, Element will try to look up the connection +infomation using `.well-known`, and if that fails, take `default_server_config` as the homeserver connection +infomation. ## Labs flags diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 0a0634199e..b51d8cc19f 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1,5 +1,5 @@ { - "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: a default_hs_url can't be specified along with default_server_name or default_server_config": "Invalid configuration: a default_hs_url can't be specified along with default_server_name or default_server_config", "Invalid configuration: no default server specified.": "Invalid configuration: no default server specified.", "Your Element is misconfigured": "Your Element is misconfigured", "Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "Your Element configuration contains invalid JSON. Please correct the problem and reload the page.", diff --git a/src/vector/app.tsx b/src/vector/app.tsx index 7371ccf0f0..05f1cd5b85 100644 --- a/src/vector/app.tsx +++ b/src/vector/app.tsx @@ -169,11 +169,11 @@ async function verifyServerConfig(): Promise { const isUrl = config["default_is_url"]; const incompatibleOptions = [wkConfig, serverName, hsUrl].filter((i) => !!i); - if (incompatibleOptions.length > 1) { + if (hsUrl && (wkConfig || serverName)) { // noinspection ExceptionCaughtLocallyJS throw new UserFriendlyError( - "Invalid configuration: can only specify one of default_server_config, default_server_name, " + - "or default_hs_url.", + "Invalid configuration: a default_hs_url can't be specified along with default_server_name " + + "or default_server_config", ); } if (incompatibleOptions.length < 1) { @@ -201,7 +201,7 @@ async function verifyServerConfig(): Promise { } let discoveryResult: ClientConfig | undefined; - if (wkConfig) { + if (!serverName && wkConfig) { logger.log("Config uses a default_server_config - validating object"); discoveryResult = await AutoDiscovery.fromDiscoveryConfig(wkConfig); } @@ -213,6 +213,10 @@ async function verifyServerConfig(): Promise { "use default_server_config instead.", ); discoveryResult = await AutoDiscovery.findClientConfig(serverName); + if (discoveryResult["m.homeserver"].base_url === null && wkConfig) { + logger.log("Finding base_url failed but a default_server_config was found - using it as a fallback"); + discoveryResult = await AutoDiscovery.fromDiscoveryConfig(wkConfig); + } } validatedConfig = AutoDiscoveryUtils.buildValidatedConfigFromDiscovery(serverName, discoveryResult, true); diff --git a/src/vector/mobile_guide/index.ts b/src/vector/mobile_guide/index.ts index 5f93440748..7c14a25867 100644 --- a/src/vector/mobile_guide/index.ts +++ b/src/vector/mobile_guide/index.ts @@ -44,10 +44,10 @@ async function initPage(): Promise { const defaultIsUrl = config?.["default_is_url"]; const incompatibleOptions = [wkConfig, serverName, defaultHsUrl].filter((i) => !!i); - if (incompatibleOptions.length > 1) { + if (defaultHsUrl && (wkConfig || serverName)) { return renderConfigError( - "Invalid configuration: can only specify one of default_server_config, default_server_name, " + - "or default_hs_url.", + "Invalid configuration: a default_hs_url can't be specified along with default_server_name " + + "or default_server_config", ); } if (incompatibleOptions.length < 1) { @@ -57,7 +57,7 @@ async function initPage(): Promise { let hsUrl: string | undefined; let isUrl: string | undefined; - if (typeof wkConfig?.["m.homeserver"]?.["base_url"] === "string") { + if (!serverName && typeof wkConfig?.["m.homeserver"]?.["base_url"] === "string") { hsUrl = wkConfig["m.homeserver"]["base_url"]; if (typeof wkConfig["m.identity_server"]?.["base_url"] === "string") { @@ -78,8 +78,16 @@ async function initPage(): Promise { } } } catch (e) { - logger.error(e); - return renderConfigError("Unable to fetch homeserver configuration"); + if (wkConfig && wkConfig["m.homeserver"]) { + hsUrl = wkConfig["m.homeserver"]["base_url"] || undefined; + + if (wkConfig["m.identity_server"]) { + isUrl = wkConfig["m.identity_server"]["base_url"] || undefined; + } + } else { + logger.error(e); + return renderConfigError("Unable to fetch homeserver configuration"); + } } } diff --git a/test/app-tests/server-config-test.ts b/test/app-tests/server-config-test.ts new file mode 100644 index 0000000000..22b8304458 --- /dev/null +++ b/test/app-tests/server-config-test.ts @@ -0,0 +1,79 @@ +/* +Copyright 2023 Yorusaka Miyabi + +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. +*/ + +import SdkConfig from "matrix-react-sdk/src/SdkConfig"; +import PlatformPeg from "matrix-react-sdk/src/PlatformPeg"; +import fetchMock from "fetch-mock-jest"; + +import { loadApp } from "../../src/vector/app"; +import WebPlatform from "../../src/vector/platform/WebPlatform"; + +fetchMock.config.overwriteRoutes = true; + +describe("Loading server config", function () { + beforeEach(async () => { + SdkConfig.reset(); + PlatformPeg.set(new WebPlatform()); + fetchMock.get("https://matrix-client.matrix.org/_matrix/client/versions", { + unstable_features: {}, + versions: [], + }); + fetchMock.get("https://matrix.org/.well-known/matrix/client", { + "m.homeserver": { + base_url: "https://matrix-client.matrix.org", + }, + }); + fetchMock.get("/version", "1.10.13"); + }); + + it("should use the default_server_config", async function () { + SdkConfig.put({ + default_server_config: { + "m.homeserver": { + base_url: "https://matrix-client.matrix.org", + }, + }, + }); + await loadApp({}); + expect((SdkConfig.get("validated_server_config") || {}).hsUrl).toBe("https://matrix-client.matrix.org"); + }); + + it("should use the default_server_name when resolveable", async function () { + SdkConfig.put({ + default_server_name: "matrix.org", + }); + await loadApp({}); + expect((SdkConfig.get("validated_server_config") || {}).hsUrl).toBe("https://matrix-client.matrix.org"); + }); + + it( + "should not throw when both default_server_name and default_server_config is specified " + + "and default_server_name isn't resolvable", + async function () { + fetchMock.get("https://matrix.org/.well-known/matrix/client", 500); + SdkConfig.put({ + default_server_name: "matrix.org", + default_server_config: { + "m.homeserver": { + base_url: "https://matrix-client.matrix.org", + }, + }, + }); + await loadApp({}); + expect((SdkConfig.get("validated_server_config") || {}).hsUrl).toBe("https://matrix-client.matrix.org"); + }, + ); +});