diff --git a/plugins/poll/assets/javascripts/initializers/add-poll-ui-builder.js.es6 b/plugins/poll/assets/javascripts/initializers/add-poll-ui-builder.js.es6
index c2b0a287235..86d5f64f472 100644
--- a/plugins/poll/assets/javascripts/initializers/add-poll-ui-builder.js.es6
+++ b/plugins/poll/assets/javascripts/initializers/add-poll-ui-builder.js.es6
@@ -1,15 +1,22 @@
import { withPluginApi } from 'discourse/lib/plugin-api';
+import computed from 'ember-addons/ember-computed-decorators';
import showModal from 'discourse/lib/show-modal';
function initializePollUIBuilder(api) {
- const siteSettings = api.container.lookup('site-settings:main');
-
- if (!siteSettings.poll_enabled && (api.getCurrentUser() && !api.getCurrentUser().staff)) return;
-
api.modifyClass('controller:composer', {
+ @computed('siteSettings.poll_enabled', 'siteSettings.poll_minimum_trust_level_to_create')
+ canBuildPoll(pollEnabled, minimumTrustLevelToCreate) {
+ return pollEnabled &&
+ this.currentUser &&
+ (
+ this.currentUser.admin ||
+ this.currentUser.trust_level >= minimumTrustLevelToCreate
+ );
+ },
+
actions: {
showPollBuilder() {
- showModal("poll-ui-builder").set("toolbarEvent", this.get("toolbarEvent"));
+ showModal('poll-ui-builder').set('toolbarEvent', this.get('toolbarEvent'));
}
}
});
@@ -18,13 +25,14 @@ function initializePollUIBuilder(api) {
return {
action: 'showPollBuilder',
icon: 'bar-chart-o',
- label: 'poll.ui_builder.title'
+ label: 'poll.ui_builder.title',
+ condition: 'canBuildPoll'
};
});
}
export default {
- name: "add-poll-ui-builder",
+ name: 'add-poll-ui-builder',
initialize() {
withPluginApi('0.8.7', initializePollUIBuilder);
diff --git a/plugins/poll/assets/javascripts/lib/discourse-markdown/poll.js.es6 b/plugins/poll/assets/javascripts/lib/discourse-markdown/poll.js.es6
index 442f2a0d242..ca67fa921b4 100644
--- a/plugins/poll/assets/javascripts/lib/discourse-markdown/poll.js.es6
+++ b/plugins/poll/assets/javascripts/lib/discourse-markdown/poll.js.es6
@@ -281,10 +281,7 @@ const rule = {
function newApiInit(helper) {
helper.registerOptions((opts, siteSettings) => {
- const currentUser = (opts.getCurrentUser && opts.getCurrentUser(opts.userId)) || opts.currentUser;
- const staff = currentUser && currentUser.staff;
-
- opts.features.poll = !!siteSettings.poll_enabled || staff;
+ opts.features.poll = !!siteSettings.poll_enabled;
opts.pollMaximumOptions = siteSettings.poll_maximum_options;
});
diff --git a/plugins/poll/config/locales/server.en.yml b/plugins/poll/config/locales/server.en.yml
index 6ae0bea3c42..1916da774f6 100644
--- a/plugins/poll/config/locales/server.en.yml
+++ b/plugins/poll/config/locales/server.en.yml
@@ -16,9 +16,10 @@
en:
site_settings:
- poll_enabled: "Allow users to create polls?"
+ poll_enabled: "Allow polls?"
poll_maximum_options: "Maximum number of options allowed in a poll."
poll_edit_window_mins: "Number of minutes after post creation during which polls can be edited."
+ poll_minimum_trust_level_to_create: "Define the minimum trust level needed to create polls"
poll:
multiple_polls_without_name: "There are multiple polls without a name. Use the 'name
' attribute to uniquely identify your polls."
@@ -61,5 +62,7 @@ en:
topic_must_be_open_to_toggle_status: "The topic must be open to toggle status."
only_staff_or_op_can_toggle_status: "Only a staff member or the original poster can toggle a poll status."
+ insufficient_trust_level_to_create: "Your trust level (%{current}) is insufficient to create polls (required: %{required})"
+
email:
link_to_poll: "Click to view the poll."
diff --git a/plugins/poll/config/settings.yml b/plugins/poll/config/settings.yml
index 04bf21f5e99..5f4cfa825b7 100644
--- a/plugins/poll/config/settings.yml
+++ b/plugins/poll/config/settings.yml
@@ -7,3 +7,7 @@ plugins:
client: true
poll_edit_window_mins:
default: 5
+ poll_minimum_trust_level_to_create:
+ default: 1
+ client: true
+ enum: 'TrustLevelSetting'
diff --git a/plugins/poll/lib/post_validator.rb b/plugins/poll/lib/post_validator.rb
new file mode 100644
index 00000000000..7e1a5f53ad1
--- /dev/null
+++ b/plugins/poll/lib/post_validator.rb
@@ -0,0 +1,25 @@
+module DiscoursePoll
+ class PostValidator
+ def initialize(post)
+ @post = post
+ end
+
+ def validate_post
+ min_trust_level = SiteSetting.poll_minimum_trust_level_to_create
+ trusted = @post&.user&.admin ||
+ @post&.user&.trust_level >= TrustLevel[min_trust_level]
+
+ if !trusted
+ message = I18n.t("poll.insufficient_trust_level_to_create",
+ current: @post&.user&.trust_level,
+ required: min_trust_level
+ )
+
+ @post.errors.add(:base, message)
+ return false
+ end
+
+ true
+ end
+ end
+end
diff --git a/plugins/poll/plugin.rb b/plugins/poll/plugin.rb
index 84eb24adf63..669c72956c2 100644
--- a/plugins/poll/plugin.rb
+++ b/plugins/poll/plugin.rb
@@ -14,12 +14,12 @@ PLUGIN_NAME ||= "discourse_poll".freeze
DATA_PREFIX ||= "data-poll-".freeze
after_initialize do
-
module ::DiscoursePoll
DEFAULT_POLL_NAME ||= "poll".freeze
POLLS_CUSTOM_FIELD ||= "polls".freeze
VOTES_CUSTOM_FIELD ||= "polls-votes".freeze
+ autoload :PostValidator, "#{Rails.root}/plugins/poll/lib/post_validator"
autoload :PollsValidator, "#{Rails.root}/plugins/poll/lib/polls_validator"
autoload :PollsUpdater, "#{Rails.root}/plugins/poll/lib/polls_updater"
@@ -314,6 +314,9 @@ after_initialize do
# only care when raw has changed!
return unless self.raw_changed? || force
+ validator = DiscoursePoll::PostValidator.new(self)
+ return unless validator.validate_post
+
validator = DiscoursePoll::PollsValidator.new(self)
return unless (polls = validator.validate_polls)
diff --git a/plugins/poll/spec/controllers/posts_controller_spec.rb b/plugins/poll/spec/controllers/posts_controller_spec.rb
index 7a3e39a77cd..637eb66267e 100644
--- a/plugins/poll/spec/controllers/posts_controller_spec.rb
+++ b/plugins/poll/spec/controllers/posts_controller_spec.rb
@@ -336,4 +336,100 @@ describe PostsController do
end
+ describe "disabled polls" do
+ before do
+ SiteSetting.poll_enabled = false
+ end
+
+ it "doesn’t cook the poll" do
+ post :create, params: {
+ title: title, raw: "[poll]\n- A\n- B\n[/poll]"
+ }, format: :json
+
+ expect(response).to be_success
+ json = ::JSON.parse(response.body)
+ expect(json["cooked"]).to eq("
[poll]
\n