diff --git a/app/assets/javascripts/discourse/app/widgets/topic-admin-menu.js b/app/assets/javascripts/discourse/app/widgets/topic-admin-menu.js index ed7d6e9ca76..299c0754bb4 100644 --- a/app/assets/javascripts/discourse/app/widgets/topic-admin-menu.js +++ b/app/assets/javascripts/discourse/app/widgets/topic-admin-menu.js @@ -250,7 +250,7 @@ export default createWidget("topic-admin-menu", { } } - if (this.get("currentUser.canManageTopic")) { + if (details.get("can_toggle_topic_visibility")) { this.addActionButton({ className: "topic-admin-visible", buttonClass: "popup-menu-btn", @@ -258,7 +258,9 @@ export default createWidget("topic-admin-menu", { icon: visible ? "far-eye-slash" : "far-eye", label: visible ? "actions.invisible" : "actions.visible", }); + } + if (this.get("currentUser.canManageTopic")) { if (details.get("can_convert_topic")) { this.addActionButton({ className: "topic-admin-convert", diff --git a/app/assets/javascripts/discourse/tests/fixtures/topic.js b/app/assets/javascripts/discourse/tests/fixtures/topic.js index 5d97207a921..34915dd7e02 100644 --- a/app/assets/javascripts/discourse/tests/fixtures/topic.js +++ b/app/assets/javascripts/discourse/tests/fixtures/topic.js @@ -2205,6 +2205,7 @@ export default { details: { can_publish_page: true, can_invite_via_email: true, + can_toggle_topic_visibility: true, auto_close_at: null, auto_close_hours: null, auto_close_based_on_last_post: false, @@ -5592,6 +5593,7 @@ export default { can_review_topic: true, can_close_topic: true, can_archive_topic: true, + can_toggle_topic_visibility: true, can_split_merge_topic: true, can_edit_staff_notes: true, can_moderate_category: true, diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index 6d7af2ba359..d1b5ca2b7c6 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -420,6 +420,8 @@ class TopicsController < ApplicationController guardian.ensure_can_close_topic!(@topic) when 'archived' guardian.ensure_can_archive_topic!(@topic) + when 'visible' + guardian.ensure_can_toggle_topic_visibility!(@topic) else guardian.ensure_can_moderate!(@topic) end diff --git a/app/serializers/topic_view_details_serializer.rb b/app/serializers/topic_view_details_serializer.rb index 9988675130c..16a28e40f59 100644 --- a/app/serializers/topic_view_details_serializer.rb +++ b/app/serializers/topic_view_details_serializer.rb @@ -20,6 +20,7 @@ class TopicViewDetailsSerializer < ApplicationSerializer :can_archive_topic, :can_split_merge_topic, :can_edit_staff_notes, + :can_toggle_topic_visibility, :can_moderate_category] end @@ -144,6 +145,10 @@ class TopicViewDetailsSerializer < ApplicationSerializer !scope.can_edit?(object.topic) && scope.can_edit_tags?(object.topic) end + def include_can_toggle_topic_visibility? + scope.can_toggle_topic_visibility?(object.topic) + end + def can_perform_action_available_to_group_moderators? @can_perform_action_available_to_group_moderators ||= scope.can_perform_action_available_to_group_moderators?(object.topic) end diff --git a/lib/guardian/topic_guardian.rb b/lib/guardian/topic_guardian.rb index 74a02958504..ed64497d7da 100644 --- a/lib/guardian/topic_guardian.rb +++ b/lib/guardian/topic_guardian.rb @@ -146,6 +146,10 @@ module TopicGuardian !Discourse.static_doc_topic_ids.include?(topic.id) end + def can_toggle_topic_visibility?(topic) + can_moderate?(topic) || can_perform_action_available_to_group_moderators?(topic) + end + def can_convert_topic?(topic) return false unless SiteSetting.enable_personal_messages? return false if topic.blank? diff --git a/spec/requests/topics_controller_spec.rb b/spec/requests/topics_controller_spec.rb index 07e3448bafc..32e6ee1a516 100644 --- a/spec/requests/topics_controller_spec.rb +++ b/spec/requests/topics_controller_spec.rb @@ -948,6 +948,28 @@ RSpec.describe TopicsController do expect(response.status).to eq(403) expect(topic.reload.pinned_at).to eq(nil) end + + it 'should allow a group moderator to unlist a topic' do + put "/t/#{topic.id}/status.json", params: { + status: 'visible', enabled: 'false' + } + + expect(response.status).to eq(200) + expect(topic.reload.visible).to eq(false) + expect(topic.posts.last.action_code).to eq('visible.disabled') + end + + it 'should allow a group moderator to list an unlisted topic' do + topic.update!(visible: false) + + put "/t/#{topic.id}/status.json", params: { + status: 'visible', enabled: 'true' + } + + expect(response.status).to eq(200) + expect(topic.reload.visible).to eq(true) + expect(topic.posts.last.action_code).to eq('visible.enabled') + end end end