forked from e621ng/e621ng
[Posts] Add back comment disabling (#749)
This commit is contained in:
parent
567ec94e5a
commit
6f296e8e01
@ -174,7 +174,8 @@ class PostsController < ApplicationController
|
||||
]
|
||||
permitted_params += %i[is_rating_locked] if CurrentUser.is_privileged?
|
||||
permitted_params += %i[is_note_locked bg_color] if CurrentUser.is_janitor?
|
||||
permitted_params += %i[is_status_locked is_comment_locked locked_tags hide_from_anonymous hide_from_search_engines] if CurrentUser.is_admin?
|
||||
permitted_params += %i[is_comment_locked] if CurrentUser.is_moderator?
|
||||
permitted_params += %i[is_status_locked is_comment_disabled locked_tags hide_from_anonymous hide_from_search_engines] if CurrentUser.is_admin?
|
||||
|
||||
params.require(:post).permit(permitted_params)
|
||||
end
|
||||
|
@ -93,6 +93,7 @@ class VoteManager
|
||||
raise UserVote::Error, "Invalid vote" unless [1, -1].include?(score)
|
||||
raise UserVote::Error, "You do not have permission to vote" unless user.is_member?
|
||||
raise UserVote::Error, "Comment section is locked" if comment.post.is_comment_locked?
|
||||
raise UserVote::Error, "Comment section is disabled" if comment.post.is_comment_disabled?
|
||||
CommentVote.transaction(**ISOLATION) do
|
||||
CommentVote.uncached do
|
||||
score_modifier = score
|
||||
|
@ -31,6 +31,10 @@ class Comment < ApplicationRecord
|
||||
belongs_to :warning_user, class_name: "User", optional: true
|
||||
has_many :votes, :class_name => "CommentVote", :dependent => :destroy
|
||||
|
||||
scope :deleted, -> { where(is_hidden: true) }
|
||||
scope :undeleted, -> { where(is_hidden: false) }
|
||||
scope :stickied, -> { where(is_sticky: true) }
|
||||
|
||||
module SearchMethods
|
||||
def recent
|
||||
reorder("comments.id desc").limit(RECENT_COUNT)
|
||||
@ -47,21 +51,16 @@ class Comment < ApplicationRecord
|
||||
end
|
||||
|
||||
def visible(user)
|
||||
if user.is_moderator?
|
||||
where("comments.score >= ? or comments.is_sticky = true", user.comment_threshold)
|
||||
elsif user.is_janitor?
|
||||
where("(comments.score >= ? or comments.is_sticky = true) and (comments.is_sticky = true or comments.is_hidden = false or comments.creator_id = ?)", user.comment_threshold, user.id)
|
||||
q = where("comments.score >= ? or comments.is_sticky = true", user.comment_threshold)
|
||||
unless user.is_moderator?
|
||||
q = q.joins(:post).where("comments.is_sticky = true or posts.is_comment_disabled = false or comments.creator_id = ?", user.id)
|
||||
if user.is_janitor?
|
||||
q = q.where("comments.is_sticky = true or comments.is_hidden = false or comments.creator_id = ?", user.id)
|
||||
else
|
||||
where("(comments.score >= ? or comments.is_sticky = true) and (comments.is_hidden = false or comments.creator_id = ?)", user.comment_threshold, user.id)
|
||||
q = q.where("comments.is_hidden = false or comments.creator_id = ?", user.id)
|
||||
end
|
||||
end
|
||||
|
||||
def deleted
|
||||
where("comments.is_hidden = true")
|
||||
end
|
||||
|
||||
def undeleted
|
||||
where("comments.is_hidden = false")
|
||||
q
|
||||
end
|
||||
|
||||
def post_tags_match(query)
|
||||
@ -139,7 +138,11 @@ class Comment < ApplicationRecord
|
||||
end
|
||||
|
||||
def post_not_comment_locked
|
||||
errors.add(:base, "Post has comments locked") if !CurrentUser.is_moderator? && Post.find_by(id: post_id)&.is_comment_locked?
|
||||
return if CurrentUser.is_moderator?
|
||||
post = Post.find_by(id: post_id)
|
||||
return if post.blank?
|
||||
errors.add(:base, "Post has comments locked") if post.is_comment_locked?
|
||||
errors.add(:base, "Post has comments disabled") if post.is_comment_disabled?
|
||||
end
|
||||
|
||||
def update_last_commented_at_on_create
|
||||
@ -179,25 +182,26 @@ class Comment < ApplicationRecord
|
||||
|
||||
def can_reply?(user)
|
||||
return false if is_sticky?
|
||||
return false if post.is_comment_locked? && !user.is_moderator?
|
||||
return false if (post.is_comment_locked? || post.is_comment_disabled?) && !user.is_moderator?
|
||||
true
|
||||
end
|
||||
|
||||
def editable_by?(user)
|
||||
return true if user.is_admin?
|
||||
return false if post.is_comment_locked? && !user.is_moderator?
|
||||
return false if (post.is_comment_locked? || post.is_comment_disabled?) && !user.is_moderator?
|
||||
return false if was_warned?
|
||||
creator_id == user.id
|
||||
end
|
||||
|
||||
def can_hide?(user)
|
||||
return true if user.is_moderator?
|
||||
return false if was_warned?
|
||||
return false if !visible_to?(user) || was_warned? || post&.is_comment_disabled?
|
||||
user.id == creator_id
|
||||
end
|
||||
|
||||
def visible_to?(user)
|
||||
return true if user.is_moderator?
|
||||
return false if !is_sticky? && (post&.is_comment_disabled? && creator_id != user.id)
|
||||
return true if user.is_janitor? && is_sticky?
|
||||
return true if is_hidden? == false
|
||||
creator_id == user.id # Can always see your own comments, even if hidden.
|
||||
|
@ -58,9 +58,6 @@ class Post < ApplicationRecord
|
||||
attr_accessor :old_tag_string, :old_parent_id, :old_source, :old_rating,
|
||||
:do_not_version_changes, :tag_string_diff, :source_diff, :edit_reason
|
||||
|
||||
# FIXME: Remove this
|
||||
alias_attribute :is_comment_locked, :is_comment_disabled
|
||||
|
||||
has_many :versions, -> {order("post_versions.id ASC")}, :class_name => "PostVersion", :dependent => :destroy
|
||||
|
||||
IMAGE_TYPES = %i[original large preview crop]
|
||||
@ -1573,6 +1570,10 @@ class Post < ApplicationRecord
|
||||
action = is_comment_locked? ? :comment_locked : :comment_unlocked
|
||||
PostEvent.add(id, CurrentUser.user, action)
|
||||
end
|
||||
if saved_change_to_is_comment_disabled?
|
||||
action = is_comment_disabled? ? :comment_disabled : :comment_enabled
|
||||
PostEvent.add(id, CurrentUser.user, action)
|
||||
end
|
||||
if saved_change_to_bg_color?
|
||||
PostEvent.add(id, CurrentUser.user, :changed_bg_color, { bg_color: bg_color })
|
||||
end
|
||||
@ -1770,8 +1771,12 @@ class Post < ApplicationRecord
|
||||
!has_tag?("grandfathered_content") && created_at.after?("2015-01-01")
|
||||
end
|
||||
|
||||
def visible_comment_count(_user)
|
||||
def visible_comment_count(user)
|
||||
if user.is_moderator? || !is_comment_disabled?
|
||||
comment_count
|
||||
else
|
||||
comments.visible(user).count
|
||||
end
|
||||
end
|
||||
|
||||
def avoid_posting_artists
|
||||
|
@ -19,6 +19,8 @@ class PostEvent < ApplicationRecord
|
||||
note_unlocked: 13,
|
||||
comment_locked: 18,
|
||||
comment_unlocked: 19,
|
||||
comment_disabled: 22,
|
||||
comment_enabled: 23,
|
||||
replacement_accepted: 14,
|
||||
replacement_rejected: 15,
|
||||
replacement_promoted: 20,
|
||||
@ -26,9 +28,11 @@ class PostEvent < ApplicationRecord
|
||||
expunged: 17,
|
||||
changed_bg_color: 21,
|
||||
}
|
||||
MOD_ONLY_ACTIONS = [
|
||||
MOD_ONLY_SEARCH_ACTIONS = [
|
||||
actions[:comment_locked],
|
||||
actions[:comment_unlocked],
|
||||
actions[:comment_disabled],
|
||||
actions[:comment_enabled],
|
||||
].freeze
|
||||
|
||||
def self.add(post_id, creator, action, data = {})
|
||||
@ -47,11 +51,8 @@ class PostEvent < ApplicationRecord
|
||||
def self.search(params)
|
||||
q = super
|
||||
|
||||
unless CurrentUser.is_moderator?
|
||||
q = q.where.not(action: MOD_ONLY_ACTIONS)
|
||||
end
|
||||
if params[:post_id].present?
|
||||
q = q.where("post_id = ?", params[:post_id].to_i)
|
||||
q = q.where(post_id: params[:post_id])
|
||||
end
|
||||
|
||||
q = q.where_user(:creator_id, :creator, params) do |condition, user_ids|
|
||||
@ -62,9 +63,18 @@ class PostEvent < ApplicationRecord
|
||||
end
|
||||
|
||||
if params[:action].present?
|
||||
q = q.where('action = ?', actions[params[:action]])
|
||||
if !CurrentUser.user.is_moderator? && MOD_ONLY_SEARCH_ACTIONS.include?(actions[params[:action]])
|
||||
raise(User::PrivilegeError)
|
||||
end
|
||||
q = q.where(action: actions[params[:action]])
|
||||
end
|
||||
|
||||
q.apply_basic_order(params)
|
||||
end
|
||||
|
||||
def self.search_options_for(user)
|
||||
options = actions.keys
|
||||
return options if user.is_moderator?
|
||||
options.reject { |action| MOD_ONLY_SEARCH_ACTIONS.any?(actions[action]) }
|
||||
end
|
||||
end
|
||||
|
@ -19,7 +19,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="comments">
|
||||
<%= render "comments/partials/index/list", :post => post, :comments => post.comments.visible(CurrentUser.user).recent.reverse %>
|
||||
<%= render "comments/partials/index/list", post: post, comments: post.comments.visible(CurrentUser.user).recent.reverse %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
@ -1,7 +1,18 @@
|
||||
<div class="comments-for-post" data-post-id="<%= post.id %>">
|
||||
<% if post.is_comment_disabled? %>
|
||||
Comment section has been disabled.
|
||||
<% end %>
|
||||
<% if post.is_comment_locked? %>
|
||||
Comment section has been locked.
|
||||
<% end %>
|
||||
<% if !CurrentUser.user.is_moderator? && post.is_comment_disabled? %>
|
||||
<% comments = comments.stickied %>
|
||||
<div class="list-of-comments">
|
||||
<% if comments.any? %>
|
||||
<%= render partial: "comments/partials/show/comment", collection: comments, locals: { post: post } %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="row notices">
|
||||
<% if post.comments.hidden(CurrentUser.user).count > 0 || (params[:controller] == "comments" && post.comments.count > Comment::RECENT_COUNT) %>
|
||||
<span id="threshold-comments-notice-for-<%= post.id %>">
|
||||
@ -21,8 +32,9 @@
|
||||
<%= render partial: "comments/partials/show/comment", collection: comments, locals: { post: post } %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if post.is_comment_locked? && !CurrentUser.is_moderator? %>
|
||||
<% if (post.is_comment_locked? || post.is_comment_disabled?) && !CurrentUser.is_moderator? %>
|
||||
<% elsif CurrentUser.is_member? %>
|
||||
<div class="new-comment">
|
||||
<% if !CurrentUser.is_anonymous? && !CurrentUser.user.is_janitor? %>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<%= form_search path: post_events_path do |f| %>
|
||||
<%= f.input :post_id, label: "Post #" %>
|
||||
<%= f.user :creator %>
|
||||
<%= f.input :action, label: "Action", collection: PostEvent.actions.keys.map {|k| [k.to_s.capitalize.tr("_"," "), k.to_s]}, include_blank: true %>
|
||||
<%= f.input :action, label: "Action", collection: PostEvent.search_options_for(CurrentUser.user).map { |k| [k.to_s.capitalize.tr("_"," "), k.to_s] }, include_blank: true %>
|
||||
<% end %>
|
||||
|
@ -56,6 +56,8 @@
|
||||
<%= f.input :is_rating_locked, label: "Rating" %>
|
||||
<% if CurrentUser.is_admin? %>
|
||||
<%= f.input :is_status_locked, label: "Status" %>
|
||||
<% end %>
|
||||
<% if CurrentUser.is_moderator? %>
|
||||
<%= f.input :is_comment_locked, label: "Comments" %>
|
||||
<% end %>
|
||||
</fieldset>
|
||||
@ -72,6 +74,7 @@
|
||||
<fieldset class="limits">
|
||||
<%= f.input :hide_from_anonymous, as: :boolean, label: "Hide from Anon" %>
|
||||
<%= f.input :hide_from_search_engines, as: :boolean, label: "Hide from search engines" %>
|
||||
<%= f.input :is_comment_disabled, label: "Hide comments" %>
|
||||
</fieldset>
|
||||
</div>
|
||||
<% end %>
|
||||
|
8
db/fixes/119_convert_comment_disabled_to_locked.rb
Executable file
8
db/fixes/119_convert_comment_disabled_to_locked.rb
Executable file
@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "config", "environment"))
|
||||
|
||||
Post.without_timeout do
|
||||
Post.where(is_comment_disabled: true).update_all("is_comment_locked = is_comment_disabled, is_comment_disabled = false")
|
||||
end
|
@ -0,0 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class AddIsCommentLockedToPosts < ActiveRecord::Migration[7.1]
|
||||
def change
|
||||
add_column(:posts, :is_comment_locked, :boolean, null: false, default: false)
|
||||
end
|
||||
end
|
@ -1685,7 +1685,8 @@ CREATE TABLE public.posts (
|
||||
bg_color character varying,
|
||||
generated_samples character varying[],
|
||||
duration numeric,
|
||||
is_comment_disabled boolean DEFAULT false NOT NULL
|
||||
is_comment_disabled boolean DEFAULT false NOT NULL,
|
||||
is_comment_locked boolean DEFAULT false NOT NULL
|
||||
);
|
||||
|
||||
|
||||
@ -4676,6 +4677,7 @@ ALTER TABLE ONLY public.avoid_postings
|
||||
SET search_path TO "$user", public;
|
||||
|
||||
INSERT INTO "schema_migrations" (version) VALUES
|
||||
('20240905160626'),
|
||||
('20240726170041'),
|
||||
('20240709134926'),
|
||||
('20240706061122'),
|
||||
|
@ -14,10 +14,10 @@ class CommentVotesControllerTest < ActionDispatch::IntegrationTest
|
||||
CurrentUser.user = @user
|
||||
end
|
||||
|
||||
context "#create.json" do
|
||||
context "create action" do
|
||||
should "create a vote" do
|
||||
assert_difference(-> { CommentVote.count }, 1) do
|
||||
post_auth comment_votes_path(@comment), @user, params: { score: -1, format: :json}
|
||||
assert_difference("CommentVote.count", 1) do
|
||||
post_auth comment_votes_path(@comment), @user, params: { score: -1, format: :json }
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
@ -29,6 +29,40 @@ class CommentVotesControllerTest < ActionDispatch::IntegrationTest
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
|
||||
should "prevent voting on comment locked posts" do
|
||||
@post.update(is_comment_locked: true)
|
||||
assert_no_difference("CommentVote.count") do
|
||||
post_auth comment_votes_path(@comment), @user, params: { score: -1, format: :json }
|
||||
assert_response 422
|
||||
end
|
||||
end
|
||||
|
||||
should "prevent unvoting on comment locked posts" do
|
||||
@post.update(is_comment_locked: true)
|
||||
create(:comment_vote, comment: @comment, user: @user, score: -1)
|
||||
assert_no_difference("CommentVote.count") do
|
||||
post_auth comment_votes_path(@comment), @user, params: { score: -1, format: :json }
|
||||
assert_response 422
|
||||
end
|
||||
end
|
||||
|
||||
should "prevent voting on comment disabled posts" do
|
||||
@post.update(is_comment_disabled: true)
|
||||
assert_no_difference("CommentVote.count") do
|
||||
post_auth comment_votes_path(@comment), @user, params: { score: -1, format: :json }
|
||||
assert_response 422
|
||||
end
|
||||
end
|
||||
|
||||
should "prevent unvoting on comment disabled posts" do
|
||||
@post.update(is_comment_disabled: true)
|
||||
create(:comment_vote, comment: @comment, user: @user, score: -1)
|
||||
assert_no_difference("CommentVote.count") do
|
||||
post_auth comment_votes_path(@comment), @user, params: { score: -1, format: :json }
|
||||
assert_response 422
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -108,6 +108,22 @@ class CommentsControllerTest < ActionDispatch::IntegrationTest
|
||||
assert_equal(false, @comment.reload.do_not_bump_post)
|
||||
assert_equal(@post.id, @comment.post_id)
|
||||
end
|
||||
|
||||
should "not allow changing comments on comment locked posts" do
|
||||
@post.update(is_comment_locked: true)
|
||||
body = @comment.body
|
||||
put_auth comment_path(@comment.id), @user, params: { comment: { body: "abc" } }
|
||||
assert_response(:forbidden)
|
||||
assert_equal(body, @comment.reload.body)
|
||||
end
|
||||
|
||||
should "not allow changing comments on comment disabled posts" do
|
||||
@post.update(is_comment_disabled: true)
|
||||
body = @comment.body
|
||||
put_auth comment_path(@comment.id), @user, params: { comment: { body: "abc" } }
|
||||
assert_response(:forbidden)
|
||||
assert_equal(body, @comment.reload.body)
|
||||
end
|
||||
end
|
||||
|
||||
context "new action" do
|
||||
@ -132,14 +148,39 @@ class CommentsControllerTest < ActionDispatch::IntegrationTest
|
||||
end
|
||||
assert_redirected_to comments_path
|
||||
end
|
||||
|
||||
should "not allow commenting on comment locked posts" do
|
||||
@post.update(is_comment_locked: true)
|
||||
assert_difference("Comment.count", 0) do
|
||||
post_auth comments_path, @user, params: { comment: { body: "abc", post_id: @post.id } }
|
||||
assert_redirected_to(post_path(@post))
|
||||
assert_equal("Post has comments locked", flash[:notice])
|
||||
end
|
||||
end
|
||||
|
||||
should "not allow commenting on comment disabled posts" do
|
||||
@post.update(is_comment_disabled: true)
|
||||
assert_difference("Comment.count", 0) do
|
||||
post_auth comments_path, @user, params: { comment: { body: "abc", post_id: @post.id } }
|
||||
assert_redirected_to(post_path(@post))
|
||||
assert_equal("Post has comments disabled", flash[:notice])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "hide action" do
|
||||
should "mark comment as hidden" do
|
||||
post_auth hide_comment_path(@comment.id), @user
|
||||
post_auth hide_comment_path(@comment), @user
|
||||
assert_equal(true, @comment.reload.is_hidden)
|
||||
assert_redirected_to @comment
|
||||
end
|
||||
|
||||
should "not allow hiding comments on comment disabled posts" do
|
||||
@post.update(is_comment_disabled: true)
|
||||
post_auth hide_comment_path(@comment), @user
|
||||
assert_equal(false, @comment.reload.is_hidden)
|
||||
assert_response(403)
|
||||
end
|
||||
end
|
||||
|
||||
context "unhide action" do
|
||||
@ -148,13 +189,13 @@ class CommentsControllerTest < ActionDispatch::IntegrationTest
|
||||
end
|
||||
|
||||
should "mark comment as unhidden if mod" do
|
||||
post_auth unhide_comment_path(@comment.id), @mod
|
||||
post_auth unhide_comment_path(@comment), @mod
|
||||
assert_equal(false, @comment.reload.is_hidden)
|
||||
assert_redirected_to(@comment)
|
||||
end
|
||||
|
||||
should "not mark comment as unhidden if not mod" do
|
||||
post_auth unhide_comment_path(@comment.id), @user
|
||||
post_auth unhide_comment_path(@comment), @user
|
||||
assert_equal(true, @comment.reload.is_hidden)
|
||||
assert_response :forbidden
|
||||
end
|
||||
@ -162,7 +203,7 @@ class CommentsControllerTest < ActionDispatch::IntegrationTest
|
||||
|
||||
context "destroy action" do
|
||||
should "destroy the comment" do
|
||||
delete_auth comment_path(@comment.id), create(:admin_user)
|
||||
delete_auth comment_path(@comment), create(:admin_user)
|
||||
assert_equal(0, Comment.where(id: @comment.id).count)
|
||||
end
|
||||
end
|
||||
|
@ -79,6 +79,38 @@ class PostsControllerTest < ActionDispatch::IntegrationTest
|
||||
put_auth post_path(@post), @user, params: {:post => {:last_noted_at => 1.minute.ago}}
|
||||
assert_nil(@post.reload.last_noted_at)
|
||||
end
|
||||
|
||||
should "allow moderators to lock comments" do
|
||||
assert_difference("PostEvent.count", 1) do
|
||||
put_auth post_path(@post), create(:moderator_user), params: { post: { is_comment_locked: true } }
|
||||
end
|
||||
assert_equal(true, @post.reload.is_comment_locked?)
|
||||
assert_equal("comment_locked", PostEvent.last.action)
|
||||
end
|
||||
|
||||
should "allow moderators to unlock comments" do
|
||||
@post.update_columns(is_comment_locked: true)
|
||||
assert_difference("PostEvent.count", 1) do
|
||||
put_auth post_path(@post), create(:moderator_user), params: { post: { is_comment_locked: false } }
|
||||
end
|
||||
assert_equal(false, @post.reload.is_comment_locked?)
|
||||
assert_equal("comment_unlocked", PostEvent.last.action)
|
||||
end
|
||||
|
||||
should "not allow moderators to disable comments" do
|
||||
assert_no_difference("PostEvent.count") do
|
||||
put_auth post_path(@post), create(:moderator_user), params: { post: { is_comment_disabled: true } }
|
||||
end
|
||||
assert_equal(false, @post.reload.is_comment_disabled?)
|
||||
end
|
||||
|
||||
should "not allow moderators to enable comments" do
|
||||
@post.update_columns(is_comment_disabled: true)
|
||||
assert_no_difference("PostEvent.count") do
|
||||
put_auth post_path(@post), create(:moderator_user), params: { post: { is_comment_disabled: false } }
|
||||
end
|
||||
assert_equal(true, @post.reload.is_comment_disabled?)
|
||||
end
|
||||
end
|
||||
|
||||
context "revert action" do
|
||||
|
@ -281,6 +281,18 @@ class CommentTest < ActiveSupport::TestCase
|
||||
assert_equal(["Post has comments locked"], comment.errors.full_messages)
|
||||
end
|
||||
end
|
||||
|
||||
context "on a comment disabled post" do
|
||||
setup do
|
||||
@post = create(:post, is_comment_disabled: true)
|
||||
end
|
||||
|
||||
should "prevent new comments" do
|
||||
comment = build(:comment, post: @post)
|
||||
comment.save
|
||||
assert_equal(["Post has comments disabled"], comment.errors.full_messages)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "during validation" do
|
||||
|
Loading…
Reference in New Issue
Block a user