Merge pull request #4605 from matrix-org/t3chguy/e2eedefault
Add .well-known option to control default e2ee behaviourpull/21833/head
commit
eccacb1bc7
|
@ -63,4 +63,25 @@ limitations under the License.
|
||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_SecurityUserSettingsTab_warning {
|
||||||
|
color: $notice-primary-color;
|
||||||
|
position: relative;
|
||||||
|
padding-left: 40px;
|
||||||
|
margin-top: 30px;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
mask-repeat: no-repeat;
|
||||||
|
mask-position: 0 center;
|
||||||
|
mask-size: $font-24px;
|
||||||
|
position: absolute;
|
||||||
|
width: $font-24px;
|
||||||
|
height: $font-24px;
|
||||||
|
content: "";
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
background-color: $notice-primary-color;
|
||||||
|
mask-image: url('$(res)/img/feather-customised/alert-triangle.svg');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.29 3.86002L1.82002 18C1.46466 18.6154 1.46254 19.3732 1.81445 19.9905C2.16635 20.6079 2.81943 20.9922 3.53002 21H20.47C21.1806 20.9922 21.8337 20.6079 22.1856 19.9905C22.5375 19.3732 22.5354 18.6154 22.18 18L13.71 3.86002C13.3475 3.2623 12.6991 2.89728 12 2.89728C11.3009 2.89728 10.6526 3.2623 10.29 3.86002Z" stroke="#2E2F32" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M12 9V13" stroke="#2E2F32" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<circle cx="12" cy="17" r="1" fill="#2E2F32"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 665 B |
|
@ -22,13 +22,13 @@ import {
|
||||||
import {
|
import {
|
||||||
hideToast as hideSetupEncryptionToast,
|
hideToast as hideSetupEncryptionToast,
|
||||||
Kind as SetupKind,
|
Kind as SetupKind,
|
||||||
Kind,
|
|
||||||
showToast as showSetupEncryptionToast
|
showToast as showSetupEncryptionToast
|
||||||
} from "./toasts/SetupEncryptionToast";
|
} from "./toasts/SetupEncryptionToast";
|
||||||
import {
|
import {
|
||||||
hideToast as hideUnverifiedSessionsToast,
|
hideToast as hideUnverifiedSessionsToast,
|
||||||
showToast as showUnverifiedSessionsToast
|
showToast as showUnverifiedSessionsToast
|
||||||
} from "./toasts/UnverifiedSessionToast";
|
} from "./toasts/UnverifiedSessionToast";
|
||||||
|
import {privateShouldBeEncrypted} from "./createRoom";
|
||||||
|
|
||||||
const KEY_BACKUP_POLL_INTERVAL = 5 * 60 * 1000;
|
const KEY_BACKUP_POLL_INTERVAL = 5 * 60 * 1000;
|
||||||
|
|
||||||
|
@ -169,6 +169,14 @@ export default class DeviceListener {
|
||||||
return this.keyBackupInfo;
|
return this.keyBackupInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private shouldShowSetupEncryptionToast() {
|
||||||
|
// In a default configuration, show the toasts. If the well-known config causes e2ee default to be false
|
||||||
|
// then do not show the toasts until user is in at least one encrypted room.
|
||||||
|
if (privateShouldBeEncrypted()) return true;
|
||||||
|
const cli = MatrixClientPeg.get();
|
||||||
|
return cli && cli.getRooms().some(r => cli.isRoomEncrypted(r.roomId));
|
||||||
|
}
|
||||||
|
|
||||||
async _recheck() {
|
async _recheck() {
|
||||||
const cli = MatrixClientPeg.get();
|
const cli = MatrixClientPeg.get();
|
||||||
|
|
||||||
|
@ -184,7 +192,7 @@ export default class DeviceListener {
|
||||||
|
|
||||||
if (this.dismissedThisDeviceToast || crossSigningReady) {
|
if (this.dismissedThisDeviceToast || crossSigningReady) {
|
||||||
hideSetupEncryptionToast();
|
hideSetupEncryptionToast();
|
||||||
} else {
|
} else if (this.shouldShowSetupEncryptionToast()) {
|
||||||
// make sure our keys are finished downloading
|
// make sure our keys are finished downloading
|
||||||
await cli.downloadKeys([cli.getUserId()]);
|
await cli.downloadKeys([cli.getUserId()]);
|
||||||
// cross signing isn't enabled - nag to enable it
|
// cross signing isn't enabled - nag to enable it
|
||||||
|
@ -196,10 +204,10 @@ export default class DeviceListener {
|
||||||
const backupInfo = await this._getKeyBackupInfo();
|
const backupInfo = await this._getKeyBackupInfo();
|
||||||
if (backupInfo) {
|
if (backupInfo) {
|
||||||
// No cross-signing on account but key backup available (upgrade encryption)
|
// No cross-signing on account but key backup available (upgrade encryption)
|
||||||
showSetupEncryptionToast(Kind.UPGRADE_ENCRYPTION);
|
showSetupEncryptionToast(SetupKind.UPGRADE_ENCRYPTION);
|
||||||
} else {
|
} else {
|
||||||
// No cross-signing or key backup on account (set up encryption)
|
// No cross-signing or key backup on account (set up encryption)
|
||||||
showSetupEncryptionToast(Kind.SET_UP_ENCRYPTION);
|
showSetupEncryptionToast(SetupKind.SET_UP_ENCRYPTION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -622,7 +622,7 @@ async function startMatrixClient(startSyncing=true) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that we have a MatrixClientPeg, update the Jitsi info
|
// Now that we have a MatrixClientPeg, update the Jitsi info
|
||||||
await Jitsi.getInstance().update();
|
await Jitsi.getInstance().start();
|
||||||
|
|
||||||
// dispatch that we finished starting up to wire up any other bits
|
// dispatch that we finished starting up to wire up any other bits
|
||||||
// of the matrix client that cannot be set prior to starting up.
|
// of the matrix client that cannot be set prior to starting up.
|
||||||
|
|
|
@ -49,6 +49,7 @@ export interface IOpts {
|
||||||
initialSyncLimit?: number;
|
initialSyncLimit?: number;
|
||||||
pendingEventOrdering?: "detached" | "chronological";
|
pendingEventOrdering?: "detached" | "chronological";
|
||||||
lazyLoadMembers?: boolean;
|
lazyLoadMembers?: boolean;
|
||||||
|
clientWellKnownPollPeriod?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IMatrixClientPeg {
|
export interface IMatrixClientPeg {
|
||||||
|
@ -209,6 +210,7 @@ class _MatrixClientPeg implements IMatrixClientPeg {
|
||||||
// the react sdk doesn't work without this, so don't allow
|
// the react sdk doesn't work without this, so don't allow
|
||||||
opts.pendingEventOrdering = "detached";
|
opts.pendingEventOrdering = "detached";
|
||||||
opts.lazyLoadMembers = true;
|
opts.lazyLoadMembers = true;
|
||||||
|
opts.clientWellKnownPollPeriod = 2 * 60 * 60; // 2 hours
|
||||||
|
|
||||||
// Connect the matrix client to the dispatcher and setting handlers
|
// Connect the matrix client to the dispatcher and setting handlers
|
||||||
MatrixActionCreators.start(this.matrixClient);
|
MatrixActionCreators.start(this.matrixClient);
|
||||||
|
|
|
@ -24,6 +24,7 @@ import withValidation from '../elements/Validation';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
||||||
import {Key} from "../../../Keyboard";
|
import {Key} from "../../../Keyboard";
|
||||||
|
import {privateShouldBeEncrypted} from "../../../createRoom";
|
||||||
|
|
||||||
export default createReactClass({
|
export default createReactClass({
|
||||||
displayName: 'CreateRoomDialog',
|
displayName: 'CreateRoomDialog',
|
||||||
|
@ -36,7 +37,7 @@ export default createReactClass({
|
||||||
const config = SdkConfig.get();
|
const config = SdkConfig.get();
|
||||||
return {
|
return {
|
||||||
isPublic: this.props.defaultPublic || false,
|
isPublic: this.props.defaultPublic || false,
|
||||||
isEncrypted: true,
|
isEncrypted: privateShouldBeEncrypted(),
|
||||||
name: "",
|
name: "",
|
||||||
topic: "",
|
topic: "",
|
||||||
alias: "",
|
alias: "",
|
||||||
|
@ -193,6 +194,13 @@ export default createReactClass({
|
||||||
|
|
||||||
let e2eeSection;
|
let e2eeSection;
|
||||||
if (!this.state.isPublic) {
|
if (!this.state.isPublic) {
|
||||||
|
let microcopy;
|
||||||
|
if (privateShouldBeEncrypted()) {
|
||||||
|
microcopy = _t("You can’t disable this later. Bridges & most bots won’t work yet.");
|
||||||
|
} else {
|
||||||
|
microcopy = _t("Your server admin has disabled end-to-end encryption by default " +
|
||||||
|
"in private rooms & Direct Messages.");
|
||||||
|
}
|
||||||
e2eeSection = <React.Fragment>
|
e2eeSection = <React.Fragment>
|
||||||
<LabelledToggleSwitch
|
<LabelledToggleSwitch
|
||||||
label={ _t("Enable end-to-end encryption")}
|
label={ _t("Enable end-to-end encryption")}
|
||||||
|
@ -200,7 +208,7 @@ export default createReactClass({
|
||||||
value={this.state.isEncrypted}
|
value={this.state.isEncrypted}
|
||||||
className='mx_CreateRoomDialog_e2eSwitch' // for end-to-end tests
|
className='mx_CreateRoomDialog_e2eSwitch' // for end-to-end tests
|
||||||
/>
|
/>
|
||||||
<p>{ _t("You can’t disable this later. Bridges & most bots won’t work yet.") }</p>
|
<p>{ microcopy }</p>
|
||||||
</React.Fragment>;
|
</React.Fragment>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ import dis from "../../../dispatcher/dispatcher";
|
||||||
import IdentityAuthClient from "../../../IdentityAuthClient";
|
import IdentityAuthClient from "../../../IdentityAuthClient";
|
||||||
import Modal from "../../../Modal";
|
import Modal from "../../../Modal";
|
||||||
import {humanizeTime} from "../../../utils/humanize";
|
import {humanizeTime} from "../../../utils/humanize";
|
||||||
import createRoom, {canEncryptToAllUsers} from "../../../createRoom";
|
import createRoom, {canEncryptToAllUsers, privateShouldBeEncrypted} from "../../../createRoom";
|
||||||
import {inviteMultipleToRoom} from "../../../RoomInvite";
|
import {inviteMultipleToRoom} from "../../../RoomInvite";
|
||||||
import {Key} from "../../../Keyboard";
|
import {Key} from "../../../Keyboard";
|
||||||
import {Action} from "../../../dispatcher/actions";
|
import {Action} from "../../../dispatcher/actions";
|
||||||
|
@ -575,14 +575,16 @@ export default class InviteDialog extends React.PureComponent {
|
||||||
|
|
||||||
const createRoomOptions = {inlineErrors: true};
|
const createRoomOptions = {inlineErrors: true};
|
||||||
|
|
||||||
// Check whether all users have uploaded device keys before.
|
if (privateShouldBeEncrypted()) {
|
||||||
// If so, enable encryption in the new room.
|
// Check whether all users have uploaded device keys before.
|
||||||
const has3PidMembers = targets.some(t => t instanceof ThreepidMember);
|
// If so, enable encryption in the new room.
|
||||||
if (!has3PidMembers) {
|
const has3PidMembers = targets.some(t => t instanceof ThreepidMember);
|
||||||
const client = MatrixClientPeg.get();
|
if (!has3PidMembers) {
|
||||||
const allHaveDeviceKeys = await canEncryptToAllUsers(client, targetIds);
|
const client = MatrixClientPeg.get();
|
||||||
if (allHaveDeviceKeys) {
|
const allHaveDeviceKeys = await canEncryptToAllUsers(client, targetIds);
|
||||||
createRoomOptions.encryption = true;
|
if (allHaveDeviceKeys) {
|
||||||
|
createRoomOptions.encryption = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ import dis from '../../../dispatcher/dispatcher';
|
||||||
import Modal from '../../../Modal';
|
import Modal from '../../../Modal';
|
||||||
import * as sdk from '../../../index';
|
import * as sdk from '../../../index';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import createRoom from '../../../createRoom';
|
import createRoom, {privateShouldBeEncrypted} from '../../../createRoom';
|
||||||
import DMRoomMap from '../../../utils/DMRoomMap';
|
import DMRoomMap from '../../../utils/DMRoomMap';
|
||||||
import AccessibleButton from '../elements/AccessibleButton';
|
import AccessibleButton from '../elements/AccessibleButton';
|
||||||
import SdkConfig from '../../../SdkConfig';
|
import SdkConfig from '../../../SdkConfig';
|
||||||
|
@ -108,15 +108,17 @@ async function openDMForUser(matrixClient, userId) {
|
||||||
dmUserId: userId,
|
dmUserId: userId,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check whether all users have uploaded device keys before.
|
if (privateShouldBeEncrypted()) {
|
||||||
// If so, enable encryption in the new room.
|
// Check whether all users have uploaded device keys before.
|
||||||
const usersToDevicesMap = await matrixClient.downloadKeys([userId]);
|
// If so, enable encryption in the new room.
|
||||||
const allHaveDeviceKeys = Object.values(usersToDevicesMap).every(devices => {
|
const usersToDevicesMap = await matrixClient.downloadKeys([userId]);
|
||||||
// `devices` is an object of the form { deviceId: deviceInfo, ... }.
|
const allHaveDeviceKeys = Object.values(usersToDevicesMap).every(devices => {
|
||||||
return Object.keys(devices).length > 0;
|
// `devices` is an object of the form { deviceId: deviceInfo, ... }.
|
||||||
});
|
return Object.keys(devices).length > 0;
|
||||||
if (allHaveDeviceKeys) {
|
});
|
||||||
createRoomOptions.encryption = true;
|
if (allHaveDeviceKeys) {
|
||||||
|
createRoomOptions.encryption = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
createRoom(createRoomOptions);
|
createRoom(createRoomOptions);
|
||||||
|
|
|
@ -26,6 +26,7 @@ import Modal from "../../../../../Modal";
|
||||||
import * as sdk from "../../../../..";
|
import * as sdk from "../../../../..";
|
||||||
import {sleep} from "../../../../../utils/promise";
|
import {sleep} from "../../../../../utils/promise";
|
||||||
import dis from "../../../../../dispatcher/dispatcher";
|
import dis from "../../../../../dispatcher/dispatcher";
|
||||||
|
import {privateShouldBeEncrypted} from "../../../../../createRoom";
|
||||||
|
|
||||||
export class IgnoredUser extends React.Component {
|
export class IgnoredUser extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -317,8 +318,17 @@ export default class SecurityUserSettingsTab extends React.Component {
|
||||||
|
|
||||||
const E2eAdvancedPanel = sdk.getComponent('views.settings.E2eAdvancedPanel');
|
const E2eAdvancedPanel = sdk.getComponent('views.settings.E2eAdvancedPanel');
|
||||||
|
|
||||||
|
let warning;
|
||||||
|
if (!privateShouldBeEncrypted()) {
|
||||||
|
warning = <div className="mx_SecurityUserSettingsTab_warning">
|
||||||
|
{ _t("Your server admin has disabled end-to-end encryption by default " +
|
||||||
|
"in private rooms & Direct Messages.") }
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx_SettingsTab mx_SecurityUserSettingsTab">
|
<div className="mx_SettingsTab mx_SecurityUserSettingsTab">
|
||||||
|
{warning}
|
||||||
<div className="mx_SettingsTab_heading">{_t("Security & Privacy")}</div>
|
<div className="mx_SettingsTab_heading">{_t("Security & Privacy")}</div>
|
||||||
<div className="mx_SettingsTab_section">
|
<div className="mx_SettingsTab_section">
|
||||||
<span className="mx_SettingsTab_subheading">{_t("Where you’re logged in")}</span>
|
<span className="mx_SettingsTab_subheading">{_t("Where you’re logged in")}</span>
|
||||||
|
|
|
@ -24,6 +24,8 @@ import * as Rooms from "./Rooms";
|
||||||
import DMRoomMap from "./utils/DMRoomMap";
|
import DMRoomMap from "./utils/DMRoomMap";
|
||||||
import {getAddressType} from "./UserAddress";
|
import {getAddressType} from "./UserAddress";
|
||||||
|
|
||||||
|
const E2EE_WK_KEY = "im.vector.riot.e2ee";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new room, and switch to it.
|
* Create a new room, and switch to it.
|
||||||
*
|
*
|
||||||
|
@ -225,9 +227,22 @@ export async function ensureDMExists(client, userId) {
|
||||||
if (existingDMRoom) {
|
if (existingDMRoom) {
|
||||||
roomId = existingDMRoom.roomId;
|
roomId = existingDMRoom.roomId;
|
||||||
} else {
|
} else {
|
||||||
const encryption = canEncryptToAllUsers(client, [userId]);
|
let encryption;
|
||||||
|
if (privateShouldBeEncrypted()) {
|
||||||
|
encryption = canEncryptToAllUsers(client, [userId]);
|
||||||
|
}
|
||||||
roomId = await createRoom({encryption, dmUserId: userId, spinner: false, andView: false});
|
roomId = await createRoom({encryption, dmUserId: userId, spinner: false, andView: false});
|
||||||
await _waitForMember(client, roomId, userId);
|
await _waitForMember(client, roomId, userId);
|
||||||
}
|
}
|
||||||
return roomId;
|
return roomId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function privateShouldBeEncrypted() {
|
||||||
|
const clientWellKnown = MatrixClientPeg.get().getClientWellKnown();
|
||||||
|
if (clientWellKnown && clientWellKnown[E2EE_WK_KEY]) {
|
||||||
|
const defaultDisabled = clientWellKnown[E2EE_WK_KEY]["default"] === false;
|
||||||
|
return !defaultDisabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -871,6 +871,7 @@
|
||||||
"Key backup": "Key backup",
|
"Key backup": "Key backup",
|
||||||
"Message search": "Message search",
|
"Message search": "Message search",
|
||||||
"Cross-signing": "Cross-signing",
|
"Cross-signing": "Cross-signing",
|
||||||
|
"Your server admin has disabled end-to-end encryption by default in private rooms & Direct Messages.": "Your server admin has disabled end-to-end encryption by default in private rooms & Direct Messages.",
|
||||||
"Security & Privacy": "Security & Privacy",
|
"Security & Privacy": "Security & Privacy",
|
||||||
"Where you’re logged in": "Where you’re logged in",
|
"Where you’re logged in": "Where you’re logged in",
|
||||||
"Manage the names of and sign out of your sessions below or <a>verify them in your User Profile</a>.": "Manage the names of and sign out of your sessions below or <a>verify them in your User Profile</a>.",
|
"Manage the names of and sign out of your sessions below or <a>verify them in your User Profile</a>.": "Manage the names of and sign out of your sessions below or <a>verify them in your User Profile</a>.",
|
||||||
|
@ -1559,8 +1560,8 @@
|
||||||
"Please enter a name for the room": "Please enter a name for the room",
|
"Please enter a name for the room": "Please enter a name for the room",
|
||||||
"Set a room address to easily share your room with other people.": "Set a room address to easily share your room with other people.",
|
"Set a room address to easily share your room with other people.": "Set a room address to easily share your room with other people.",
|
||||||
"This room is private, and can only be joined by invitation.": "This room is private, and can only be joined by invitation.",
|
"This room is private, and can only be joined by invitation.": "This room is private, and can only be joined by invitation.",
|
||||||
"Enable end-to-end encryption": "Enable end-to-end encryption",
|
|
||||||
"You can’t disable this later. Bridges & most bots won’t work yet.": "You can’t disable this later. Bridges & most bots won’t work yet.",
|
"You can’t disable this later. Bridges & most bots won’t work yet.": "You can’t disable this later. Bridges & most bots won’t work yet.",
|
||||||
|
"Enable end-to-end encryption": "Enable end-to-end encryption",
|
||||||
"Create a public room": "Create a public room",
|
"Create a public room": "Create a public room",
|
||||||
"Create a private room": "Create a private room",
|
"Create a private room": "Create a private room",
|
||||||
"Name": "Name",
|
"Name": "Name",
|
||||||
|
|
|
@ -21,10 +21,8 @@ import {IntegrationManagerInstance, KIND_ACCOUNT, KIND_CONFIG, KIND_HOMESERVER}
|
||||||
import type {MatrixClient, MatrixEvent, Room} from "matrix-js-sdk";
|
import type {MatrixClient, MatrixEvent, Room} 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";
|
|
||||||
import SettingsStore from "../settings/SettingsStore";
|
import SettingsStore from "../settings/SettingsStore";
|
||||||
|
|
||||||
const HS_MANAGERS_REFRESH_INTERVAL = 8 * 60 * 60 * 1000; // 8 hours
|
|
||||||
const KIND_PREFERENCE = [
|
const KIND_PREFERENCE = [
|
||||||
// Ordered: first is most preferred, last is least preferred.
|
// Ordered: first is most preferred, last is least preferred.
|
||||||
KIND_ACCOUNT,
|
KIND_ACCOUNT,
|
||||||
|
@ -44,7 +42,6 @@ export class IntegrationManagers {
|
||||||
|
|
||||||
_managers: IntegrationManagerInstance[] = [];
|
_managers: IntegrationManagerInstance[] = [];
|
||||||
_client: MatrixClient;
|
_client: MatrixClient;
|
||||||
_wellknownRefreshTimerId: number = null;
|
|
||||||
_primaryManager: IntegrationManagerInstance;
|
_primaryManager: IntegrationManagerInstance;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -55,20 +52,19 @@ export class IntegrationManagers {
|
||||||
this.stopWatching();
|
this.stopWatching();
|
||||||
this._client = MatrixClientPeg.get();
|
this._client = MatrixClientPeg.get();
|
||||||
this._client.on("accountData", this._onAccountData);
|
this._client.on("accountData", this._onAccountData);
|
||||||
|
this._client.on("WellKnown.client", this._setupHomeserverManagers);
|
||||||
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);
|
this._client.removeListener("accountData", this._onAccountData);
|
||||||
if (this._wellknownRefreshTimerId !== null) clearInterval(this._wellknownRefreshTimerId);
|
this._client.removeListener("WellKnown.client", this._setupHomeserverManagers);
|
||||||
}
|
}
|
||||||
|
|
||||||
_compileManagers() {
|
_compileManagers() {
|
||||||
this._managers = [];
|
this._managers = [];
|
||||||
this._setupConfiguredManager();
|
this._setupConfiguredManager();
|
||||||
this._setupHomeserverManagers();
|
|
||||||
this._setupAccountManagers();
|
this._setupAccountManagers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,39 +78,31 @@ export class IntegrationManagers {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async _setupHomeserverManagers() {
|
async _setupHomeserverManagers(discoveryResponse) {
|
||||||
if (!MatrixClientPeg.get()) return;
|
console.log("Updating homeserver-configured integration managers...");
|
||||||
try {
|
if (discoveryResponse && discoveryResponse['m.integrations']) {
|
||||||
console.log("Updating homeserver-configured integration managers...");
|
let managers = discoveryResponse['m.integrations']['managers'];
|
||||||
const homeserverDomain = MatrixClientPeg.getHomeserverName();
|
if (!Array.isArray(managers)) managers = []; // make it an array so we can wipe the HS managers
|
||||||
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`);
|
console.log(`Homeserver has ${managers.length} integration managers`);
|
||||||
|
|
||||||
// Clear out any known managers for the homeserver
|
// Clear out any known managers for the homeserver
|
||||||
// TODO: Log out of the scalar clients
|
// TODO: Log out of the scalar clients
|
||||||
this._managers = this._managers.filter(m => m.kind !== KIND_HOMESERVER);
|
this._managers = this._managers.filter(m => m.kind !== KIND_HOMESERVER);
|
||||||
|
|
||||||
// Now add all the managers the homeserver wants us to have
|
// Now add all the managers the homeserver wants us to have
|
||||||
for (const hsManager of managers) {
|
for (const hsManager of managers) {
|
||||||
if (!hsManager["api_url"]) continue;
|
if (!hsManager["api_url"]) continue;
|
||||||
this._managers.push(new IntegrationManagerInstance(
|
this._managers.push(new IntegrationManagerInstance(
|
||||||
KIND_HOMESERVER,
|
KIND_HOMESERVER,
|
||||||
hsManager["api_url"],
|
hsManager["api_url"],
|
||||||
hsManager["ui_url"], // optional
|
hsManager["ui_url"], // optional
|
||||||
));
|
));
|
||||||
}
|
|
||||||
|
|
||||||
this._primaryManager = null; // reset primary
|
|
||||||
} else {
|
|
||||||
console.log("Homeserver has no integration managers");
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
this._primaryManager = null; // reset primary
|
||||||
// Errors during discovery are non-fatal
|
} else {
|
||||||
|
console.log("Homeserver has no integration managers");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,10 +16,8 @@ limitations under the License.
|
||||||
|
|
||||||
import SdkConfig from "../SdkConfig";
|
import SdkConfig from "../SdkConfig";
|
||||||
import {MatrixClientPeg} from "../MatrixClientPeg";
|
import {MatrixClientPeg} from "../MatrixClientPeg";
|
||||||
import {AutoDiscovery} from "matrix-js-sdk/src/autodiscovery";
|
|
||||||
|
|
||||||
const JITSI_WK_PROPERTY = "im.vector.riot.jitsi";
|
const JITSI_WK_PROPERTY = "im.vector.riot.jitsi";
|
||||||
const JITSI_WK_CHECK_INTERVAL = 2 * 60 * 60 * 1000; // 2 hours, arbitrarily selected
|
|
||||||
|
|
||||||
export interface JitsiWidgetData {
|
export interface JitsiWidgetData {
|
||||||
conferenceId: string;
|
conferenceId: string;
|
||||||
|
@ -36,39 +34,27 @@ export class Jitsi {
|
||||||
return this.domain || 'jitsi.riot.im';
|
return this.domain || 'jitsi.riot.im';
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
public start() {
|
||||||
// We rely on the first call to be an .update() instead of doing one here. Doing one
|
const cli = MatrixClientPeg.get();
|
||||||
// here could result in duplicate calls to the homeserver.
|
cli.on("WellKnown.client", this.update);
|
||||||
|
// call update initially in case we missed the first WellKnown.client event and for if no well-known present
|
||||||
// Start a timer to update the server info regularly
|
this.update(cli.getClientWellKnown());
|
||||||
setInterval(() => this.update(), JITSI_WK_CHECK_INTERVAL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async update(): Promise<any> {
|
private update = async (discoveryResponse): Promise<any> => {
|
||||||
// Start with a default of the config's domain
|
// Start with a default of the config's domain
|
||||||
let domain = (SdkConfig.get()['jitsi'] || {})['preferredDomain'] || 'jitsi.riot.im';
|
let domain = (SdkConfig.get()['jitsi'] || {})['preferredDomain'] || 'jitsi.riot.im';
|
||||||
|
|
||||||
// Now request the .well-known config to see if it changed
|
console.log("Attempting to get Jitsi conference information from homeserver");
|
||||||
if (MatrixClientPeg.get()) {
|
if (discoveryResponse && discoveryResponse[JITSI_WK_PROPERTY]) {
|
||||||
try {
|
const wkPreferredDomain = discoveryResponse[JITSI_WK_PROPERTY]['preferredDomain'];
|
||||||
console.log("Attempting to get Jitsi conference information from homeserver");
|
if (wkPreferredDomain) domain = wkPreferredDomain;
|
||||||
|
|
||||||
const homeserverDomain = MatrixClientPeg.getHomeserverName();
|
|
||||||
const discoveryResponse = await AutoDiscovery.getRawClientConfig(homeserverDomain);
|
|
||||||
if (discoveryResponse && discoveryResponse[JITSI_WK_PROPERTY]) {
|
|
||||||
const wkPreferredDomain = discoveryResponse[JITSI_WK_PROPERTY]['preferredDomain'];
|
|
||||||
if (wkPreferredDomain) domain = wkPreferredDomain;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
// These are non-fatal errors
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put the result into memory for us to use later
|
// Put the result into memory for us to use later
|
||||||
this.domain = domain;
|
this.domain = domain;
|
||||||
console.log("Jitsi conference domain:", this.preferredDomain);
|
console.log("Jitsi conference domain:", this.preferredDomain);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the given URL into the data needed for a Jitsi widget, if the widget
|
* Parses the given URL into the data needed for a Jitsi widget, if the widget
|
||||||
|
|
Loading…
Reference in New Issue