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.