forked from e621ng/e621ng
Merge pull request #284 from Earlopain/replacements-audit
Add replacement tracking for uploader
This commit is contained in:
commit
0d531ff146
@ -1,7 +1,7 @@
|
||||
class PostReplacementsController < ApplicationController
|
||||
respond_to :html
|
||||
respond_to :html, :json
|
||||
before_action :moderator_only, only: [:destroy]
|
||||
before_action :janitor_only, only: [:create, :new, :approve, :reject, :promote]
|
||||
before_action :janitor_only, only: [:create, :new, :approve, :reject, :promote, :toggle_penalize]
|
||||
content_security_policy only: [:new] do |p|
|
||||
p.img_src :self, :data, "*"
|
||||
end
|
||||
@ -15,48 +15,57 @@ class PostReplacementsController < ApplicationController
|
||||
def create
|
||||
@post = Post.find(params[:post_id])
|
||||
@post_replacement = @post.replacements.create(create_params.merge(creator_id: CurrentUser.id, creator_ip_addr: CurrentUser.ip_addr))
|
||||
if @post_replacement.errors.size == 0
|
||||
flash[:notice] = "Post replacement submitted"
|
||||
else
|
||||
if @post_replacement.errors.any?
|
||||
flash[:notice] = @post_replacement.errors.full_messages.join('; ')
|
||||
else
|
||||
flash[:notice] = "Post replacement submitted"
|
||||
end
|
||||
respond_with(@post_replacement, location: @post)
|
||||
end
|
||||
|
||||
def approve
|
||||
@post_replacement = PostReplacement.find(params[:id])
|
||||
@post_replacement.approve!
|
||||
@post_replacement.approve!(penalize_current_uploader: params[:penalize_current_uploader])
|
||||
|
||||
respond_with(@post_replacement, location: post_path(@post_replacement.post))
|
||||
end
|
||||
|
||||
def toggle_penalize
|
||||
@post_replacement = PostReplacement.find(params[:id])
|
||||
@post_replacement.toggle_penalize!
|
||||
|
||||
respond_with(@post_replacement)
|
||||
end
|
||||
|
||||
def reject
|
||||
@post_replacement = PostReplacement.find(params[:id])
|
||||
@post_replacement.reject!
|
||||
|
||||
respond_with(@post_replacement)
|
||||
respond_with(@post_replacement, location: post_path(@post_replacement.post))
|
||||
end
|
||||
|
||||
def destroy
|
||||
@post_replacement = PostReplacement.find(params[:id])
|
||||
@post_replacement.destroy
|
||||
|
||||
respond_with(@post_replacement)
|
||||
respond_with(@post_replacement, location: post_path(@post_replacement.post))
|
||||
end
|
||||
|
||||
def promote
|
||||
@post_replacement = PostReplacement.find(params[:id])
|
||||
@post = @post_replacement.promote!
|
||||
if @post.errors.any?
|
||||
respond_with(@post)
|
||||
@upload = @post_replacement.promote!
|
||||
if @post_replacement.errors.any?
|
||||
respond_with(@post_replacement)
|
||||
elsif @upload.errors.any?
|
||||
respond_with(@upload)
|
||||
else
|
||||
respond_with(@post.post)
|
||||
respond_with(@upload.post)
|
||||
end
|
||||
end
|
||||
|
||||
def index
|
||||
params[:search][:post_id] = params.delete(:post_id) if params.has_key?(:post_id)
|
||||
@post_replacements = PostReplacement.visible(CurrentUser.user).search(search_params).paginate(params[:page], limit: params[:limit])
|
||||
@post_replacements = PostReplacement.includes(:post).visible(CurrentUser.user).search(search_params).paginate(params[:page], limit: params[:limit])
|
||||
|
||||
respond_with(@post_replacements)
|
||||
end
|
||||
|
@ -1,6 +1,10 @@
|
||||
module PostReplacementHelper
|
||||
def replacement_thumbnail(replacement)
|
||||
return tag.a(image_tag(replacement.replacement_thumb_url), href: replacement.replacement_file_url) if replacement.file_visible_to?(CurrentUser.user)
|
||||
image_tag(replacement.replacement_thumb_url)
|
||||
if replacement.post.deleteblocked?
|
||||
image_tag(Danbooru.config.deleted_preview_url)
|
||||
else
|
||||
image_tag(replacement.replacement_thumb_url)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -37,6 +37,7 @@ export { default as Note } from '../src/javascripts/notes.js';
|
||||
export { default as Post } from '../src/javascripts/posts.js';
|
||||
export { default as PostDeletion } from "../src/javascripts/post_delete.js";
|
||||
export { default as PostModeMenu } from '../src/javascripts/post_mode_menu.js';
|
||||
export { default as PostReplacement } from '../src/javascripts/post_replacement.js';
|
||||
export { default as PostVersions } from '../src/javascripts/post_versions.js';
|
||||
export { default as RelatedTag } from '../src/javascripts/related_tag.js';
|
||||
export { default as Shortcuts } from '../src/javascripts/shortcuts.js';
|
||||
|
82
app/javascript/src/javascripts/post_replacement.js
Normal file
82
app/javascript/src/javascripts/post_replacement.js
Normal file
@ -0,0 +1,82 @@
|
||||
import Utility from './utility'
|
||||
|
||||
let PostReplacement = {};
|
||||
|
||||
PostReplacement.initialize_all = function () {
|
||||
$(".replacement-approve-action").on("click", e => {
|
||||
const target = $(e.target);
|
||||
e.preventDefault();
|
||||
PostReplacement.approve(target.data("replacement-id"), target.data("penalize"));
|
||||
});
|
||||
$(".replacement-reject-action").on("click", e => {
|
||||
e.preventDefault();
|
||||
PostReplacement.reject($(e.target).data("replacement-id"));
|
||||
});
|
||||
$(".replacement-promote-action").on("click", e => {
|
||||
e.preventDefault();
|
||||
PostReplacement.promote($(e.target).data("replacement-id"));
|
||||
});
|
||||
$(".replacement-toggle-penalize-action").on("click", e => {
|
||||
e.preventDefault();
|
||||
PostReplacement.toggle_penalize($(e.target).data("replacement-id"));
|
||||
});
|
||||
};
|
||||
|
||||
PostReplacement.approve = function (id, penalize_current_uploader) {
|
||||
$.ajax({
|
||||
type: "PUT",
|
||||
url: `/post_replacements/${id}/approve.json`,
|
||||
data: {
|
||||
penalize_current_uploader: penalize_current_uploader
|
||||
},
|
||||
dataType: 'json'
|
||||
}).done(function () {
|
||||
Utility.notice("Post Replacement accepted");
|
||||
}).fail(function (data, status, xhr) {
|
||||
Utility.error(data.responseText);
|
||||
});
|
||||
};
|
||||
|
||||
PostReplacement.reject = function (id) {
|
||||
$.ajax({
|
||||
type: "PUT",
|
||||
url: `/post_replacements/${id}/reject.json`,
|
||||
dataType: 'json'
|
||||
}).done(function () {
|
||||
Utility.notice("Post Replacement rejected");
|
||||
}).fail(function (data, status, xhr) {
|
||||
Utility.error(data.responseText);
|
||||
});
|
||||
}
|
||||
|
||||
PostReplacement.promote = function (id) {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: `/post_replacements/${id}/promote.json`,
|
||||
dataType: 'json'
|
||||
}).done(function (data) {
|
||||
Utility.notice(`Replacement promoted to post #${data.post.id}`)
|
||||
}).fail(function (data, status, xhr) {
|
||||
Utility.error(data.responseText);
|
||||
});
|
||||
}
|
||||
|
||||
PostReplacement.toggle_penalize = function (id) {
|
||||
$.ajax({
|
||||
type: "PUT",
|
||||
url: `/post_replacements/${id}/toggle_penalize.json`,
|
||||
dataType: 'json'
|
||||
}).done(function (data) {
|
||||
Utility.notice("User upload limit updated");
|
||||
}).fail(function (data, status, xhr) {
|
||||
Utility.error(data.responseText);
|
||||
});
|
||||
}
|
||||
|
||||
$(function () {
|
||||
if ($("#c-post-replacements").length)
|
||||
PostReplacement.initialize_all();
|
||||
});
|
||||
|
||||
|
||||
export default PostReplacement
|
@ -35,7 +35,7 @@ class UploadService
|
||||
raise ProcessingError, "Could not create post file backup?" if !repl.valid?
|
||||
end
|
||||
|
||||
def process!
|
||||
def process!(penalize_current_uploader:)
|
||||
# Prevent trying to replace deleted posts
|
||||
raise ProcessingError, "Cannot replace post: post is deleted." if post.is_deleted?
|
||||
|
||||
@ -76,6 +76,8 @@ class UploadService
|
||||
post.generated_samples = nil
|
||||
end
|
||||
|
||||
previous_uploader = post.uploader_id
|
||||
|
||||
post.md5 = upload.md5
|
||||
post.file_ext = upload.file_ext
|
||||
post.image_width = upload.image_width
|
||||
@ -88,10 +90,22 @@ class UploadService
|
||||
post.uploader_ip_addr = replacement.creator_ip_addr
|
||||
post.save!
|
||||
|
||||
|
||||
# rescaling notes reloads the post, be careful when accessing previous values
|
||||
rescale_notes(post)
|
||||
update_ugoira_frame_data(post, upload)
|
||||
|
||||
replacement.update({status: 'approved', approver_id: CurrentUser.id})
|
||||
replacement.update({
|
||||
status: 'approved',
|
||||
approver_id: CurrentUser.id,
|
||||
uploader_id_on_approve: previous_uploader,
|
||||
penalize_uploader_on_approve: penalize_current_uploader.to_s.truthy?
|
||||
})
|
||||
|
||||
UserStatus.for_user(previous_uploader).update_all("own_post_replaced_count = own_post_replaced_count + 1")
|
||||
if penalize_current_uploader.to_s.truthy?
|
||||
UserStatus.for_user(previous_uploader).update_all("own_post_replaced_penalize_count = own_post_replaced_penalize_count + 1")
|
||||
end
|
||||
|
||||
if post.is_video?
|
||||
post.generate_video_samples(later: true)
|
||||
|
@ -3,6 +3,7 @@ class PostReplacement < ApplicationRecord
|
||||
belongs_to :post
|
||||
belongs_to :creator, class_name: "User"
|
||||
belongs_to :approver, class_name: "User", optional: true
|
||||
belongs_to :uploader_on_approve, class_name: "User", foreign_key: :uploader_id_on_approve, optional: true
|
||||
attr_accessor :replacement_file, :replacement_url, :final_source, :tags, :is_backup
|
||||
|
||||
validate :user_is_not_limited, on: :create
|
||||
@ -168,33 +169,63 @@ class PostReplacement < ApplicationRecord
|
||||
|
||||
module ApiMethods
|
||||
def hidden_attributes
|
||||
super + [:storage_id]
|
||||
super + %i[storage_id protected uploader_id_on_approve penalize_uploader_on_approve]
|
||||
end
|
||||
end
|
||||
|
||||
module ProcessingMethods
|
||||
def approve!
|
||||
def approve!(penalize_current_uploader:)
|
||||
unless ["pending", "original"].include? status
|
||||
errors.add(:status, "must be pending or original to approve")
|
||||
return
|
||||
end
|
||||
|
||||
transaction do
|
||||
ModAction.log(:post_replacement_accept, {post_id: post.id, replacement_id: self.id, old_md5: post.md5, new_md5: self.md5})
|
||||
processor = UploadService::Replacer.new(post: post, replacement: self)
|
||||
processor.process!
|
||||
processor.process!(penalize_current_uploader: penalize_current_uploader)
|
||||
end
|
||||
post.update_index
|
||||
end
|
||||
|
||||
def toggle_penalize!
|
||||
if status != "approved"
|
||||
errors.add(:status, "must be approved to penalize")
|
||||
return
|
||||
end
|
||||
|
||||
if penalize_uploader_on_approve
|
||||
UserStatus.for_user(uploader_on_approve).update_all("own_post_replaced_penalize_count = own_post_replaced_penalize_count - 1")
|
||||
else
|
||||
UserStatus.for_user(uploader_on_approve).update_all("own_post_replaced_penalize_count = own_post_replaced_penalize_count + 1")
|
||||
end
|
||||
update_attribute(:penalize_uploader_on_approve, !penalize_uploader_on_approve)
|
||||
end
|
||||
|
||||
def promote!
|
||||
if status != "pending"
|
||||
errors.add(:status, "must be pending to promote")
|
||||
return
|
||||
end
|
||||
|
||||
transaction do
|
||||
processor = UploadService.new(new_upload_params)
|
||||
new_post = processor.start!
|
||||
new_upload = processor.start!
|
||||
update_attribute(:status, 'promoted')
|
||||
new_post
|
||||
new_upload
|
||||
end
|
||||
post.update_index
|
||||
end
|
||||
|
||||
def reject!
|
||||
if status != "pending"
|
||||
errors.add(:status, "must be pending to reject")
|
||||
return
|
||||
end
|
||||
|
||||
ModAction.log(:post_replacement_reject, {post_id: post.id, replacement_id: self.id})
|
||||
update_attribute(:status, 'rejected')
|
||||
UserStatus.for_user(creator_id).update_all("post_replacement_rejected_count = post_replacement_rejected_count + 1")
|
||||
post.update_index
|
||||
end
|
||||
end
|
||||
@ -226,15 +257,23 @@ class PostReplacement < ApplicationRecord
|
||||
q = q.attribute_exact_matches(:status, params[:status])
|
||||
|
||||
if params[:creator_id].present?
|
||||
q = q.where(creator_id: params[:creator_id].split(",").map(&:to_i))
|
||||
q = q.where("creator_id in (?)", params[:creator_id].split(",").first(100).map(&:to_i))
|
||||
end
|
||||
|
||||
if params[:creator_name].present?
|
||||
q = q.where(creator_id: User.name_to_id(params[:creator_name]))
|
||||
q = q.where("creator_id = ?", User.name_to_id(params[:creator_name]))
|
||||
end
|
||||
|
||||
if params[:uploader_id_on_approve].present?
|
||||
q = q.where("uploader_id_on_approve in (?)", params[:uploader_id_on_approve].split(",").first(100).map(&:to_i))
|
||||
end
|
||||
|
||||
if params[:uploader_name_on_approve].present?
|
||||
q = q.where("uploader_id_on_approve = ?", User.name_to_id(params[:uploader_name_on_approve]))
|
||||
end
|
||||
|
||||
if params[:post_id].present?
|
||||
q = q.where(post_id: params[:post_id].split(",").map(&:to_i))
|
||||
q = q.where("post_id in (?)", params[:post_id].split(",").first(100).map(&:to_i))
|
||||
end
|
||||
|
||||
|
||||
@ -257,6 +296,18 @@ class PostReplacement < ApplicationRecord
|
||||
where(creator_id: id.to_i)
|
||||
end
|
||||
|
||||
def for_uploader_on_approve(id)
|
||||
where(uploader_id_on_approve: id.to_i)
|
||||
end
|
||||
|
||||
def penalized
|
||||
where(penalize_uploader_on_approve: true)
|
||||
end
|
||||
|
||||
def not_penalized
|
||||
where(penalize_uploader_on_approve: false)
|
||||
end
|
||||
|
||||
def visible(user)
|
||||
return where('status != ?', 'rejected') if user.is_anonymous?
|
||||
return all if user.is_janitor?
|
||||
|
@ -584,7 +584,8 @@ class User < ApplicationRecord
|
||||
|
||||
def upload_limit_pieces
|
||||
deleted_count = Post.deleted.for_user(id).count
|
||||
rejected_replacement_count = PostReplacement.rejected.for_user(id).count
|
||||
rejected_replacement_count = post_replacement_rejected_count
|
||||
replaced_penalize_count = own_post_replaced_penalize_count
|
||||
unapproved_count = Post.pending_or_flagged.for_user(id).count
|
||||
unapproved_replacements_count = PostReplacement.pending.for_user(id).count
|
||||
approved_count = Post.for_user(id).where('is_flagged = false AND is_deleted = false AND is_pending = false').count
|
||||
@ -758,6 +759,18 @@ class User < ApplicationRecord
|
||||
feedback.negative.count
|
||||
end
|
||||
|
||||
def post_replacement_rejected_count
|
||||
user_status.post_replacement_rejected_count
|
||||
end
|
||||
|
||||
def own_post_replaced_count
|
||||
user_status.own_post_replaced_count
|
||||
end
|
||||
|
||||
def own_post_replaced_penalize_count
|
||||
user_status.own_post_replaced_penalize_count
|
||||
end
|
||||
|
||||
def refresh_counts!
|
||||
self.class.without_timeout do
|
||||
UserStatus.where(user_id: id).update_all(
|
||||
|
@ -78,6 +78,10 @@ class UserPresenter
|
||||
template.link_to(user.post_deleted_count, template.deleted_posts_path(user_id: user.id))
|
||||
end
|
||||
|
||||
def replaced_upload_count(template)
|
||||
template.link_to(user.own_post_replaced_count, template.post_replacements_path(search: {uploader_name_on_approve: user.name}))
|
||||
end
|
||||
|
||||
def favorite_count(template)
|
||||
template.link_to(user.favorite_count, template.favorites_path(:user_id => user.id))
|
||||
end
|
||||
|
@ -2,6 +2,7 @@
|
||||
<%= f.input :md5, label: "MD5", input_html: { value: params.dig(:search, :md5) } %>
|
||||
<%= f.input :creator_name, label: "Creator", input_html: { value: params.dig(:search, :creator_name) } %>
|
||||
<%= f.input :post_id, label: "Post ID", input_html: { value: params.dig(:search, :post_id) } %>
|
||||
<%= f.input :uploader_name_on_approve, label: "Uploader on Approve", input_html: { value: params.dig(:search, :uploader_name_on_approve) } %>
|
||||
<%= f.input :status, label: "status", collection: ["pending", "rejected", "approved", "promoted"], include_blank: true, selected: params.dig(:search, :status) %>
|
||||
<%= f.submit "Search" %>
|
||||
<% end %>
|
||||
|
@ -70,6 +70,14 @@
|
||||
<dt>Reason</dt>
|
||||
<dd><%= post_replacement.reason %></dd>
|
||||
<% if post_replacement.status == 'approved' %>
|
||||
<dt>Original Uploader</dt>
|
||||
<dd>
|
||||
<%= link_to_user post_replacement.uploader_on_approve %>
|
||||
<% if CurrentUser.is_janitor? %>
|
||||
| penalized: <%= post_replacement.penalize_uploader_on_approve ? "yes" : "no" %>
|
||||
<%= link_to "toggle", "#toggle", class: "replacement-toggle-penalize-action", data: { replacement_id: post_replacement.id} %><br>
|
||||
<% end %>
|
||||
</dd>
|
||||
<dt>Approver</dt>
|
||||
<dd><%= link_to_user post_replacement.approver %></dd>
|
||||
<% end %>
|
||||
@ -84,9 +92,15 @@
|
||||
|
||||
<td>
|
||||
<% if CurrentUser.is_janitor? %>
|
||||
<%= link_to "Approve", approve_post_replacement_path(post_replacement), method: :PUT %><br>
|
||||
<%= link_to "Reject", reject_post_replacement_path(post_replacement), method: :PUT %><br>
|
||||
<%= link_to "As New Post", promote_post_replacement_path(post_replacement), method: :PUT %><br>
|
||||
<% if post_replacement.status == "pending"%>
|
||||
<%= link_to "Approve And Penalize Current Uploader", "#approve", class: "replacement-approve-action", data: { replacement_id: post_replacement.id, penalize: true} %><br>
|
||||
<%= link_to "Approve", "#approve", class: "replacement-approve-action", data: { replacement_id: post_replacement.id, penalize: false} %><br>
|
||||
<%= link_to "Reject", "#reject", class: "replacement-reject-action", data: { replacement_id: post_replacement.id} %><br>
|
||||
<%= link_to "As New Post", "#promote", class: "replacement-promote-action", data: { replacement_id: post_replacement.id} %><br>
|
||||
<% end %>
|
||||
<% if post_replacement.status == "original" %>
|
||||
<%= link_to "Reset To", "#approve", class: "replacement-approve-action", data: { replacement_id: post_replacement.id, penalize: false} %><br>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% if CurrentUser.is_moderator? %>
|
||||
<%= link_to "Destroy", post_replacement_path(post_replacement), method: :DELETE, 'data-confirm': 'Are you sure you want to destroy this replacement?' %>
|
||||
|
@ -57,12 +57,13 @@
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Deleted Posts</th>
|
||||
<th>Deleted/Replaced Posts</th>
|
||||
<td>
|
||||
<%= presenter.deleted_upload_count(self) %>
|
||||
<% if CurrentUser.is_moderator? %>
|
||||
[<%= link_to "sample", posts_path(:tags => "user:#{user.name} order:random limit:300 status:deleted") %>]
|
||||
<% end %>
|
||||
/ <%= presenter.replaced_upload_count(self) %>
|
||||
</td>
|
||||
<th>Post Changes</th>
|
||||
<td>
|
||||
|
@ -250,7 +250,8 @@ Rails.application.routes.draw do
|
||||
member do
|
||||
put :approve
|
||||
put :reject
|
||||
put :promote
|
||||
post :promote
|
||||
put :toggle_penalize
|
||||
end
|
||||
end
|
||||
resources :deleted_posts, only: [:index]
|
||||
|
9
db/migrate/20210625155528_add_replacement_audit_stats.rb
Normal file
9
db/migrate/20210625155528_add_replacement_audit_stats.rb
Normal file
@ -0,0 +1,9 @@
|
||||
class AddReplacementAuditStats < ActiveRecord::Migration[6.1]
|
||||
def change
|
||||
add_column :post_replacements2, :uploader_id_on_approve, :int
|
||||
add_column :post_replacements2, :penalize_uploader_on_approve, :boolean
|
||||
add_column :user_statuses, :own_post_replaced_count, :int, nil: false, default: 0
|
||||
add_column :user_statuses, :own_post_replaced_penalize_count, :int, nil: false, default: 0
|
||||
add_column :user_statuses, :post_replacement_rejected_count, :int, nil: false, default: 0
|
||||
end
|
||||
end
|
@ -1638,7 +1638,9 @@ CREATE TABLE public.post_replacements2 (
|
||||
storage_id character varying NOT NULL,
|
||||
status character varying DEFAULT 'pending'::character varying NOT NULL,
|
||||
reason character varying NOT NULL,
|
||||
protected boolean DEFAULT false NOT NULL
|
||||
protected boolean DEFAULT false NOT NULL,
|
||||
uploader_id_on_approve integer,
|
||||
penalize_uploader_on_approve boolean
|
||||
);
|
||||
|
||||
|
||||
@ -2588,7 +2590,10 @@ CREATE TABLE public.user_statuses (
|
||||
pool_edit_count integer DEFAULT 0 NOT NULL,
|
||||
blip_count integer DEFAULT 0 NOT NULL,
|
||||
set_count integer DEFAULT 0 NOT NULL,
|
||||
artist_edit_count integer DEFAULT 0 NOT NULL
|
||||
artist_edit_count integer DEFAULT 0 NOT NULL,
|
||||
own_post_replaced_count integer DEFAULT 0,
|
||||
own_post_replaced_penalize_count integer DEFAULT 0,
|
||||
post_replacement_rejected_count integer DEFAULT 0
|
||||
);
|
||||
|
||||
|
||||
@ -5263,6 +5268,6 @@ INSERT INTO "schema_migrations" (version) VALUES
|
||||
('20210426025625'),
|
||||
('20210430201028'),
|
||||
('20210506235640'),
|
||||
('20210718172512');
|
||||
|
||||
('20210718172512'),
|
||||
('20210625155528');
|
||||
|
||||
|
24
script/fixes/103_fill_new_post_replacement_fields.rb
Normal file
24
script/fixes/103_fill_new_post_replacement_fields.rb
Normal file
@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'config', 'environment'))
|
||||
|
||||
UserStatus.find_each do |user_status|
|
||||
user_status.update_column(:post_replacement_rejected_count, PostReplacement.rejected.for_user(user_status.user.id).count)
|
||||
end
|
||||
|
||||
# post ids who have two replacements, one approved, one original
|
||||
PostReplacement.select(:post_id).where(status: ["approved", "original"]).group(:post_id)
|
||||
.having("count(post_id) = 2").map(&:post_id).each do |post_id|
|
||||
replacements = PostReplacement.where(post_id: post_id).order(:status)
|
||||
|
||||
approved = replacements[0]
|
||||
original = replacements[1]
|
||||
|
||||
approved.uploader_id_on_approve = original.creator_id
|
||||
approved.penalize_uploader_on_approve = true
|
||||
approved.save!
|
||||
|
||||
user_status = UserStatus.for_user(original.creator_id)
|
||||
user_status.update_all("own_post_replaced_count = own_post_replaced_count + 1")
|
||||
user_status.update_all("own_post_replaced_penalize_count = own_post_replaced_penalize_count + 1")
|
||||
end
|
@ -3,11 +3,11 @@ require 'test_helper'
|
||||
class PostReplacementsControllerTest < ActionDispatch::IntegrationTest
|
||||
|
||||
setup do
|
||||
Sidekiq::Testing::inline!
|
||||
Sidekiq::Testing.inline!
|
||||
end
|
||||
|
||||
teardown do
|
||||
Sidekiq::Testing::fake!
|
||||
Sidekiq::Testing.fake!
|
||||
end
|
||||
|
||||
context "The post replacements controller" do
|
||||
@ -43,7 +43,7 @@ class PostReplacementsControllerTest < ActionDispatch::IntegrationTest
|
||||
context "reject action" do
|
||||
should "reject replacement" do
|
||||
put_auth reject_post_replacement_path(@replacement), @user
|
||||
assert_redirected_to post_replacement_path(@replacement)
|
||||
assert_redirected_to post_path(@post)
|
||||
@replacement.reload
|
||||
@post.reload
|
||||
assert_equal @replacement.status, "rejected"
|
||||
@ -64,7 +64,7 @@ class PostReplacementsControllerTest < ActionDispatch::IntegrationTest
|
||||
|
||||
context "promote action" do
|
||||
should "create post" do
|
||||
put_auth promote_post_replacement_path(@replacement), @user
|
||||
post_auth promote_post_replacement_path(@replacement), @user
|
||||
last_post = Post.last
|
||||
assert_redirected_to post_path(last_post)
|
||||
@replacement.reload
|
||||
@ -74,6 +74,18 @@ class PostReplacementsControllerTest < ActionDispatch::IntegrationTest
|
||||
end
|
||||
end
|
||||
|
||||
context "toggle action" do
|
||||
should "change penalize_uploader flag" do
|
||||
put_auth approve_post_replacement_path(@replacement, penalize_current_uploader: true), @user
|
||||
@replacement.reload
|
||||
assert @replacement.penalize_uploader_on_approve
|
||||
put_auth toggle_penalize_post_replacement_path(@replacement), @user
|
||||
assert_redirected_to post_replacement_path(@replacement)
|
||||
@replacement.reload
|
||||
assert !@replacement.penalize_uploader_on_approve
|
||||
end
|
||||
end
|
||||
|
||||
context "index action" do
|
||||
should "render" do
|
||||
get post_replacements_path
|
||||
|
@ -77,7 +77,7 @@ class PostReplacementTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
should "affect user upload limit" do
|
||||
assert_difference("PostReplacement.pending.for_user(@user.id).count", 1) do
|
||||
assert_difference(->{PostReplacement.pending.for_user(@user.id).count}, 1) do
|
||||
@replacement = @post.replacements.create(FactoryBot.attributes_for(:png_replacement).merge(creator: @user, creator_ip_addr: '127.0.0.1'))
|
||||
end
|
||||
end
|
||||
@ -109,10 +109,26 @@ class PostReplacementTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
should "give user back their upload slot" do
|
||||
assert_difference("PostReplacement.pending.for_user(@user.id).count", -1) do
|
||||
assert_difference(->{PostReplacement.pending.for_user(@user.id).count}, -1) do
|
||||
@replacement.reject!
|
||||
end
|
||||
end
|
||||
|
||||
should "increment the users rejected replacements count" do
|
||||
assert_difference(->{@user.post_replacement_rejected_count}, 1) do
|
||||
assert_difference(->{PostReplacement.rejected.for_user(@user.id).count}, 1) do
|
||||
@replacement.reject!
|
||||
@user.reload
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
should "work only once for pending replacements" do
|
||||
@replacement.reject!
|
||||
assert_equal [], @replacement.errors.full_messages
|
||||
@replacement.reject!
|
||||
assert_equal ["Status must be pending to reject"], @replacement.errors.full_messages
|
||||
end
|
||||
end
|
||||
|
||||
context "Approve:" do
|
||||
@ -124,20 +140,21 @@ class PostReplacementTest < ActiveSupport::TestCase
|
||||
|
||||
should "create a mod action" do
|
||||
assert_difference("ModAction.count") do
|
||||
@replacement.approve!
|
||||
@replacement.approve! penalize_current_uploader: true
|
||||
end
|
||||
end
|
||||
|
||||
should "fail if post cannot be backed up" do
|
||||
@post.md5 = "123" # Breaks file path, should force backup to fail.
|
||||
assert_raise(ProcessingError) do
|
||||
@replacement.approve!
|
||||
@replacement.approve! penalize_current_uploader: true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
should "update post with new image" do
|
||||
old_md5 = @post.md5
|
||||
@replacement.approve!
|
||||
@replacement.approve! penalize_current_uploader: true
|
||||
@post.reload
|
||||
assert_not_equal @post.md5, old_md5
|
||||
assert_equal @replacement.image_width, @post.image_width
|
||||
@ -151,25 +168,25 @@ class PostReplacementTest < ActiveSupport::TestCase
|
||||
should "generate videos samples if replacement is video" do
|
||||
@replacement = FactoryBot.create(:webm_replacement, creator: @user, creator_ip_addr: '127.0.0.1', post: @post)
|
||||
@post.expects(:generate_video_samples).times(1)
|
||||
@replacement.approve!
|
||||
@replacement.approve! penalize_current_uploader: true
|
||||
end
|
||||
|
||||
should "delete original files immediately" do
|
||||
sm = Danbooru.config.storage_manager
|
||||
old_md5 = @post.md5
|
||||
old_ext = @post.file_ext
|
||||
@replacement.approve!
|
||||
@replacement.approve! penalize_current_uploader: true
|
||||
@post.reload
|
||||
assert_not File.exists?(sm.file_path(old_md5, old_ext, :original))
|
||||
assert_not File.exists?(sm.file_path(old_md5, old_ext, :preview))
|
||||
assert_not File.exists?(sm.file_path(old_md5, old_ext, :large))
|
||||
assert_not File.exists?(sm.file_path(old_md5, old_ext, :original, protected=true))
|
||||
assert_not File.exist?(sm.file_path(old_md5, old_ext, :original))
|
||||
assert_not File.exist?(sm.file_path(old_md5, old_ext, :preview))
|
||||
assert_not File.exist?(sm.file_path(old_md5, old_ext, :large))
|
||||
assert_not File.exist?(sm.file_path(old_md5, old_ext, :original, protected=true))
|
||||
end
|
||||
|
||||
should "not be able to approve on deleted post" do
|
||||
@post.update_column(:is_deleted, true)
|
||||
assert_raise ProcessingError do
|
||||
@replacement.approve!
|
||||
@replacement.approve! penalize_current_uploader: true
|
||||
end
|
||||
end
|
||||
|
||||
@ -177,7 +194,7 @@ class PostReplacementTest < ActiveSupport::TestCase
|
||||
old_md5 = @post.md5
|
||||
old_source = @post.source
|
||||
assert_difference("@post.replacements.size", 1) do
|
||||
@replacement.approve!
|
||||
@replacement.approve! penalize_current_uploader: true
|
||||
end
|
||||
new_replacement = @post.replacements.last
|
||||
assert_equal 'original', new_replacement.status
|
||||
@ -187,21 +204,78 @@ class PostReplacementTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
should "update users upload counts" do
|
||||
assert_difference("Post.for_user(@mod_user.id).where('is_flagged = false AND is_deleted = false AND is_pending = false').count", -1) do
|
||||
assert_difference("Post.for_user(@user.id).where('is_flagged = false AND is_deleted = false AND is_pending = false').count", 1) do
|
||||
@replacement.approve!
|
||||
assert_difference(->{Post.for_user(@mod_user.id).where('is_flagged = false AND is_deleted = false AND is_pending = false').count}, -1) do
|
||||
assert_difference(->{Post.for_user(@user.id).where('is_flagged = false AND is_deleted = false AND is_pending = false').count}, 1) do
|
||||
@replacement.approve! penalize_current_uploader: true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
should "update the original users upload limit if penalized" do
|
||||
assert_difference(->{@mod_user.own_post_replaced_count}, 1) do
|
||||
assert_difference(->{@mod_user.own_post_replaced_penalize_count}, 1) do
|
||||
assert_difference(->{PostReplacement.penalized.for_uploader_on_approve(@mod_user.id).count}, 1) do
|
||||
@replacement.approve! penalize_current_uploader: true
|
||||
@mod_user.reload
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
should "not update the original users upload limit if not penalizing" do
|
||||
assert_difference(-> {@mod_user.own_post_replaced_count}, 1) do
|
||||
assert_difference(->{@mod_user.own_post_replaced_penalize_count}, 0) do
|
||||
assert_difference(->{PostReplacement.not_penalized.for_uploader_on_approve(@mod_user.id).count}, 1) do
|
||||
@replacement.approve! penalize_current_uploader: false
|
||||
@mod_user.reload
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
should "correctly resize the posts notes" do
|
||||
@replacement.approve!
|
||||
@replacement.approve! penalize_current_uploader: true
|
||||
@note.reload
|
||||
assert_equal 153, @note.x
|
||||
assert_equal 611, @note.y
|
||||
assert_equal 153, @note.width
|
||||
assert_equal 152, @note.height
|
||||
end
|
||||
|
||||
should "only work on pending or original replacements" do
|
||||
@replacement.reject!
|
||||
@replacement.approve! penalize_current_uploader: false
|
||||
assert_equal(["Status must be pending or original to approve"], @replacement.errors.full_messages)
|
||||
end
|
||||
|
||||
should "only work once" do
|
||||
@replacement.approve! penalize_current_uploader: false
|
||||
assert_equal [], @replacement.errors.full_messages
|
||||
@replacement.approve! penalize_current_uploader: false
|
||||
assert_equal ["Status must be pending or original to approve"], @replacement.errors.full_messages
|
||||
end
|
||||
end
|
||||
|
||||
context "Toggle:" do
|
||||
setup do
|
||||
@replacement = FactoryBot.create(:png_replacement, creator: @user, creator_ip_addr: '127.0.0.1', post: @post)
|
||||
assert @replacement
|
||||
end
|
||||
|
||||
should "change the users upload limit" do
|
||||
@replacement.approve! penalize_current_uploader: false
|
||||
assert_difference(->{@mod_user.own_post_replaced_penalize_count}, 1) do
|
||||
assert_difference(->{PostReplacement.penalized.for_uploader_on_approve(@mod_user.id).count}, 1) do
|
||||
@replacement.toggle_penalize!
|
||||
@mod_user.reload
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
should "only work on appoved replacements" do
|
||||
@replacement.toggle_penalize!
|
||||
assert_equal(["Status must be approved to penalize"], @replacement.errors.full_messages)
|
||||
end
|
||||
end
|
||||
|
||||
context "Promote:" do
|
||||
@ -226,8 +300,8 @@ class PostReplacementTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
should "credit replacer with new post" do
|
||||
assert_difference("Post.for_user(@mod_user.id).where('is_flagged = false AND is_deleted = false AND is_pending = false').count", 0) do
|
||||
assert_difference("Post.for_user(@user.id).where('is_flagged = false AND is_deleted = false').count", 1) do
|
||||
assert_difference(->{Post.for_user(@mod_user.id).where('is_flagged = false AND is_deleted = false AND is_pending = false').count}, 0) do
|
||||
assert_difference(->{Post.for_user(@user.id).where('is_flagged = false AND is_deleted = false').count}, 1) do
|
||||
post = @replacement.promote!
|
||||
assert post
|
||||
assert_equal [], post.errors.full_messages
|
||||
@ -235,5 +309,11 @@ class PostReplacementTest < ActiveSupport::TestCase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
should "only work on pending replacements" do
|
||||
@replacement.approve! penalize_current_uploader: false
|
||||
@replacement.promote!
|
||||
assert_equal(["Status must be pending to promote"], @replacement.errors.full_messages)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user