mirror of
https://github.com/discourse/discourse.git
synced 2025-06-03 19:39:30 +08:00
FEATURE: Allow group moderators to add/remove staff notes (#10252)
* FEATURE: Allow group moderators to add/remove staff notes
This commit is contained in:
@ -121,6 +121,7 @@ export default function transformPost(
|
|||||||
currentUser && (currentUser.id === post.user_id || currentUser.staff);
|
currentUser && (currentUser.id === post.user_id || currentUser.staff);
|
||||||
postAtts.canArchiveTopic = !!details.can_archive_topic;
|
postAtts.canArchiveTopic = !!details.can_archive_topic;
|
||||||
postAtts.canCloseTopic = !!details.can_close_topic;
|
postAtts.canCloseTopic = !!details.can_close_topic;
|
||||||
|
postAtts.canEditStaffNotes = !!details.can_edit_staff_notes;
|
||||||
postAtts.canReplyAsNewTopic = !!details.can_reply_as_new_topic;
|
postAtts.canReplyAsNewTopic = !!details.can_reply_as_new_topic;
|
||||||
postAtts.canReviewTopic = !!details.can_review_topic;
|
postAtts.canReviewTopic = !!details.can_review_topic;
|
||||||
postAtts.canPublishPage =
|
postAtts.canPublishPage =
|
||||||
|
@ -52,7 +52,7 @@ export function buildManageButtons(attrs, currentUser, siteSettings) {
|
|||||||
contents.push(buttonAtts);
|
contents.push(buttonAtts);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentUser.staff) {
|
if (attrs.canEditStaffNotes) {
|
||||||
if (attrs.noticeType) {
|
if (attrs.noticeType) {
|
||||||
contents.push({
|
contents.push({
|
||||||
icon: "user-shield",
|
icon: "user-shield",
|
||||||
|
@ -332,7 +332,7 @@ registerButton(
|
|||||||
);
|
);
|
||||||
|
|
||||||
registerButton("admin", attrs => {
|
registerButton("admin", attrs => {
|
||||||
if (!attrs.canManage && !attrs.canWiki) {
|
if (!attrs.canManage && !attrs.canWiki && !attrs.canEditStaffNotes) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
@ -6,9 +6,11 @@
|
|||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.topic-post:first-child {
|
.staff {
|
||||||
nav.post-controls .post-admin-menu {
|
.topic-post:first-child {
|
||||||
bottom: -125px;
|
nav.post-controls .post-admin-menu {
|
||||||
|
bottom: -125px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,9 +474,8 @@ class PostsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def notice
|
def notice
|
||||||
raise Discourse::NotFound unless guardian.is_staff?
|
|
||||||
|
|
||||||
post = find_post_from_params
|
post = find_post_from_params
|
||||||
|
raise Discourse::NotFound unless guardian.can_edit_staff_notes?(post.topic)
|
||||||
|
|
||||||
if params[:notice].present?
|
if params[:notice].present?
|
||||||
post.custom_fields[Post::NOTICE_TYPE] = Post.notices[:custom]
|
post.custom_fields[Post::NOTICE_TYPE] = Post.notices[:custom]
|
||||||
|
@ -18,7 +18,8 @@ class TopicViewDetailsSerializer < ApplicationSerializer
|
|||||||
:can_edit_tags,
|
:can_edit_tags,
|
||||||
:can_publish_page,
|
:can_publish_page,
|
||||||
:can_close_topic,
|
:can_close_topic,
|
||||||
:can_archive_topic]
|
:can_archive_topic,
|
||||||
|
:can_edit_staff_notes]
|
||||||
end
|
end
|
||||||
|
|
||||||
attributes(
|
attributes(
|
||||||
@ -136,13 +137,12 @@ class TopicViewDetailsSerializer < ApplicationSerializer
|
|||||||
!scope.can_edit?(object.topic) && scope.can_edit_tags?(object.topic)
|
!scope.can_edit?(object.topic) && scope.can_edit_tags?(object.topic)
|
||||||
end
|
end
|
||||||
|
|
||||||
def include_can_close_topic?
|
def can_perform_action_available_to_group_moderators?
|
||||||
scope.can_close_topic?(object.topic)
|
@can_perform_action_available_to_group_moderators ||= scope.can_perform_action_available_to_group_moderators?(object.topic)
|
||||||
end
|
|
||||||
|
|
||||||
def include_can_archive_topic?
|
|
||||||
scope.can_archive_topic?(object.topic)
|
|
||||||
end
|
end
|
||||||
|
alias :include_can_close_topic? :can_perform_action_available_to_group_moderators?
|
||||||
|
alias :include_can_archive_topic? :can_perform_action_available_to_group_moderators?
|
||||||
|
alias :include_can_edit_staff_notes? :can_perform_action_available_to_group_moderators?
|
||||||
|
|
||||||
def include_can_publish_page?
|
def include_can_publish_page?
|
||||||
scope.can_publish_page?(object.topic)
|
scope.can_publish_page?(object.topic)
|
||||||
|
@ -216,5 +216,6 @@ module TopicGuardian
|
|||||||
end
|
end
|
||||||
alias :can_archive_topic? :can_perform_action_available_to_group_moderators?
|
alias :can_archive_topic? :can_perform_action_available_to_group_moderators?
|
||||||
alias :can_close_topic? :can_perform_action_available_to_group_moderators?
|
alias :can_close_topic? :can_perform_action_available_to_group_moderators?
|
||||||
|
alias :can_edit_staff_notes? :can_perform_action_available_to_group_moderators?
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -1779,6 +1779,28 @@ describe Guardian do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "can_edit_staff_notes?" do
|
||||||
|
it 'returns false with a nil object' do
|
||||||
|
expect(Guardian.new(user).can_edit_staff_notes?(nil)).to eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns true for a staff user' do
|
||||||
|
expect(Guardian.new(moderator).can_edit_staff_notes?(topic)).to eq(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns false for a regular user' do
|
||||||
|
expect(Guardian.new(user).can_edit_staff_notes?(topic)).to eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns true for a group member with reviewable status' do
|
||||||
|
SiteSetting.enable_category_group_moderation = true
|
||||||
|
group = Fabricate(:group)
|
||||||
|
GroupUser.create!(group_id: group.id, user_id: user.id)
|
||||||
|
topic.category.update!(reviewable_by_group_id: group.id)
|
||||||
|
expect(Guardian.new(user).can_edit_staff_notes?(topic)).to eq(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context "can_create_topic?" do
|
context "can_create_topic?" do
|
||||||
it 'returns true for staff user' do
|
it 'returns true for staff user' do
|
||||||
expect(Guardian.new(moderator).can_create_topic?(topic)).to eq(true)
|
expect(Guardian.new(moderator).can_create_topic?(topic)).to eq(true)
|
||||||
|
@ -1795,11 +1795,9 @@ describe PostsController do
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe "#notice" do
|
describe "#notice" do
|
||||||
before do
|
it 'can create and remove notices as a moderator' do
|
||||||
sign_in(moderator)
|
sign_in(moderator)
|
||||||
end
|
|
||||||
|
|
||||||
it 'can create and remove notices' do
|
|
||||||
put "/posts/#{public_post.id}/notice.json", params: { notice: "Hello *world*!\n\nhttps://github.com/discourse/discourse" }
|
put "/posts/#{public_post.id}/notice.json", params: { notice: "Hello *world*!\n\nhttps://github.com/discourse/discourse" }
|
||||||
|
|
||||||
expect(response.status).to eq(200)
|
expect(response.status).to eq(200)
|
||||||
@ -1815,6 +1813,52 @@ describe PostsController do
|
|||||||
expect(public_post.custom_fields[Post::NOTICE_TYPE]).to eq(nil)
|
expect(public_post.custom_fields[Post::NOTICE_TYPE]).to eq(nil)
|
||||||
expect(public_post.custom_fields[Post::NOTICE_ARGS]).to eq(nil)
|
expect(public_post.custom_fields[Post::NOTICE_ARGS]).to eq(nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'group moderators' do
|
||||||
|
fab!(:group_user) { Fabricate(:group_user) }
|
||||||
|
let(:user) { group_user.user }
|
||||||
|
let(:group) { group_user.group }
|
||||||
|
|
||||||
|
before do
|
||||||
|
SiteSetting.enable_category_group_moderation = true
|
||||||
|
topic.category.update!(reviewable_by_group_id: group.id)
|
||||||
|
|
||||||
|
sign_in(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'can create and remove notices as a group moderator' do
|
||||||
|
put "/posts/#{public_post.id}/notice.json", params: { notice: "Hello *world*!\n\nhttps://github.com/discourse/discourse" }
|
||||||
|
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
public_post.reload
|
||||||
|
expect(public_post.custom_fields[Post::NOTICE_TYPE]).to eq(Post.notices[:custom])
|
||||||
|
expect(public_post.custom_fields[Post::NOTICE_ARGS]).to include('<p>Hello <em>world</em>!</p>')
|
||||||
|
expect(public_post.custom_fields[Post::NOTICE_ARGS]).not_to include('onebox')
|
||||||
|
|
||||||
|
put "/posts/#{public_post.id}/notice.json", params: { notice: nil }
|
||||||
|
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
public_post.reload
|
||||||
|
expect(public_post.custom_fields[Post::NOTICE_TYPE]).to eq(nil)
|
||||||
|
expect(public_post.custom_fields[Post::NOTICE_ARGS]).to eq(nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'prevents a group moderator from altering notes outside of their category' do
|
||||||
|
moderatable_group = Fabricate(:group)
|
||||||
|
topic.category.update!(reviewable_by_group_id: moderatable_group.id)
|
||||||
|
|
||||||
|
put "/posts/#{public_post.id}/notice.json", params: { notice: "Hello" }
|
||||||
|
|
||||||
|
expect(response.status).to eq(404)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'prevents a normal user from altering notes' do
|
||||||
|
group_user.destroy!
|
||||||
|
put "/posts/#{public_post.id}/notice.json", params: { notice: "Hello" }
|
||||||
|
|
||||||
|
expect(response.status).to eq(404)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe Plugin::Instance do
|
describe Plugin::Instance do
|
||||||
|
21
test/javascripts/acceptance/post-admin-menu-test.js
Normal file
21
test/javascripts/acceptance/post-admin-menu-test.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { acceptance } from "helpers/qunit-helpers";
|
||||||
|
|
||||||
|
acceptance("Post - Admin Menu Anonymous Users", { loggedIn: false });
|
||||||
|
|
||||||
|
QUnit.test("Enter as a anon user", async assert => {
|
||||||
|
await visit("/t/internationalization-localization/280");
|
||||||
|
await click(".show-more-actions");
|
||||||
|
|
||||||
|
assert.ok(exists("#topic"), "The topic was rendered");
|
||||||
|
assert.ok(!exists(".show-post-admin-menu"), "The wrench button was not rendered");
|
||||||
|
});
|
||||||
|
|
||||||
|
acceptance("Post - Admin Menu", { loggedIn: true });
|
||||||
|
|
||||||
|
QUnit.test("Enter as a user with group moderator permissions", async assert => {
|
||||||
|
await visit("/t/topic-for-group-moderators/2480");
|
||||||
|
await click(".show-more-actions");
|
||||||
|
await click(".show-post-admin-menu");
|
||||||
|
|
||||||
|
assert.ok(exists(".add-notice"), "The add notice button was rendered");
|
||||||
|
});
|
@ -19,10 +19,10 @@ QUnit.test("Enter as a user with group moderator permissions", async assert => {
|
|||||||
assert.ok(exists(".toggle-admin-menu"), "The admin menu button was rendered");
|
assert.ok(exists(".toggle-admin-menu"), "The admin menu button was rendered");
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test("Enter as a user with group moderator permissions", async assert => {
|
QUnit.test("Enter as a user with moderator and admin permissions", async assert => {
|
||||||
updateCurrentUser({ moderator: true, admin: true, trust_level: 4 });
|
updateCurrentUser({ moderator: true, admin: true, trust_level: 4 });
|
||||||
|
|
||||||
await visit("/t/topic-for-group-moderators/2480");
|
await visit("/t/internationalization-localization/280");
|
||||||
assert.ok(exists("#topic"), "The topic was rendered");
|
assert.ok(exists("#topic"), "The topic was rendered");
|
||||||
assert.ok(exists(".toggle-admin-menu"), "The admin menu button was rendered");
|
assert.ok(exists(".toggle-admin-menu"), "The admin menu button was rendered");
|
||||||
});
|
});
|
||||||
|
@ -259,6 +259,7 @@ export function applyDefaultHandlers(pretender) {
|
|||||||
const json = fixturesByUrl["/t/34/1.json"];
|
const json = fixturesByUrl["/t/34/1.json"];
|
||||||
json.details.can_archive_topic = true;
|
json.details.can_archive_topic = true;
|
||||||
json.details.can_close_topic = true;
|
json.details.can_close_topic = true;
|
||||||
|
json.details.can_edit_staff_notes = true;
|
||||||
|
|
||||||
return response(json);
|
return response(json);
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user