[Cleanup] Remove post appeals

This commit is contained in:
Earlopain 2022-02-11 17:05:09 +01:00
parent 8df9c94202
commit f7ba9c5043
No known key found for this signature in database
GPG Key ID: 6CFB948E15246897
25 changed files with 4 additions and 464 deletions

View File

@ -1,38 +0,0 @@
class PostAppealsController < ApplicationController
#before_action :member_only, :except => [:index, :show]
before_action :admin_only
respond_to :html, :json
def new
@post_appeal = PostAppeal.new(post_appeal_params)
respond_with(@post_appeal)
end
def index
@post_appeals = PostAppeal.includes(:creator).search(search_params).includes(post: [:appeals, :uploader, :approver])
@post_appeals = @post_appeals.paginate(params[:page], limit: params[:limit])
respond_with(@post_appeals)
end
def create
@post_appeal = PostAppeal.create(post_appeal_params)
respond_with(@post_appeal) do |fmt|
fmt.html do
redirect_to post_path(id: @post_appeal.post_id)
end
end
end
def show
@post_appeal = PostAppeal.find(params[:id])
respond_with(@post_appeal) do |fmt|
fmt.html { redirect_to post_appeals_path(search: { id: @post_appeal.id }) }
end
end
private
def post_appeal_params
params.fetch(:post_appeal, {}).permit(%i[post_id reason])
end
end

View File

@ -1,22 +0,0 @@
module PostAppealsHelper
def post_appeal_reasons(post)
html = []
html << '<ul>'
post.appeals.each do |appeal|
reason = format_text(appeal.reason, inline: true)
user = link_to_user(appeal.creator)
if CurrentUser.is_moderator?
ip = "(#{link_to_ip(appeal.creator_ip_addr)})"
else
ip = ""
end
time = time_ago_in_words_tagged(appeal.created_at)
html << "<li>#{reason} - #{user} #{ip} #{time}</li>"
end
html << '</ul>'
html.join("\n").html_safe
end
end

View File

@ -105,7 +105,6 @@ Autocomplete.initialize_tag_autocomplete = function() {
case "noteupdater":
case "fav":
case "favoritedby":
case "appealer":
case "flagger":
case "upvote":
case "downvote":

View File

@ -341,13 +341,6 @@ div#c-posts {
}
}
&.notice-appealed {
@include themable {
background-color: themed('color-section');
border: 1px solid themed('color-foreground');
}
}
&.notice-resized {
@include themable {
background-color: themed('color-section');

View File

@ -50,7 +50,6 @@ class Post < ApplicationRecord
has_one :upload, :dependent => :destroy
has_one :pixiv_ugoira_frame_data, :class_name => "PixivUgoiraFrameData", :dependent => :destroy
has_many :flags, :class_name => "PostFlag", :dependent => :destroy
has_many :appeals, :class_name => "PostAppeal", :dependent => :destroy
has_many :votes, :class_name => "PostVote", :dependent => :destroy
has_many :notes, :dependent => :destroy
has_many :comments, -> {includes(:creator, :updater).order("comments.is_sticky DESC, comments.id")}, :dependent => :destroy
@ -367,18 +366,6 @@ class Post < ApplicationRecord
PostEvent.add(id, CurrentUser.user, :flag_removed)
end
def appeal!(reason)
if is_status_locked?
raise PostAppeal::Error.new("Post is locked and cannot be appealed")
end
appeal = appeals.create(:reason => reason)
if appeal.errors.any?
raise PostAppeal::Error.new(appeal.errors.full_messages.join("; "))
end
end
def approved_by?(user)
approver == user || approvals.where(user: user).exists?
end
@ -1599,12 +1586,6 @@ class Post < ApplicationRecord
relation
end
def with_appeal_stats
relation = left_outer_joins(:appeals).group(:id).select("posts.*")
relation = relation.select("COUNT(post_appeals.id) AS appeal_count")
relation
end
def with_approval_stats
relation = left_outer_joins(:approvals).group(:id).select("posts.*")
relation = relation.select("COUNT(post_approvals.id) AS approval_count")

View File

@ -1,105 +0,0 @@
class PostAppeal < ApplicationRecord
class Error < Exception ; end
belongs_to :creator, :class_name => "User"
belongs_to :post
validates :post, :reason, :creator_id, :creator_ip_addr, presence: true
validate :validate_post_is_inactive
validate :validate_creator_is_not_limited
before_validation :initialize_creator, :on => :create
validates :creator_id, uniqueness: { :scope => :post_id, :message => "have already appealed this post" }
module SearchMethods
def post_tags_match(query)
where(post_id: PostQueryBuilder.new(query).build.reorder(""))
end
def resolved
joins(:post).where("posts.is_deleted = false and posts.is_flagged = false")
end
def unresolved
joins(:post).where("posts.is_deleted = true or posts.is_flagged = true")
end
def for_user(user_id)
where("creator_id = ?", user_id)
end
def recent
where("created_at >= ?", 1.day.ago)
end
def for_creator(user_id)
where("creator_id = ?", user_id)
end
def search(params)
q = super
q = q.attribute_matches(:reason, params[:reason_matches])
if params[:creator_id].present?
q = q.where(creator_id: params[:creator_id].split(",").map(&:to_i))
end
if params[:creator_name].present?
q = q.where("creator_id = (select _.id from users _ where lower(_.name) = ?)", params[:creator_name].mb_chars.downcase.strip.tr(" ", "_"))
end
if params[:post_id].present?
q = q.where(post_id: params[:post_id].split(",").map(&:to_i))
end
if params[:post_tags_match].present?
q = q.post_tags_match(params[:post_tags_match])
end
q = q.resolved if params[:is_resolved].to_s.truthy?
q = q.unresolved if params[:is_resolved].to_s.falsy?
q.apply_default_order(params)
end
end
extend SearchMethods
def resolved?
post.present? && !post.is_deleted? && !post.is_flagged?
end
def is_resolved
resolved?
end
def validate_creator_is_not_limited
if appeal_count_for_creator >= Danbooru.config.max_appeals_per_day
errors.add(:creator, "can appeal at most #{Danbooru.config.max_appeals_per_day} post a day")
false
else
true
end
end
def validate_post_is_inactive
if resolved?
errors.add(:post, "is active")
false
else
true
end
end
def initialize_creator
self.creator_id = CurrentUser.id
self.creator_ip_addr = CurrentUser.ip_addr
end
def appeal_count_for_creator
PostAppeal.for_user(creator_id).recent.count
end
def method_attributes
super + [:is_resolved]
end
end

View File

@ -19,12 +19,12 @@ class Tag < ApplicationRecord
-locked locked width height mpixels ratio score favcount filesize source
-source id -id date age order limit -status status tagcount parent -parent
child pixiv_id pixiv search upvote downvote voted filetype -filetype flagger type -type
-flagger appealer -appealer disapproval -disapproval set -set randseed -voted
-flagger disapproval -disapproval set -set randseed -voted
-upvote -downvote description -description change -user_id user_id delreason -delreason
deletedby -deletedby votedup voteddown -votedup -voteddown duration
] + TagCategory.short_name_list.map {|x| "#{x}tags"} + COUNT_METATAGS + BOOLEAN_METATAGS
SUBQUERY_METATAGS = %w[commenter comm noter noteupdater flagger -flagger appealer -appealer]
SUBQUERY_METATAGS = %w[commenter comm noter noteupdater flagger -flagger]
ORDER_METATAGS = %w[
id id_desc

View File

@ -689,7 +689,7 @@ class User < ApplicationRecord
[
:wiki_page_version_count, :artist_version_count, :pool_version_count,
:forum_post_count, :comment_count,
:appeal_count, :flag_count, :positive_feedback_count,
:flag_count, :positive_feedback_count,
:neutral_feedback_count, :negative_feedback_count, :upload_limit
]
end
@ -740,10 +740,6 @@ class User < ApplicationRecord
user_status.comment_count
end
def appeal_count
PostAppeal.for_creator(id).count
end
def flag_count
user_status.post_flag_count
end

View File

@ -132,10 +132,6 @@ class UserPresenter
template.link_to(user.pool_version_count, template.pool_versions_path(:search => {:updater_id => user.id}))
end
def appeal_count(template)
template.link_to(user.appeal_count, template.post_appeals_path(:search => {:creator_name => user.name}))
end
def flag_count(template)
template.link_to(user.flag_count, template.post_flags_path(:search => {:creator_name => user.name}))
end

View File

@ -21,9 +21,6 @@
<% if post.is_flagged? %>
<li><strong>Flagged</strong>: <%= post_flag_reasons(post) %></li>
<% end %>
<% if (post.is_flagged? || post.is_deleted?) && post.appeals.any? %>
<li><strong>Appeals</strong>: <%= post_appeal_reasons(post) %></li>
<% end %>
<li>
<strong>Hidden</strong>: <%= render "post_disapprovals/compact_counts", :disapprovals => post.disapprovals, :post => post %>
</li>

View File

@ -1,13 +0,0 @@
<div class="appeal-dialog-body">
<div class="dtext-container">
<%= format_text(WikiPage.titled(Danbooru.config.appeal_notice_wiki_page).first.try(&:body)) %>
</div>
<%# XXX dtext_field expects there to be a `post_appeal` instance variable. %>
<% @post_appeal = post_appeal %>
<%= simple_form_for(@post_appeal) do |f| %>
<%= f.hidden_field :post_id %>
<%= dtext_field "post_appeal", "reason", type: "string" %>
<%= f.submit "Submit" %>
<% end %>
</div>

View File

@ -1,8 +0,0 @@
<%= simple_form_for(:search, url: post_appeals_path, method: :get, defaults: { required: false }, html: { class: "inline-form" }) do |f| %>
<%= f.input :reason_matches, label: "Reason", hint: "Use * for wildcard searches", input_html: { value: params[:search][:reason_matches] } %>
<%= f.input :post_tags_match, label: "Tags", input_html: { value: params[:search][:post_tags_match], data: { autocomplete: "tag-query" } } %>
<%= f.input :post_id, label: "Post ID", input_html: { value: params[:search][:post_id] } %>
<%= f.input :creator_name, label: "Creator", input_html: { value: params[:search][:creator_name], data: { autocomplete: "user" } } %>
<%= f.input :is_resolved, label: "Resolved?", collection: [["Yes", true], ["No", false]], include_blank: true, selected: params[:search][:is_resolved] %>
<%= f.submit "Search" %>
<% end %>

View File

@ -1,59 +0,0 @@
<div id="c-post-appeals">
<div id="a-index">
<h1>Appeals</h1>
<%= render "search" %>
<%= render "posts/partials/common/inline_blacklist" %>
<table width="100%" class="striped">
<thead>
<tr>
<th width="1%">Post</th>
<th>Reason</th>
<th width="1%">Appeals</th>
<th width="5%">Resolved?</th>
<th width="15%">Uploaded</th>
<th width="15%">Appealed</th>
<th width="15%">Approver</th>
</tr>
</thead>
<tbody>
<% @post_appeals.each do |post_appeal| %>
<tr>
<td><%= PostPresenter.preview(post_appeal.post, :tags => "status:any") %></td>
<td><%= format_text post_appeal.reason %></td>
<td>
<%= link_to post_appeal.post.appeals.size, post_appeals_path(search: { post_id: post_appeal.post_id }) %>
</td>
<td>
<%= link_to post_appeal.is_resolved.to_s, post_appeals_path(search: params[:search].merge(is_resolved: post_appeal.is_resolved)) %>
</td>
<td>
<%= compact_time post_appeal.post.created_at %>
<br> by <%= link_to_user post_appeal.post.uploader %>
<%= link_to "»", post_appeals_path(search: params[:search].merge(post_tags_match: "#{params[:search][:post_tags_match]} user:#{post_appeal.post.uploader.name}".strip)) %>
</td>
<td>
<%= compact_time post_appeal.created_at %>
<br> by <%= link_to_user post_appeal.creator %>
<%= link_to "»", post_appeals_path(search: params[:search].merge(creator_name: post_appeal.creator.name)) %>
</td>
<td>
<% if post_appeal.post.approver %>
<%= link_to_user post_appeal.post.approver %>
<%= link_to "»", post_appeals_path(search: params[:search].merge(post_tags_match: "#{params[:search][:post_tags_match]} approver:#{post_appeal.post.approver.name}".strip)) %>
<% else %>
<em>none</em>
<%= link_to "»", post_appeals_path(search: params[:search].merge(post_tags_match: "#{params[:search][:post_tags_match]} approver:none".strip)) %>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
<%= numbered_paginator(@post_appeals) %>
</div>
</div>
<% content_for(:page_title) do %>
Appeals
<% end %>

View File

@ -1,9 +0,0 @@
<div id="c-post-appeals">
<div id="a-new">
<%= render "post_appeals/new", post_appeal: @post_appeal %>
</div>
</div>
<% content_for(:page_title) do %>
New Appeal - #<%= @post_appeal.post_id %>
<% end %>

View File

@ -47,10 +47,3 @@
<p>This post has <%= fast_link_to "pending replacements.", post_replacements_path(:search => {:post_id => @post.id}) %></p>
</div>
<% end %>
<% if CurrentUser.is_janitor? && (post.is_flagged? || post.is_deleted?) && post.appeals.any? %>
<div class="notice notice-appealed">
<p>This post was appealed:</p>
<%= post_appeal_reasons(post) %>
</div>
<% end %>

View File

@ -63,11 +63,4 @@
<p>This post has <%= fast_link_to "pending replacements.", post_replacements_path(:search => {:post_id => @post.id}) %></p>
</div>
<% end %>
<% if !CurrentUser.is_janitor? && (post.is_flagged? || post.is_deleted?) && post.appeals.any? %>
<div class="notice notice-appealed">
<p>This post was appealed:</p>
<%= post_appeal_reasons(post) %>
</div>
<% end %>
</div>

View File

@ -114,7 +114,7 @@
<% if CurrentUser.user.id == user.id || CurrentUser.is_janitor? %>
<tr>
<th>Appeals</th>
<td><%= presenter.appeal_count(self) %></td>
<td>0</td> <!-- FIXME: Remove this. Restructure table to make it easier to add/remove single entries. -->
<th>Flags</th>
<td><%= presenter.flag_count(self) %></td>
</tr>

View File

@ -763,10 +763,6 @@ fart'
"help:flag_notice"
end
def appeal_notice_wiki_page
"help:appeal_notice"
end
def replacement_notice_wiki_page
"help:replacement_notice"
end
@ -802,10 +798,6 @@ fart'
posts.select {|x| can_user_see_post?(user, x)}
end
def max_appeals_per_day
1
end
# Counting every post is typically expensive because it involves a sequential scan on
# potentially millions of rows. If this method returns a value, then blank searches
# will return that number for the fast_count call instead.

View File

@ -19,9 +19,6 @@ en:
post_vote:
user: "You"
user_id: "You"
post_appeal:
creator: "You"
creator_id: "You"
post_disapproval:
post: "You"
post_id: "You"

View File

@ -277,7 +277,6 @@ Rails.application.routes.draw do
end
end
resources :post_events, only: :index
resources :post_appeals
resources :post_flags, except: [:destroy]
resources :post_approvals, only: [:index]
resources :post_versions, :only => [:index, :search] do

View File

@ -1,5 +0,0 @@
FactoryBot.define do
factory(:post_appeal) do
reason { "xxx" }
end
end

View File

@ -124,20 +124,6 @@ module Moderator
assert_response :success
end
end
context "for appeals" do
setup do
as(@user) do
@post = create(:post, :is_deleted => true)
@post.appeal!("blah")
end
end
should "render" do
get_auth moderator_dashboard_path, @admin
assert_response :success
end
end
end
end
end

View File

@ -1,52 +0,0 @@
require 'test_helper'
class PostAppealsControllerTest < ActionDispatch::IntegrationTest
context "The post appeals controller" do
setup do
@user = create(:user)
end
context "new action" do
should "render" do
get_auth new_post_appeal_path, @user
assert_response :success
end
end
context "index action" do
setup do
as_user do
@post = create(:post, :is_deleted => true)
@post_appeal = create(:post_appeal, :post => @post)
end
end
should "render" do
get_auth post_appeals_path, @user
assert_response :success
end
context "with search parameters" do
should "render" do
get_auth post_appeals_path, @user, params: {:search => {:post_id => @post_appeal.post_id}}
assert_response :success
end
end
end
context "create action" do
setup do
as_user do
@post = create(:post, :is_deleted => true)
end
end
should "create a new appeal" do
assert_difference("PostAppeal.count", 1) do
post_auth post_appeals_path, @user, params: {:format => "js", :post_appeal => {:post_id => @post.id, :reason => "xxx"}}
assert_response :success
end
end
end
end
end

View File

@ -1,57 +0,0 @@
require 'test_helper'
class PostAppealTest < ActiveSupport::TestCase
context "In all cases" do
setup do
@alice = FactoryBot.create(:user)
CurrentUser.user = @alice
CurrentUser.ip_addr = "127.0.0.1"
Danbooru.config.stubs(:max_appeals_per_day).returns(5)
end
teardown do
CurrentUser.user = nil
CurrentUser.ip_addr = nil
end
context "a user" do
setup do
@post = FactoryBot.create(:post, :tag_string => "aaa", :is_deleted => true)
end
should "not be able to appeal a post more than twice" do
assert_difference("PostAppeal.count", 1) do
@post_appeal = PostAppeal.create(:post => @post, :reason => "aaa")
end
assert_difference("PostAppeal.count", 0) do
@post_appeal = PostAppeal.create(:post => @post, :reason => "aaa")
end
assert_equal(["You have already appealed this post"], @post_appeal.errors.full_messages)
end
should "not be able to appeal more than 5 posts in 24 hours" do
@post_appeal = PostAppeal.new(:post => @post, :reason => "aaa")
@post_appeal.expects(:appeal_count_for_creator).returns(5)
assert_difference("PostAppeal.count", 0) do
@post_appeal.save
end
assert_equal(["You can appeal at most 5 post a day"], @post_appeal.errors.full_messages)
end
should "not be able to appeal an active post" do
@post.update_attribute(:is_deleted, false)
assert_difference("PostAppeal.count", 0) do
@post_appeal = PostAppeal.create(:post => @post, :reason => "aaa")
end
assert_equal(["Post is active"], @post_appeal.errors.full_messages)
end
should "initialize its creator" do
@post_appeal = PostAppeal.create(:post => @post, :reason => "aaa")
assert_equal(@alice.id, @post_appeal.creator_id)
end
end
end
end

View File

@ -451,14 +451,6 @@ class PostTest < ActiveSupport::TestCase
assert_equal(false, @post.reload.is_deleted?)
end
end
should "be appealed" do
assert_difference("PostAppeal.count", 1) do
@post.appeal!("xxx")
end
assert(@post.is_deleted?, "Post should still be deleted")
assert_equal(1, @post.appeals.count)
end
end
context "An approved post" do
@ -523,12 +515,6 @@ class PostTest < ActiveSupport::TestCase
assert_equal(["Post is locked and cannot be flagged"], flag.errors.full_messages)
end
should "not allow new appeals" do
assert_raises(PostAppeal::Error) do
@post.appeal!("wrong")
end
end
should "not allow approval" do
approval = @post.approve!
assert_includes(approval.errors.full_messages, "Post is locked and cannot be approved")