Fail more softly on homeserver liveliness errors
This performs liveliness checks on the auth pages to try and show a friendlier error. Earlier checks in the app startup are expected to not block the app from loading on such failures. See https://github.com/vector-im/riot-web/issues/9828
This commit is contained in:
parent
b412103f21
commit
e2fdeec71a
8 changed files with 257 additions and 33 deletions
|
@ -15,10 +15,15 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import {AutoDiscovery} from "matrix-js-sdk";
|
||||
import {_td, newTranslatableError} from "../languageHandler";
|
||||
import {_t, _td, newTranslatableError} from "../languageHandler";
|
||||
import {makeType} from "./TypeUtils";
|
||||
import SdkConfig from "../SdkConfig";
|
||||
|
||||
const LIVLINESS_DISCOVERY_ERRORS = [
|
||||
AutoDiscovery.ERROR_INVALID_HOMESERVER,
|
||||
AutoDiscovery.ERROR_INVALID_IDENTITY_SERVER,
|
||||
];
|
||||
|
||||
export class ValidatedServerConfig {
|
||||
hsUrl: string;
|
||||
hsName: string;
|
||||
|
@ -31,7 +36,52 @@ export class ValidatedServerConfig {
|
|||
}
|
||||
|
||||
export default class AutoDiscoveryUtils {
|
||||
static async validateServerConfigWithStaticUrls(homeserverUrl: string, identityUrl: string): ValidatedServerConfig {
|
||||
/**
|
||||
* Checks if a given error or error message is considered an error
|
||||
* relating to the liveliness of the server. Must be an error returned
|
||||
* from this AutoDiscoveryUtils class.
|
||||
* @param {string|Error} error The error to check
|
||||
* @returns {boolean} True if the error is a liveliness error.
|
||||
*/
|
||||
static isLivelinessError(error: string|Error): boolean {
|
||||
if (!error) return false;
|
||||
return !!LIVLINESS_DISCOVERY_ERRORS.find(e => e === error || e === error.message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the common state for auth components (login, registration, forgot
|
||||
* password) for a given validation error.
|
||||
* @param {Error} err The error encountered.
|
||||
* @returns {{serverDeadError: (string|*), serverIsAlive: boolean}} The state
|
||||
* for the component, given the error.
|
||||
*/
|
||||
static authComponentStateForError(err: Error): {serverIsAlive: boolean, serverDeadError: string} {
|
||||
if (AutoDiscoveryUtils.isLivelinessError(err)) {
|
||||
// TODO: TravisR - Copy from Nad
|
||||
return {
|
||||
serverIsAlive: false,
|
||||
serverDeadError: _t("Server failed liveliness check"),
|
||||
};
|
||||
} else {
|
||||
// TODO: TravisR - Copy from Nad
|
||||
return {
|
||||
serverIsAlive: false,
|
||||
serverDeadError: _t("Server failed syntax check"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a server configuration, using a pair of URLs as input.
|
||||
* @param {string} homeserverUrl The homeserver URL.
|
||||
* @param {string} identityUrl The identity server URL.
|
||||
* @param {boolean} syntaxOnly If true, errors relating to liveliness of the servers will
|
||||
* not be raised.
|
||||
* @returns {Promise<ValidatedServerConfig>} Resolves to the validated configuration.
|
||||
*/
|
||||
static async validateServerConfigWithStaticUrls(
|
||||
homeserverUrl: string, identityUrl: string, syntaxOnly = false): ValidatedServerConfig {
|
||||
|
||||
if (!homeserverUrl) {
|
||||
throw newTranslatableError(_td("No homeserver URL provided"));
|
||||
}
|
||||
|
@ -50,15 +100,33 @@ export default class AutoDiscoveryUtils {
|
|||
const url = new URL(homeserverUrl);
|
||||
const serverName = url.hostname;
|
||||
|
||||
return AutoDiscoveryUtils.buildValidatedConfigFromDiscovery(serverName, result);
|
||||
return AutoDiscoveryUtils.buildValidatedConfigFromDiscovery(serverName, result, syntaxOnly);
|
||||
}
|
||||
|
||||
static async validateServerName(serverName: string): ValidatedServerConfig {
|
||||
/**
|
||||
* Validates a server configuration, using a homeserver domain name as input.
|
||||
* @param {string} serverName The homeserver domain name (eg: "matrix.org") to validate.
|
||||
* @param {boolean} syntaxOnly If true, errors relating to liveliness of the servers will
|
||||
* not be raised.
|
||||
* @returns {Promise<ValidatedServerConfig>} Resolves to the validated configuration.
|
||||
*/
|
||||
static async validateServerName(serverName: string, syntaxOnly=false): ValidatedServerConfig {
|
||||
const result = await AutoDiscovery.findClientConfig(serverName);
|
||||
return AutoDiscoveryUtils.buildValidatedConfigFromDiscovery(serverName, result);
|
||||
}
|
||||
|
||||
static buildValidatedConfigFromDiscovery(serverName: string, discoveryResult): ValidatedServerConfig {
|
||||
/**
|
||||
* Validates a server configuration, using a pre-calculated AutoDiscovery result as
|
||||
* input.
|
||||
* @param {string} serverName The domain name the AutoDiscovery result is for.
|
||||
* @param {*} discoveryResult The AutoDiscovery result.
|
||||
* @param {boolean} syntaxOnly If true, errors relating to liveliness of the servers will
|
||||
* not be raised.
|
||||
* @returns {Promise<ValidatedServerConfig>} Resolves to the validated configuration.
|
||||
*/
|
||||
static buildValidatedConfigFromDiscovery(
|
||||
serverName: string, discoveryResult, syntaxOnly=false): ValidatedServerConfig {
|
||||
|
||||
if (!discoveryResult || !discoveryResult["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".
|
||||
|
@ -68,19 +136,27 @@ export default class AutoDiscoveryUtils {
|
|||
|
||||
const hsResult = discoveryResult['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"));
|
||||
console.error("Error processing homeserver config:", hsResult);
|
||||
if (!syntaxOnly || !AutoDiscoveryUtils.isLivelinessError(hsResult.error)) {
|
||||
if (AutoDiscovery.ALL_ERRORS.indexOf(hsResult.error) !== -1) {
|
||||
throw newTranslatableError(hsResult.error);
|
||||
}
|
||||
throw newTranslatableError(_td("Unexpected error resolving homeserver configuration"));
|
||||
} // else the error is not related to syntax - continue anyways.
|
||||
}
|
||||
|
||||
const isResult = discoveryResult['m.identity_server'];
|
||||
let preferredIdentityUrl = "https://vector.im";
|
||||
let preferredIdentityUrl = "https://vector.im"; // We already know this is an IS, so don't validate it.
|
||||
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"));
|
||||
if (!syntaxOnly || !AutoDiscoveryUtils.isLivelinessError(isResult.error)) {
|
||||
if (AutoDiscovery.ALL_ERRORS.indexOf(isResult.error) !== -1) {
|
||||
throw newTranslatableError(isResult.error);
|
||||
}
|
||||
throw newTranslatableError(_td("Unexpected error resolving identity server configuration"));
|
||||
} // else the error is not related to syntax - continue anyways.
|
||||
}
|
||||
|
||||
const preferredHomeserverUrl = hsResult["base_url"];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue