diff --git a/src/UserSettingsStore.js b/src/UserSettingsStore.js
index e5dba62ee7..f2f99603d6 100644
--- a/src/UserSettingsStore.js
+++ b/src/UserSettingsStore.js
@@ -149,6 +149,22 @@ module.exports = {
return MatrixClientPeg.get().setAccountData("im.vector.web.settings", settings);
},
+ getLocalSettings: function() {
+ return localStorage.getItem('mx_local_settings');
+ },
+
+ getLocalSetting: function(type, defaultValue = null) {
+ var settings = this.getLocalSettings();
+ return settings.hasOwnProperty(type) ? settings[type] : null;
+ },
+
+ setLocalSetting: function(type, value) {
+ var settings = this.getLocalSettings();
+ settings[type] = value;
+ // FIXME: handle errors
+ localStorage.setItem('mx_local_settings', settings);
+ },
+
isFeatureEnabled: function(feature: string): boolean {
// Disable labs for guests.
if (MatrixClientPeg.get().isGuest()) return false;
diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js
index 4a1332be8c..a262431f2b 100644
--- a/src/components/structures/UserSettings.js
+++ b/src/components/structures/UserSettings.js
@@ -57,6 +57,18 @@ const SETTINGS_LABELS = [
*/
];
+const CRYPTO_SETTINGS_LABELS = [
+ {
+ id: 'blacklistUnverifiedDevices',
+ label: 'Never send encrypted messages to unverified devices',
+ },
+ // XXX: this is here for documentation; the actual setting is managed via RoomSettings
+ // {
+ // id: 'blacklistUnverifiedDevicesPerRoom'
+ // label: 'Never send encrypted messages to unverified devices in this room',
+ // }
+];
+
// Enumerate the available themes, with a nice human text label.
// 'id' gives the key name in the im.vector.web.settings account data event
// 'value' is the value for that key in the event
@@ -146,6 +158,8 @@ module.exports = React.createClass({
syncedSettings.theme = 'light';
}
this._syncedSettings = syncedSettings;
+
+ this._localSettings = UserSettingsStore.getLocalSettings();
},
componentDidMount: function() {
@@ -471,10 +485,32 @@ module.exports = React.createClass({
{identityKey}
+ { CRYPTO_SETTINGS_LABELS.map( this._renderLocalSetting ) }
);
},
+ _renderLocalSetting: function(setting) {
+ const client = MatrixClientPeg.get();
+ return
+ {
+ UserSettingsStore.setLocalSetting(setting.id, e.target.checked)
+ if (setting.id === 'blacklistUnverifiedDevices') { // XXX: this is a bit ugly
+ client.setGlobalBlacklistUnverifiedDevices(e.target.checked);
+ }
+ }
+ }
+ />
+
+
;
+ },
+
_renderDevicesPanel: function() {
var DevicesPanel = sdk.getComponent('settings.DevicesPanel');
return (
diff --git a/src/components/views/dialogs/UnknownDeviceDialog.js b/src/components/views/dialogs/UnknownDeviceDialog.js
index aad310c855..8e04414b9c 100644
--- a/src/components/views/dialogs/UnknownDeviceDialog.js
+++ b/src/components/views/dialogs/UnknownDeviceDialog.js
@@ -69,5 +69,7 @@ module.exports = React.createClass({
);
+ // XXX: do we want to give the user the option to enable blacklistUnverifiedDevices for this room (or globally) at this point?
+ // It feels like confused users will likely turn it on and then disappear in a cloud of UISIs...
}
});
diff --git a/src/components/views/rooms/RoomSettings.js b/src/components/views/rooms/RoomSettings.js
index e14a929ebe..7283201858 100644
--- a/src/components/views/rooms/RoomSettings.js
+++ b/src/components/views/rooms/RoomSettings.js
@@ -228,11 +228,13 @@ module.exports = React.createClass({
}
// encryption
- p = this.saveEncryption();
+ p = this.saveEnableEncryption();
if (!q.isFulfilled(p)) {
promises.push(p);
}
+ this.saveBlacklistUnverifiedDevicesPerRoom();
+
console.log("Performing %s operations: %s", promises.length, JSON.stringify(promises));
return promises;
},
@@ -252,11 +254,11 @@ module.exports = React.createClass({
return this.refs.url_preview_settings.saveSettings();
},
- saveEncryption: function() {
+ saveEnableEncryption: function() {
if (!this.refs.encrypt) { return q(); }
var encrypt = this.refs.encrypt.checked;
- if (!encrypt) { return q(); }
+ if (encrypt) { return q(); }
var roomId = this.props.room.roomId;
return MatrixClientPeg.get().sendStateEvent(
@@ -265,6 +267,29 @@ module.exports = React.createClass({
);
},
+ saveBlacklistUnverifiedDevicesPerRoom: function() {
+ if (!this.refs.blacklistUnverified) return;
+ if (this._isRoomBlacklistUnverified() !== this.refs.blacklistUnverified.checked) {
+ this._setRoomBlacklistUnverified(this.refs.blacklistUnverified.checked);
+ }
+ },
+
+ _isRoomBlacklistUnverified: function() {
+ var blacklistUnverifiedDevicesPerRoom = UserSettingsStore.getLocalSettings().blacklistUnverifiedDevicesPerRoom;
+ if (blacklistUnverifiedDevicesPerRoom) {
+ return blacklistUnverifiedDevicesPerRoom[this.props.room.roomId];
+ }
+ return false;
+ },
+
+ _setRoomBlacklistUnverified: function(value) {
+ var blacklistUnverifiedDevicesPerRoom = UserSettingsStore.getLocalSettings().blacklistUnverifiedDevicesPerRoom;
+ blacklistUnverifiedDevicesPerRoom[this.props.room.roomId] = value;
+ UserSettingsStore.setLocalSettings('blacklistUnverifiedDevicesPerRoom', blacklistUnverifiedDevicesPerRoom);
+
+ this.props.room.setBlacklistUnverifiedDevices(value);
+ },
+
_hasDiff: function(strA, strB) {
// treat undefined as an empty string because other components may blindly
// call setName("") when there has been no diff made to the name!
@@ -477,6 +502,16 @@ module.exports = React.createClass({
var cli = MatrixClientPeg.get();
var roomState = this.props.room.currentState;
var isEncrypted = cli.isRoomEncrypted(this.props.room.roomId);
+ var isGlobalBlacklistUnverified = UserSettingsStore.getLocalSettings().blacklistUnverifiedDevices;
+ var isRoomBlacklistUnverified = this._isRoomBlacklistUnverified();
+
+ var settings =
+ ;
if (!isEncrypted &&
roomState.mayClientSendStateEvent("m.room.encryption", cli)) {
@@ -486,6 +521,7 @@ module.exports = React.createClass({
Enable encryption (warning: cannot be disabled again!)
+ { settings }
);
}
else {
@@ -497,6 +533,7 @@ module.exports = React.createClass({
}
Encryption is { isEncrypted ? "" : "not " } enabled in this room.
+ { settings }
);
}
},