mirror of
https://github.com/element-hq/element-web
synced 2024-11-25 02:35:48 +03:00
Support homeserver-configured integration managers
Fixes https://github.com/vector-im/riot-web/issues/4913 Requires https://github.com/matrix-org/matrix-js-sdk/pull/1024 Implements part of [MSC1957](https://github.com/matrix-org/matrix-doc/pull/1957)
This commit is contained in:
parent
efe8254985
commit
a35735da45
2 changed files with 71 additions and 3 deletions
|
@ -23,11 +23,13 @@ import url from 'url';
|
||||||
|
|
||||||
export const KIND_ACCOUNT = "account";
|
export const KIND_ACCOUNT = "account";
|
||||||
export const KIND_CONFIG = "config";
|
export const KIND_CONFIG = "config";
|
||||||
|
export const KIND_HOMESERVER = "homeserver";
|
||||||
|
|
||||||
export class IntegrationManagerInstance {
|
export class IntegrationManagerInstance {
|
||||||
apiUrl: string;
|
apiUrl: string;
|
||||||
uiUrl: string;
|
uiUrl: string;
|
||||||
kind: string;
|
kind: string;
|
||||||
|
id: string; // only applicable in some cases
|
||||||
|
|
||||||
constructor(kind: string, apiUrl: string, uiUrl: string) {
|
constructor(kind: string, apiUrl: string, uiUrl: string) {
|
||||||
this.kind = kind;
|
this.kind = kind;
|
||||||
|
|
|
@ -17,10 +17,19 @@ limitations under the License.
|
||||||
import SdkConfig from '../SdkConfig';
|
import SdkConfig from '../SdkConfig';
|
||||||
import sdk from "../index";
|
import sdk from "../index";
|
||||||
import Modal from '../Modal';
|
import Modal from '../Modal';
|
||||||
import {IntegrationManagerInstance, KIND_ACCOUNT, KIND_CONFIG} from "./IntegrationManagerInstance";
|
import {IntegrationManagerInstance, KIND_ACCOUNT, KIND_CONFIG, KIND_HOMESERVER} from "./IntegrationManagerInstance";
|
||||||
import type {MatrixClient, MatrixEvent} from "matrix-js-sdk";
|
import type {MatrixClient, MatrixEvent} from "matrix-js-sdk";
|
||||||
import WidgetUtils from "../utils/WidgetUtils";
|
import WidgetUtils from "../utils/WidgetUtils";
|
||||||
import MatrixClientPeg from "../MatrixClientPeg";
|
import MatrixClientPeg from "../MatrixClientPeg";
|
||||||
|
import {AutoDiscovery} from "../../../matrix-js-sdk";
|
||||||
|
|
||||||
|
const HS_MANAGERS_REFRESH_INTERVAL = 8 * 60 * 60 * 1000; // 8 hours
|
||||||
|
const KIND_PREFERENCE = [
|
||||||
|
// Ordered: first is most preferred, last is least preferred.
|
||||||
|
KIND_ACCOUNT,
|
||||||
|
KIND_HOMESERVER,
|
||||||
|
KIND_CONFIG,
|
||||||
|
];
|
||||||
|
|
||||||
export class IntegrationManagers {
|
export class IntegrationManagers {
|
||||||
static _instance;
|
static _instance;
|
||||||
|
@ -34,6 +43,8 @@ export class IntegrationManagers {
|
||||||
|
|
||||||
_managers: IntegrationManagerInstance[] = [];
|
_managers: IntegrationManagerInstance[] = [];
|
||||||
_client: MatrixClient;
|
_client: MatrixClient;
|
||||||
|
_wellknownRefreshTimerId: number = null;
|
||||||
|
_primaryManager: IntegrationManagerInstance;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this._compileManagers();
|
this._compileManagers();
|
||||||
|
@ -44,16 +55,19 @@ export class IntegrationManagers {
|
||||||
this._client = MatrixClientPeg.get();
|
this._client = MatrixClientPeg.get();
|
||||||
this._client.on("accountData", this._onAccountData.bind(this));
|
this._client.on("accountData", this._onAccountData.bind(this));
|
||||||
this._compileManagers();
|
this._compileManagers();
|
||||||
|
setInterval(() => this._setupHomeserverManagers(), HS_MANAGERS_REFRESH_INTERVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
stopWatching(): void {
|
stopWatching(): void {
|
||||||
if (!this._client) return;
|
if (!this._client) return;
|
||||||
this._client.removeListener("accountData", this._onAccountData.bind(this));
|
this._client.removeListener("accountData", this._onAccountData.bind(this));
|
||||||
|
if (this._wellknownRefreshTimerId !== null) clearInterval(this._wellknownRefreshTimerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
_compileManagers() {
|
_compileManagers() {
|
||||||
this._managers = [];
|
this._managers = [];
|
||||||
this._setupConfiguredManager();
|
this._setupConfiguredManager();
|
||||||
|
this._setupHomeserverManagers();
|
||||||
this._setupAccountManagers();
|
this._setupAccountManagers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,6 +77,42 @@ export class IntegrationManagers {
|
||||||
|
|
||||||
if (apiUrl && uiUrl) {
|
if (apiUrl && uiUrl) {
|
||||||
this._managers.push(new IntegrationManagerInstance(KIND_CONFIG, apiUrl, uiUrl));
|
this._managers.push(new IntegrationManagerInstance(KIND_CONFIG, apiUrl, uiUrl));
|
||||||
|
this._primaryManager = null; // reset primary
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async _setupHomeserverManagers() {
|
||||||
|
try {
|
||||||
|
console.log("Updating homeserver-configured integration managers...");
|
||||||
|
const homeserverDomain = MatrixClientPeg.getHomeserverName();
|
||||||
|
const discoveryResponse = await AutoDiscovery.getRawClientConfig(homeserverDomain);
|
||||||
|
if (discoveryResponse && discoveryResponse['m.integrations']) {
|
||||||
|
let managers = discoveryResponse['m.integrations']['managers'];
|
||||||
|
if (!Array.isArray(managers)) managers = []; // make it an array so we can wipe the HS managers
|
||||||
|
|
||||||
|
console.log(`Homeserver has ${managers.length} integration managers`);
|
||||||
|
|
||||||
|
// Clear out any known managers for the homeserver
|
||||||
|
// TODO: Log out of the scalar clients
|
||||||
|
this._managers = this._managers.filter(m => m.kind !== KIND_HOMESERVER);
|
||||||
|
|
||||||
|
// Now add all the managers the homeserver wants us to have
|
||||||
|
for (const hsManager of managers) {
|
||||||
|
if (!hsManager["api_url"]) continue;
|
||||||
|
this._managers.push(new IntegrationManagerInstance(
|
||||||
|
KIND_HOMESERVER,
|
||||||
|
hsManager["api_url"],
|
||||||
|
hsManager["ui_url"], // optional
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
this._primaryManager = null; // reset primary
|
||||||
|
} else {
|
||||||
|
console.log("Homeserver has no integration managers");
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
// Errors during discovery are non-fatal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,8 +127,11 @@ export class IntegrationManagers {
|
||||||
const apiUrl = data['api_url'];
|
const apiUrl = data['api_url'];
|
||||||
if (!apiUrl || !uiUrl) return;
|
if (!apiUrl || !uiUrl) return;
|
||||||
|
|
||||||
this._managers.push(new IntegrationManagerInstance(KIND_ACCOUNT, apiUrl, uiUrl));
|
const manager = new IntegrationManagerInstance(KIND_ACCOUNT, apiUrl, uiUrl);
|
||||||
|
manager.id = w['id'] || w['state_key'] || '';
|
||||||
|
this._managers.push(manager);
|
||||||
});
|
});
|
||||||
|
this._primaryManager = null; // reset primary
|
||||||
}
|
}
|
||||||
|
|
||||||
_onAccountData(ev: MatrixEvent): void {
|
_onAccountData(ev: MatrixEvent): void {
|
||||||
|
@ -93,7 +146,20 @@ export class IntegrationManagers {
|
||||||
|
|
||||||
getPrimaryManager(): IntegrationManagerInstance {
|
getPrimaryManager(): IntegrationManagerInstance {
|
||||||
if (this.hasManager()) {
|
if (this.hasManager()) {
|
||||||
return this._managers[this._managers.length - 1];
|
if (this._primaryManager) return this._primaryManager;
|
||||||
|
|
||||||
|
for (const kind of KIND_PREFERENCE) {
|
||||||
|
const managers = this._managers.filter(m => m.kind === kind);
|
||||||
|
if (!managers || !managers.length) continue;
|
||||||
|
|
||||||
|
if (kind === KIND_ACCOUNT) {
|
||||||
|
// Order by state_keys (IDs)
|
||||||
|
managers.sort((a, b) => a.id.localeCompare(b.id));
|
||||||
|
}
|
||||||
|
|
||||||
|
this._primaryManager = managers[0];
|
||||||
|
return this._primaryManager;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue