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 } ); } },