diff --git a/assets/javascripts/discourse/connectors/user-preferences-account/encrypt.hbs b/assets/javascripts/discourse/connectors/user-preferences-account/encrypt.hbs index 357f25c0..5f7abde1 100644 --- a/assets/javascripts/discourse/connectors/user-preferences-account/encrypt.hbs +++ b/assets/javascripts/discourse/connectors/user-preferences-account/encrypt.hbs @@ -1,4 +1,4 @@ -{{#if siteSettings.encrypt_enabled}} +{{#if isPluginEnabled}}
diff --git a/assets/javascripts/discourse/connectors/user-preferences-account/encrypt.js.es6 b/assets/javascripts/discourse/connectors/user-preferences-account/encrypt.js.es6 index 6a828fc6..2afb4dea 100644 --- a/assets/javascripts/discourse/connectors/user-preferences-account/encrypt.js.es6 +++ b/assets/javascripts/discourse/connectors/user-preferences-account/encrypt.js.es6 @@ -31,6 +31,10 @@ export default { setupComponent(args, component) { const currentUser = Discourse.User.current(); if (args.model.get("id") === currentUser.get("id")) { + const groups = (args.model.get("groups") || []).map(group => + group.get("name") + ); + const encryptGroups = Discourse.SiteSettings.encrypt_groups.split("|"); component.setProperties({ model: args.model, handler: hideComponentIfDisabled(component), @@ -48,6 +52,10 @@ export default { inProgress: false, /** @var Whether current user is the same as model user. */ isCurrentUser: true, + /** @var Whether plugin is enabled for current user. */ + isPluginEnabled: + Discourse.SiteSettings.encrypt_groups.length === 0 || + groups.some(group => encryptGroups.includes(group)), /** @var Whether the encryption is enabled or not. */ isEncryptEnabled: false, /** @var Whether the encryption is active on this device. */ diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 9ae2cc17..d2103925 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -4,3 +4,4 @@ en: enabled_already: "You have already enabled encrypted messages." site_settings: encrypt_enabled: "Enable encrypted private messages." + encrypt_groups: "The name of groups that are able to use encryption (empty means everyone)." diff --git a/config/settings.yml b/config/settings.yml index e3ca8659..7b7345dd 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -2,4 +2,8 @@ plugins: encrypt_enabled: client: true default: true - refresh: true \ No newline at end of file + refresh: true + encrypt_groups: + default: "" + client: true + type: list diff --git a/plugin.rb b/plugin.rb index 24e04983..561dba21 100644 --- a/plugin.rb +++ b/plugin.rb @@ -48,6 +48,11 @@ def update_keys private_key = params.require(:private_key) salt = params.require(:salt) + # Check if encrypt settings are visible to user. + groups = current_user.groups.pluck(:name) + encrypt_groups = SiteSetting.encrypt_groups.split("|") + raise Discourse::InvalidAccess if !SiteSetting.encrypt_groups.empty? && (groups & encrypt_groups).empty? + # Check if encryption is already enabled (but not changing passphrase). old_public_key = current_user.custom_fields['encrypt_public_key'] if old_public_key && old_public_key != public_key diff --git a/spec/requests/encrypt_controller_spec.rb b/spec/requests/encrypt_controller_spec.rb index 06ecbcbf..25266e28 100644 --- a/spec/requests/encrypt_controller_spec.rb +++ b/spec/requests/encrypt_controller_spec.rb @@ -38,6 +38,30 @@ expect(response.status).to eq(403) end + it 'does not work when user is not allowed' do + group = Fabricate(:group) + SiteSetting.encrypt_groups = group.name + + user = Fabricate(:user) + sign_in(user) + + put '/encrypt/keys', params: { + public_key: '-- the public key --', + private_key: '-- the private key --', + salt: '-- the salt --' + } + expect(response.status).to eq(403) + + Fabricate(:group_user, group: group, user: user) + + put '/encrypt/keys', params: { + public_key: '-- the public key --', + private_key: '-- the private key --', + salt: '-- the salt --' + } + expect(response.status).to eq(200) + end + it 'saves user keys' do sign_in(user3) diff --git a/test/javascripts/acceptance/encrypt-settings-test.js.es6 b/test/javascripts/acceptance/encrypt-settings-test.js.es6 new file mode 100644 index 00000000..c5732394 --- /dev/null +++ b/test/javascripts/acceptance/encrypt-settings-test.js.es6 @@ -0,0 +1,55 @@ +import { acceptance, replaceCurrentUser } from "helpers/qunit-helpers"; + +// TODO: Figure out why `await` is not enough. +function sleep(time) { + return new Promise(resolve => { + setTimeout(() => resolve(), time); + }); +} + +acceptance("Encrypt - Settings", { + loggedIn: true, + settings: { encrypt_enabled: true, encrypt_groups: "" } +}); + +test("encrypt settings visible only to allowed groups", async assert => { + await visit("/u/eviltrout/preferences"); + await sleep(1500); + + assert.ok(find(".encrypt").text().length > 0, "encrypt settings are visible"); + + Discourse.SiteSettings.encrypt_groups = "allowed_group"; + + replaceCurrentUser({ + groups: [ + Ember.Object.create({ + id: 1, + name: "not_allowed_group" + }) + ] + }); + + await visit("/u/eviltrout/preferences"); + await sleep(1500); + assert.ok( + find(".encrypt").text().length === 0, + "encrypt settings are not visible" + ); + + replaceCurrentUser({ + groups: [ + Ember.Object.create({ + id: 1, + name: "not_allowed_group" + }), + Ember.Object.create({ + id: 2, + name: "allowed_group" + }) + ] + }); + + await visit("/u/eviltrout/preferences"); + await sleep(1500); + assert.ok(find(".encrypt").text().length > 0, "encrypt settings are visible"); +}); diff --git a/test/javascripts/acceptance/encrypt-test.js.es6 b/test/javascripts/acceptance/encrypt-test.js.es6 index 27dd15c7..51c071e9 100644 --- a/test/javascripts/acceptance/encrypt-test.js.es6 +++ b/test/javascripts/acceptance/encrypt-test.js.es6 @@ -126,7 +126,7 @@ function sleep(time) { acceptance("Encrypt", { loggedIn: true, - settings: { encrypt_enabled: true }, + settings: { encrypt_enabled: true, encrypt_groups: "" }, beforeEach() { // Hook `XMLHttpRequest` to search for leaked plaintext.