Fail to start when widgets are configured without a listener (#298)

* Add note about listener configuration in widgets.md

* Add errors to check when widgets are not fully configured

* changelog

* Include widget listener in default config
This commit is contained in:
Will Hunt 2022-04-11 18:39:42 +01:00 committed by GitHub
parent 93d367375a
commit e1b5f989b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 37 additions and 4 deletions

1
changelog.d/298.misc Normal file
View File

@ -0,0 +1 @@
Fail to start when widgets are configured but no "widgets" listener is configured.

View File

@ -155,4 +155,8 @@ listeners:
resources:
- metrics
- provisioning
- port: 9002
bindAddress: 0.0.0.0
resources:
- widgets

View File

@ -60,6 +60,17 @@ Unless you know what you are doing, it is recommended to not include this key. T
`branding` allows you to change the strings used for various bits of widget UI. At the moment you can:
- Set `widgetTitle` to change the title of the widget that is created.
In addition to setting up the widgets config, you must bind a listener for the widgets resource in your `listeners` config.
```yaml
listeners:
- port: 5069
bindAddress: 0.0.0.0
resources:
- widgets
```
See the [setup page](../setup#listeners-configuration) for more information on listeners.
### API

View File

@ -7,6 +7,7 @@ import { BridgeConfigListener, ResourceTypeArray } from "../ListenerService";
import { GitHubRepoConnectionOptions } from "../Connections/GithubRepo";
import { BridgeConfigActorPermission, BridgePermissions } from "../libRs";
import LogWrapper from "../LogWrapper";
import { ConfigError } from "../errors";
const log = new LogWrapper("Config");
@ -187,7 +188,7 @@ export class BridgeConfigGenericWebhooks {
public readonly waitForComplete?: boolean;
constructor(yaml: BridgeGenericWebhooksConfigYAML) {
if (typeof yaml.urlPrefix !== "string") {
throw Error('urlPrefix is not defined or not a string');
throw new ConfigError("generic.urlPrefix", "is not defined or not a string");
}
this.enabled = yaml.enabled || false;
this.urlPrefix = yaml.urlPrefix;
@ -235,10 +236,10 @@ export class BridgeWidgetConfig {
this.disallowedIpRanges = yaml.disallowedIpRanges;
this.roomSetupWidget = yaml.roomSetupWidget;
if (yaml.disallowedIpRanges !== undefined && (!Array.isArray(yaml.disallowedIpRanges) || !yaml.disallowedIpRanges.every(s => typeof s === "string"))) {
throw Error('disallowedIpRanges must be a string array');
throw new ConfigError("widgets.disallowedIpRanges", "must be a string array");
}
if (typeof yaml.publicUrl !== "string") {
throw Error('publicUrl is not defined or not a string');
throw new ConfigError("widgets.publicUrl", "is not defined or not a string");
}
this.publicUrl = yaml.publicUrl;
this.branding = yaml.branding || {
@ -389,7 +390,7 @@ export class BridgeConfig {
// To allow DEBUG as well as debug
this.logging.level = this.logging.level.toLowerCase() as "debug"|"info"|"warn"|"error"|"trace";
if (!ValidLogLevelStrings.includes(this.logging.level)) {
throw Error(`'logging.level' is not valid. Must be one of ${ValidLogLevelStrings.join(', ')}`)
throw new ConfigError("logging.level", `Logging level is not valid. Must be one of ${ValidLogLevelStrings.join(', ')}`)
}
this.permissions = configData.permissions || [{
@ -461,6 +462,11 @@ export class BridgeConfig {
});
log.warn("The `widgets` configuration still specifies a port/bindAddress. This should be moved to the `listeners` config.");
}
const hasWidgetListener = !!this.listeners.find(l => l.resources.includes('widgets'));
if (this.widgets && !hasWidgetListener) {
throw new ConfigError(`listeners`, "You have enabled the widgets feature, but not included a widgets listener.");
}
}
public async prefillMembershipCache(client: MatrixClient) {

View File

@ -120,6 +120,11 @@ export const DefaultConfig = new BridgeConfig({
port: 9001,
bindAddress: '127.0.0.1',
resources: ['metrics', 'provisioning'],
},
{
port: 9002,
bindAddress: '0.0.0.0',
resources: ['widgets'],
}
]
}, {});

View File

@ -8,4 +8,10 @@ export class NotLoggedInError extends CommandError {
constructor() {
super("User is not logged in", "You are not logged in");
}
}
export class ConfigError extends Error {
constructor(public readonly configPath: string, public readonly msg?: string) {
super(`There was an error in the config (${configPath}): ${msg}`);
}
}