Prevent comments by the staff account from being hidden (#19698)
* don't show hide/unhide on comments made by staff account * block staff account comments from being hidden on the backend as well * moar specs
This commit is contained in:
parent
5fe3a04287
commit
b0b1ace7d9
8 changed files with 138 additions and 18 deletions
|
|
@ -194,6 +194,10 @@ class Comment < ApplicationRecord
|
|||
ancestry && Comment.exists?(id: ancestry)
|
||||
end
|
||||
|
||||
def by_staff_account?
|
||||
user == User.staff_account
|
||||
end
|
||||
|
||||
def privileged_reaction_counts
|
||||
@privileged_reaction_counts ||= reactions.privileged_category.group(:category).count
|
||||
end
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ class CommentPolicy < ApplicationPolicy
|
|||
end
|
||||
|
||||
def hide?
|
||||
user_commentable_author?
|
||||
user_commentable_author? && !record.by_staff_account?
|
||||
end
|
||||
|
||||
alias unhide? hide?
|
||||
|
|
|
|||
|
|
@ -31,23 +31,24 @@
|
|||
<ul class="m-0">
|
||||
<li><a href="<%= contextual_comment_url(comment, article: @article) %>" class="crayons-link crayons-link--block permalink-copybtn" aria-label="<%= t("views.comments.menu.copy.aria_label", user: comment.user.name) %>" data-no-instant><%= t("views.comments.menu.copy.text") %></a></li>
|
||||
<li class="comment-actions hidden" data-user-id="<%= comment.user_id %>" data-action="settings-button" data-path="<%= URL.comment(comment) %>/settings" aria-label="<%= t("views.comments.menu.settings.aria_label", user: comment.user.name) %>"></li>
|
||||
<% action = comment.hidden_by_commentable_user ? "unhide" : "hide" %>
|
||||
<li class="comment-actions hidden" data-action="hide-button" data-commentable-user-id="<%= commentable&.user_id %>" data-user-id="<%= comment.user_id %>">
|
||||
<% if comment.hidden_by_commentable_user %>
|
||||
<a href="#" class="crayons-link crayons-link--block unhide-comment" data-hide-type="unhide" data-comment-id="<%= comment.id %>" aria-label="<%= t("views.comments.menu.action.aria_label", action: t("views.comments.menu.action.unhide"), user: comment.user.name) %>">
|
||||
<%= t("views.comments.menu.action.unhide_text") %>
|
||||
</a>
|
||||
<% else %>
|
||||
<button
|
||||
class="flex justify-between crayons-link crayons-link--block w-100 bg-transparent border-0 hide-comment"
|
||||
data-hide-type="hide"
|
||||
data-comment-id="<%= comment.id %>"
|
||||
data-comment-url="<%= URL.url(comment.path) %>"
|
||||
aria-label="<%= t("views.comments.menu.action.aria_label", action: t("views.comments.menu.action.hide"), user: comment.user.name) %>">
|
||||
<%= t("views.comments.menu.action.hide_text") %>
|
||||
</button>
|
||||
<% end %>
|
||||
</li>
|
||||
<% unless comment.by_staff_account? %>
|
||||
<li class="comment-actions hidden" data-action="hide-button" data-commentable-user-id="<%= commentable&.user_id %>" data-user-id="<%= comment.user_id %>">
|
||||
<% if comment.hidden_by_commentable_user %>
|
||||
<a href="#" class="crayons-link crayons-link--block unhide-comment" data-hide-type="unhide" data-comment-id="<%= comment.id %>" aria-label="<%= t("views.comments.menu.action.aria_label", action: t("views.comments.menu.action.unhide"), user: comment.user.name) %>">
|
||||
<%= t("views.comments.menu.action.unhide_text") %>
|
||||
</a>
|
||||
<% else %>
|
||||
<button
|
||||
class="flex justify-between crayons-link crayons-link--block w-100 bg-transparent border-0 hide-comment"
|
||||
data-hide-type="hide"
|
||||
data-comment-id="<%= comment.id %>"
|
||||
data-comment-url="<%= URL.url(comment.path) %>"
|
||||
aria-label="<%= t("views.comments.menu.action.aria_label", action: t("views.comments.menu.action.hide"), user: comment.user.name) %>">
|
||||
<%= t("views.comments.menu.action.hide_text") %>
|
||||
</button>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
<li class="mod-actions hidden mod-actions-comment-button" data-path="<%= URL.comment(comment) %>/mod" aria-label="<%= t("views.comments.menu.moderate.aria_label", user: comment.user.name) %>"></li>
|
||||
<li class="report-abuse-link-wrapper" data-path="/report-abuse?url=<%= URL.comment(comment) %>" aria-label="<%= t("views.comments.menu.report.aria_label", user: comment.user.name) %>"></li>
|
||||
<li class="current-user-actions"></li>
|
||||
|
|
|
|||
|
|
@ -38,5 +38,16 @@ describe('Hiding/unhiding comments on an article', () => {
|
|||
|
||||
cy.findByRole('img', { name: 'Expand' }).should('not.exist');
|
||||
});
|
||||
|
||||
context('when the comment was made by the staff account', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/admin_mcadmin/staff-commented-article-slug');
|
||||
});
|
||||
|
||||
it('does not allow the user to hide comments made by the staff account', () => {
|
||||
cy.findByRole('button', { name: 'Toggle dropdown menu' }).click();
|
||||
cy.findByRole('button', { name: /Hide/ }).should('not.exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -614,4 +614,23 @@ RSpec.describe Comment do
|
|||
expect(comment.reload.root_exists?).to be(false)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#by_staff_account?" do
|
||||
let(:regular_user) { create(:user) }
|
||||
let(:staff_account) { create(:user) }
|
||||
let(:comment) { build(:comment, user: regular_user) }
|
||||
let(:staff_comment) { build(:comment, user: staff_account) }
|
||||
|
||||
before do
|
||||
allow(User).to receive(:staff_account).and_return(staff_account)
|
||||
end
|
||||
|
||||
it "returns true if comment is by the staff account" do
|
||||
expect(staff_comment.by_staff_account?).to be(true)
|
||||
end
|
||||
|
||||
it "returns false if comment is not by the staff account" do
|
||||
expect(comment.by_staff_account?).to be(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -130,5 +130,18 @@ RSpec.describe CommentPolicy, type: :policy do
|
|||
it { is_expected.to permit_actions(%i[hide unhide create]) }
|
||||
it { is_expected.to forbid_actions(%i[edit update destroy delete_confirm moderate]) }
|
||||
it { is_expected.to forbid_actions(%i[moderator_create admin_delete]) }
|
||||
|
||||
context "when comment author is the staff account" do
|
||||
let(:staff_account) { create(:user) }
|
||||
let(:comment) { build_stubbed(:comment, commentable: article, user: staff_account) }
|
||||
|
||||
before do
|
||||
allow(User).to receive(:staff_account).and_return(staff_account)
|
||||
end
|
||||
|
||||
it { is_expected.to permit_actions([:create]) }
|
||||
it { is_expected.to forbid_actions(%i[hide unhide edit update destroy delete_confirm]) }
|
||||
it { is_expected.to forbid_actions(%i[moderate moderator_create admin_delete]) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -445,6 +445,27 @@ RSpec.describe "Comments" do
|
|||
expect(child_comment.hidden_by_commentable_user).to be false
|
||||
end
|
||||
end
|
||||
|
||||
context "with comment by staff account" do
|
||||
let(:staff_account) { create(:user) }
|
||||
let(:commentable_author) { create(:user) }
|
||||
let(:article) { create(:article, user: commentable_author) }
|
||||
let(:comment) { create(:comment, commentable: article, user: staff_account) }
|
||||
|
||||
before do
|
||||
allow(User).to receive(:staff_account).and_return(staff_account)
|
||||
sign_in commentable_author
|
||||
end
|
||||
|
||||
it "does not permit hiding the comment" do
|
||||
expect do
|
||||
patch "/comments/#{comment.id}/hide", headers: { HTTP_ACCEPT: "application/json" }
|
||||
end.to raise_error(Pundit::NotAuthorizedError)
|
||||
|
||||
comment.reload
|
||||
expect(comment.hidden_by_commentable_user).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "PATCH /comments/:comment_id/unhide" do
|
||||
|
|
|
|||
|
|
@ -207,6 +207,26 @@ end
|
|||
|
||||
##############################################################################
|
||||
|
||||
seeder.create_if_doesnt_exist(User, "email", "staff-account@forem.local") do
|
||||
staff_account = User.create!(
|
||||
name: "Sloan",
|
||||
email: "staff-account@forem.local",
|
||||
username: "sloan",
|
||||
profile_image: Rails.root.join("app/assets/images/#{rand(1..40)}.png").open,
|
||||
confirmed_at: Time.current,
|
||||
registered_at: Time.current,
|
||||
password: "password",
|
||||
password_confirmation: "password",
|
||||
saw_onboarding: true,
|
||||
checked_code_of_conduct: true,
|
||||
checked_terms_and_conditions: true,
|
||||
)
|
||||
|
||||
Settings::Community.staff_user_id = staff_account.id
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
|
||||
seeder.create_if_doesnt_exist(Organization, "slug", "bachmanity") do
|
||||
organization = Organization.create!(
|
||||
name: "Bachmanity",
|
||||
|
|
@ -586,6 +606,37 @@ end
|
|||
|
||||
##############################################################################
|
||||
|
||||
seeder.create_if_doesnt_exist(Article, "slug", "staff-commented-article-slug") do
|
||||
markdown = <<~MARKDOWN
|
||||
---
|
||||
title: Test article with Staff Account Comment
|
||||
published: true
|
||||
cover_image: #{Faker::Company.logo}
|
||||
---
|
||||
#{Faker::Hipster.paragraph(sentence_count: 2)}
|
||||
#{Faker::Markdown.random}
|
||||
#{Faker::Hipster.paragraph(sentence_count: 2)}
|
||||
MARKDOWN
|
||||
article = Article.create!(
|
||||
body_markdown: markdown,
|
||||
featured: true,
|
||||
show_comments: true,
|
||||
user_id: admin_user.id,
|
||||
slug: "staff-commented-article-slug",
|
||||
)
|
||||
|
||||
staff_comment_attributes = {
|
||||
body_markdown: Faker::Hipster.paragraph(sentence_count: 1),
|
||||
user_id: User.staff_account.id,
|
||||
commentable_id: article.id,
|
||||
commentable_type: "Article"
|
||||
}
|
||||
|
||||
Comment.create!(staff_comment_attributes)
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
|
||||
seeder.create_if_doesnt_exist(Article, "slug", "unfeatured-article-slug") do
|
||||
markdown = <<~MARKDOWN
|
||||
---
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue