Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit a35735d

Browse files
committed
Support homeserver-configured integration managers
Fixes element-hq/element-web#4913 Requires matrix-org/matrix-js-sdk#1024 Implements part of [MSC1957](matrix-org/matrix-spec-proposals#1957)
1 parent efe8254 commit a35735d

File tree

2 files changed

+71
-3
lines changed

2 files changed

+71
-3
lines changed

src/integrations/IntegrationManagerInstance.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,13 @@ import url from 'url';
2323

2424
export const KIND_ACCOUNT = "account";
2525
export const KIND_CONFIG = "config";
26+
export const KIND_HOMESERVER = "homeserver";
2627

2728
export class IntegrationManagerInstance {
2829
apiUrl: string;
2930
uiUrl: string;
3031
kind: string;
32+
id: string; // only applicable in some cases
3133

3234
constructor(kind: string, apiUrl: string, uiUrl: string) {
3335
this.kind = kind;

src/integrations/IntegrationManagers.js

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,19 @@ limitations under the License.
1717
import SdkConfig from '../SdkConfig';
1818
import sdk from "../index";
1919
import Modal from '../Modal';
20-
import {IntegrationManagerInstance, KIND_ACCOUNT, KIND_CONFIG} from "./IntegrationManagerInstance";
20+
import {IntegrationManagerInstance, KIND_ACCOUNT, KIND_CONFIG, KIND_HOMESERVER} from "./IntegrationManagerInstance";
2121
import type {MatrixClient, MatrixEvent} from "matrix-js-sdk";
2222
import WidgetUtils from "../utils/WidgetUtils";
2323
import MatrixClientPeg from "../MatrixClientPeg";
24+
import {AutoDiscovery} from "../../../matrix-js-sdk";
25+
26+
const HS_MANAGERS_REFRESH_INTERVAL = 8 * 60 * 60 * 1000; // 8 hours
27+
const KIND_PREFERENCE = [
28+
// Ordered: first is most preferred, last is least preferred.
29+
KIND_ACCOUNT,
30+
KIND_HOMESERVER,
31+
KIND_CONFIG,
32+
];
2433

2534
export class IntegrationManagers {
2635
static _instance;
@@ -34,6 +43,8 @@ export class IntegrationManagers {
3443

3544
_managers: IntegrationManagerInstance[] = [];
3645
_client: MatrixClient;
46+
_wellknownRefreshTimerId: number = null;
47+
_primaryManager: IntegrationManagerInstance;
3748

3849
constructor() {
3950
this._compileManagers();
@@ -44,16 +55,19 @@ export class IntegrationManagers {
4455
this._client = MatrixClientPeg.get();
4556
this._client.on("accountData", this._onAccountData.bind(this));
4657
this._compileManagers();
58+
setInterval(() => this._setupHomeserverManagers(), HS_MANAGERS_REFRESH_INTERVAL);
4759
}
4860

4961
stopWatching(): void {
5062
if (!this._client) return;
5163
this._client.removeListener("accountData", this._onAccountData.bind(this));
64+
if (this._wellknownRefreshTimerId !== null) clearInterval(this._wellknownRefreshTimerId);
5265
}
5366

5467
_compileManagers() {
5568
this._managers = [];
5669
this._setupConfiguredManager();
70+
this._setupHomeserverManagers();
5771
this._setupAccountManagers();
5872
}
5973

@@ -63,6 +77,42 @@ export class IntegrationManagers {
6377

6478
if (apiUrl && uiUrl) {
6579
this._managers.push(new IntegrationManagerInstance(KIND_CONFIG, apiUrl, uiUrl));
80+
this._primaryManager = null; // reset primary
81+
}
82+
}
83+
84+
async _setupHomeserverManagers() {
85+
try {
86+
console.log("Updating homeserver-configured integration managers...");
87+
const homeserverDomain = MatrixClientPeg.getHomeserverName();
88+
const discoveryResponse = await AutoDiscovery.getRawClientConfig(homeserverDomain);
89+
if (discoveryResponse && discoveryResponse['m.integrations']) {
90+
let managers = discoveryResponse['m.integrations']['managers'];
91+
if (!Array.isArray(managers)) managers = []; // make it an array so we can wipe the HS managers
92+
93+
console.log(`Homeserver has ${managers.length} integration managers`);
94+
95+
// Clear out any known managers for the homeserver
96+
// TODO: Log out of the scalar clients
97+
this._managers = this._managers.filter(m => m.kind !== KIND_HOMESERVER);
98+
99+
// Now add all the managers the homeserver wants us to have
100+
for (const hsManager of managers) {
101+
if (!hsManager["api_url"]) continue;
102+
this._managers.push(new IntegrationManagerInstance(
103+
KIND_HOMESERVER,
104+
hsManager["api_url"],
105+
hsManager["ui_url"], // optional
106+
));
107+
}
108+
109+
this._primaryManager = null; // reset primary
110+
} else {
111+
console.log("Homeserver has no integration managers");
112+
}
113+
} catch (e) {
114+
console.error(e);
115+
// Errors during discovery are non-fatal
66116
}
67117
}
68118

@@ -77,8 +127,11 @@ export class IntegrationManagers {
77127
const apiUrl = data['api_url'];
78128
if (!apiUrl || !uiUrl) return;
79129

80-
this._managers.push(new IntegrationManagerInstance(KIND_ACCOUNT, apiUrl, uiUrl));
130+
const manager = new IntegrationManagerInstance(KIND_ACCOUNT, apiUrl, uiUrl);
131+
manager.id = w['id'] || w['state_key'] || '';
132+
this._managers.push(manager);
81133
});
134+
this._primaryManager = null; // reset primary
82135
}
83136

84137
_onAccountData(ev: MatrixEvent): void {
@@ -93,7 +146,20 @@ export class IntegrationManagers {
93146

94147
getPrimaryManager(): IntegrationManagerInstance {
95148
if (this.hasManager()) {
96-
return this._managers[this._managers.length - 1];
149+
if (this._primaryManager) return this._primaryManager;
150+
151+
for (const kind of KIND_PREFERENCE) {
152+
const managers = this._managers.filter(m => m.kind === kind);
153+
if (!managers || !managers.length) continue;
154+
155+
if (kind === KIND_ACCOUNT) {
156+
// Order by state_keys (IDs)
157+
managers.sort((a, b) => a.id.localeCompare(b.id));
158+
}
159+
160+
this._primaryManager = managers[0];
161+
return this._primaryManager;
162+
}
97163
} else {
98164
return null;
99165
}

0 commit comments

Comments
 (0)