FIX: return an error if a user tries to whisper

FIX: return an error if a user tries to whisper

This commit fixes a bug where a user creates a whisper post via the api but is posted as a regular message because they don’t have access to whisper. Now a 403 unauthorized will be returned instead of the whisper param just being ignored for regular users. Staff users should not be affected by this change.

A whisper is posted as a message if the user is not staff/moderator/admin when using the API - bug - Discourse Meta

diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb
index 739580e..45e4aba 100644
--- a/app/controllers/posts_controller.rb
+++ b/app/controllers/posts_controller.rb
@@ -730,7 +730,9 @@ class PostsController < ApplicationController
       result[:shared_draft] = true
     end
 
-    if current_user.staff? && SiteSetting.enable_whispers? && params[:whisper] == "true"
+    if params[:whisper] == "true"
+      raise Discourse::InvalidAccess.new("invalid_whisper_access", nil, custom_message: "invalid_whisper_access") unless guardian.can_create_whisper?
+
       result[:post_type] = Post.types[:whisper]
     end
 
diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml
index ec82060..2ca784e 100644
--- a/config/locales/server.en.yml
+++ b/config/locales/server.en.yml
@@ -243,6 +243,7 @@ en:
   read_only_mode_enabled: "The site is in read only mode. Interactions are disabled."
   invalid_grant_badge_reason_link: "External or invalid discourse link is not allowed in badge reason"
   email_template_cant_be_modified: "This email template can't be modified"
+  invalid_whisper_access: "Either whispers are not enabled or you do not have access to create whisper posts"
 
   reading_time: "Reading time"
   likes: "Likes"
diff --git a/lib/guardian/topic_guardian.rb b/lib/guardian/topic_guardian.rb
index d6ed415..cd78f2e 100644
--- a/lib/guardian/topic_guardian.rb
+++ b/lib/guardian/topic_guardian.rb
@@ -24,6 +24,10 @@ module TopicGuardian
     is_staff? && SiteSetting.shared_drafts_enabled?
   end
 
+  def can_create_whisper?
+    is_staff? && SiteSetting.enable_whispers?
+  end
+
   def can_publish_topic?(topic, category)
     is_staff? && can_see?(topic) && can_create_topic?(category)
   end
diff --git a/spec/requests/posts_controller_spec.rb b/spec/requests/posts_controller_spec.rb
index b5dfb78..3a09541 100644
--- a/spec/requests/posts_controller_spec.rb
+++ b/spec/requests/posts_controller_spec.rb
@@ -696,6 +696,7 @@ describe PostsController do
 
     before do
       SiteSetting.min_first_post_typing_time = 0
+      SiteSetting.enable_whispers = true
     end
 
     fab!(:user) { Fabricate(:user) }
@@ -774,6 +775,22 @@ describe PostsController do
         expect(response.status).to eq(200)
         expect(post_1.topic.user.notifications.count).to eq(1)
       end
+
+      it 'prevents whispers for regular users' do
+        post_1 = Fabricate(:post)
+        user = Fabricate(:user)
+        user_key = ApiKey.create!(user: user, key: SecureRandom.hex).key
+
+        post "/posts.json", params: {
+          api_username: user.username,
+          api_key: user_key,
+          raw: 'this is test whisper',
+          topic_id: post_1.topic.id,
+          reply_to_post_number: 1,
+          whisper: true
+        }
+        expect(response.status).to eq(403)
+      end
     end
 
     describe "when logged in" do

GitHub sha: 5b5b5a59

1 Like

This commit has been mentioned on Discourse Meta. There might be relevant details there: