Skip to content

Commit

Permalink
FEATURE - allow Group Moderators to edit category description (#10292)
Browse files Browse the repository at this point in the history
Co-authored-by: Alan Guo Xiang Tan <gxtan1990@gmail.com>
  • Loading branch information
jbrw and tgxworld committed Jul 23, 2020
1 parent 61d3640 commit 2aec92d
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 2 deletions.
4 changes: 4 additions & 0 deletions app/models/post.rb
Expand Up @@ -485,6 +485,10 @@ def is_first_post?
post_number == 1
end

def is_category_description?
topic.present? && topic.is_category_topic? && is_first_post?
end

def is_reply_by_email?
via_email && post_number.present? && post_number > 1
end
Expand Down
4 changes: 4 additions & 0 deletions lib/guardian/category_guardian.rb
Expand Up @@ -54,6 +54,10 @@ def can_see_category?(category)
secure_category_ids.include?(category.id)
end

def can_edit_category_description?(category)
can_perform_action_available_to_group_moderators?(category.topic)
end

def secure_category_ids
@secure_category_ids ||= @user.secure_category_ids
end
Expand Down
4 changes: 4 additions & 0 deletions lib/guardian/post_guardian.rb
Expand Up @@ -161,6 +161,10 @@ def can_edit_post?(post)
return !post.edit_time_limit_expired?(@user)
end

if post.is_category_description?
return true if can_edit_category_description?(post.topic.category)
end

false
end

Expand Down
9 changes: 7 additions & 2 deletions lib/post_revisor.rb
Expand Up @@ -192,8 +192,13 @@ def revise!(editor, fields, opts = {})
PostLocker.new(@post, @editor).lock
end

# We log staff edits to posts
if @editor.staff? && @editor.id != @post.user_id && @fields.has_key?('raw') && !@opts[:skip_staff_log]
# We log staff/group moderator edits to posts
if (
(@editor.staff? || (@post.is_category_description? && Guardian.new(@editor).can_edit_category_description?(@post.topic.category))) &&
@editor.id != @post.user_id &&
@fields.has_key?('raw') &&
!@opts[:skip_staff_log]
)
StaffActionLogger.new(@editor).log_post_edit(
@post,
old_raw: old_raw
Expand Down
22 changes: 22 additions & 0 deletions spec/components/post_revisor_spec.rb
Expand Up @@ -598,6 +598,28 @@
end
end

context "logging group moderator edits" do
fab!(:group_user) { Fabricate(:group_user) }
fab!(:category) { Fabricate(:category, reviewable_by_group_id: group_user.group.id, topic: topic) }

before do
SiteSetting.enable_category_group_moderation = true
topic.update!(category: category)
post.update!(topic: topic)
end

it "logs an edit when a group moderator revises the category description" do
PostRevisor.new(post).revise!(group_user.user, raw: "a group moderator can update the description")

log = UserHistory.where(
acting_user_id: group_user.user.id,
action: UserHistory.actions[:post_edit]
).first
expect(log).to be_present
expect(log.details).to eq("Hello world\n\n---\n\na group moderator can update the description")
end
end

context "staff_edit_locks_post" do

context "disabled" do
Expand Down
47 changes: 47 additions & 0 deletions spec/requests/posts_controller_spec.rb
Expand Up @@ -426,6 +426,53 @@
end
end

describe "when logged in as group moderator" do
fab!(:topic) { Fabricate(:topic, category: category) }
fab!(:post) { Fabricate(:post, user: user, topic: topic) }
fab!(:group_user) { Fabricate(:group_user) }
let(:user_gm) { group_user.user }
let(:group) { group_user.group }

before do
SiteSetting.enable_category_group_moderation = true
post.topic.category.update!(reviewable_by_group_id: group.id, topic_id: topic.id)
sign_in(user_gm)
end

it "allows updating the category description" do
put "/posts/#{post.id}.json", params: update_params
expect(response.status).to eq(200)

post.reload
expect(post.raw).to eq('edited body')
expect(UserHistory.where(action: UserHistory.actions[:post_edit]).count).to eq(1)
end

it "can not update other posts within the primary category topic" do
second_post = Fabricate(:post, user: user, topic: topic)

put "/posts/#{second_post.id}.json", params: update_params
expect(response.status).to eq(403)
end

it "can not update other first posts of topics in the same category" do
second_topic_in_category = Fabricate(:topic, category: category)
post_in_second_topic = Fabricate(:post, user: user, topic: second_topic_in_category)

put "/posts/#{post_in_second_topic.id}.json", params: update_params
expect(response.status).to eq(403)
end

it "can not update category descriptions in other categories" do
second_category = Fabricate(:category)
topic.update!(category: second_category)

put "/posts/#{post.id}.json", params: update_params
expect(response.status).to eq(403)
end

end

it 'can not change category to a disallowed category' do
post = create_post
sign_in(post.user)
Expand Down
22 changes: 22 additions & 0 deletions spec/services/staff_action_logger_spec.rb
Expand Up @@ -595,4 +595,26 @@
end
end

describe 'log_post_staff_note' do
fab!(:post) { Fabricate(:post) }

it "raises an error when argument is missing" do
expect { logger.log_topic_archived(nil) }.to raise_error(Discourse::InvalidParameters)
end

it "creates a new UserHistory record" do
expect { logger.log_post_staff_note(post, { new_raw_value: 'my note', old_value: nil }) }.to change { UserHistory.count }.by(1)
user_history = UserHistory.last
expect(user_history.action).to eq(UserHistory.actions[:post_staff_note_create])
expect(user_history.new_value).to eq('my note')
expect(user_history.previous_value).to eq(nil)

expect { logger.log_post_staff_note(post, { new_raw_value: nil, old_value: 'my note' }) }.to change { UserHistory.count }.by(1)
user_history = UserHistory.last
expect(user_history.action).to eq(UserHistory.actions[:post_staff_note_destroy])
expect(user_history.new_value).to eq(nil)
expect(user_history.previous_value).to eq('my note')
end
end

end
2 changes: 2 additions & 0 deletions test/javascripts/acceptance/post-admin-menu-test.js
Expand Up @@ -7,6 +7,7 @@ QUnit.test("Enter as a anon user", async assert => {
await click(".show-more-actions");

assert.ok(exists("#topic"), "The topic was rendered");
assert.ok(exists("#post_1 .post-controls .edit"), "The edit button was not rendered");
assert.ok(!exists(".show-post-admin-menu"), "The wrench button was not rendered");
});

Expand All @@ -17,5 +18,6 @@ QUnit.test("Enter as a user with group moderator permissions", async assert => {
await click(".show-more-actions");
await click(".show-post-admin-menu");

assert.ok(exists("#post_1 .post-controls .edit"), "The edit button was rendered");
assert.ok(exists(".add-notice"), "The add notice button was rendered");
});

1 comment on commit 2aec92d

@discoursebot
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

https://meta.discourse.org/t/category-group-review-moderation/116478/56

Please sign in to comment.