Fail loudly if we forget to whitelist a param instead of silently ignoring it. misc models: convert to strong params. artist commentaries: convert to strong params. * Disallow changing or setting post_id to a nonexistent post. artists: convert to strong params. * Disallow setting `is_banned` in create/update actions. Changing it this way instead of with the ban/unban actions would leave the artist in a partially banned state. bans: convert to strong params. * Disallow changing the user_id after the ban has been created. comments: convert to strong params. favorite groups: convert to strong params. news updates: convert to strong params. post appeals: convert to strong params. post flags: convert to strong params. * Disallow users from setting the `is_deleted` / `is_resolved` flags. ip bans: convert to strong params. user feedbacks: convert to strong params. * Disallow users from setting `disable_dmail_notification` when creating feedbacks. * Disallow changing the user_id after the feedback has been created. notes: convert to strong params. wiki pages: convert to strong params. * Also fix non-Builders being able to delete wiki pages. saved searches: convert to strong params. pools: convert to strong params. * Disallow setting `post_count` or `is_deleted` in create/update actions. janitor trials: convert to strong params. post disapprovals: convert to strong params. * Factor out quick-mod bar to shared partial. * Fix quick-mod bar to use `Post#is_approvable?` to determine visibility of Approve button. dmail filters: convert to strong params. password resets: convert to strong params. user name change requests: convert to strong params. posts: convert to strong params. users: convert to strong params. * Disallow setting password_hash, last_logged_in_at, last_forum_read_at, has_mail, and dmail_filter_attributes[user_id]. * Remove initialize_default_image_size (dead code). uploads: convert to strong params. * Remove `initialize_status` because status already defaults to pending in the database. tag aliases/implications: convert to strong params. tags: convert to strong params. forum posts: convert to strong params. * Disallow changing the topic_id after creating the post. * Disallow setting is_deleted (destroy/undelete actions should be used instead). * Remove is_sticky / is_locked (nonexistent attributes). forum topics: convert to strong params. * merges https://github.com/evazion/danbooru/tree/wip-rails-5.1 * lock pg gem to 0.21 (1.0.0 is incompatible with rails 5.1.4) * switch to factorybot and change all references Co-authored-by: r888888888 <r888888888@gmail.com> Co-authored-by: evazion <noizave@gmail.com> add diffs
186 lines
5.3 KiB
Ruby
186 lines
5.3 KiB
Ruby
class PostReplacement < ApplicationRecord
|
|
DELETION_GRACE_PERIOD = 30.days
|
|
|
|
belongs_to :post
|
|
belongs_to :creator, class_name: "User"
|
|
before_validation :initialize_fields, on: :create
|
|
attr_accessor :replacement_file, :final_source, :tags
|
|
|
|
def initialize_fields
|
|
self.creator = CurrentUser.user
|
|
self.original_url = post.source
|
|
self.tags = post.tag_string + " " + self.tags.to_s
|
|
|
|
self.file_ext_was = post.file_ext
|
|
self.file_size_was = post.file_size
|
|
self.image_width_was = post.image_width
|
|
self.image_height_was = post.image_height
|
|
self.md5_was = post.md5
|
|
end
|
|
|
|
def undo!
|
|
undo_replacement = post.replacements.create(replacement_url: original_url)
|
|
undo_replacement.process!
|
|
end
|
|
|
|
def process!
|
|
upload = nil
|
|
|
|
transaction do
|
|
upload = Upload.create!(
|
|
file: replacement_file,
|
|
source: replacement_url,
|
|
rating: post.rating,
|
|
tag_string: self.tags,
|
|
replaced_post: post,
|
|
)
|
|
|
|
upload.process_upload
|
|
upload.update(status: "completed", post_id: post.id)
|
|
md5_changed = (upload.md5 != post.md5)
|
|
|
|
if replacement_file.present?
|
|
self.replacement_url = "file://#{replacement_file.original_filename}"
|
|
else
|
|
self.replacement_url = upload.downloaded_source
|
|
end
|
|
|
|
# queue the deletion *before* updating the post so that we use the old
|
|
# md5/file_ext to delete the old files. if saving the post fails,
|
|
# this is rolled back so the job won't run.
|
|
if md5_changed
|
|
post.queue_delete_files(DELETION_GRACE_PERIOD)
|
|
end
|
|
|
|
self.file_ext = upload.file_ext
|
|
self.file_size = upload.file_size
|
|
self.image_height = upload.image_height
|
|
self.image_width = upload.image_width
|
|
self.md5 = upload.md5
|
|
|
|
post.md5 = upload.md5
|
|
post.file_ext = upload.file_ext
|
|
post.image_width = upload.image_width
|
|
post.image_height = upload.image_height
|
|
post.file_size = upload.file_size
|
|
post.source = final_source.presence || upload.source
|
|
post.tag_string = upload.tag_string
|
|
|
|
rescale_notes
|
|
update_ugoira_frame_data(upload)
|
|
|
|
if md5_changed
|
|
CurrentUser.as(User.system) do
|
|
post.comments.create!(body: comment_replacement_message, do_not_bump_post: true)
|
|
end
|
|
else
|
|
post.queue_backup
|
|
end
|
|
|
|
save!
|
|
post.save!
|
|
end
|
|
|
|
# point of no return: these things can't be rolled back, so we do them
|
|
# only after the transaction successfully commits.
|
|
upload.distribute_files(post)
|
|
post.update_iqdb_async
|
|
end
|
|
|
|
def rescale_notes
|
|
x_scale = post.image_width.to_f / post.image_width_was.to_f
|
|
y_scale = post.image_height.to_f / post.image_height_was.to_f
|
|
|
|
post.notes.each do |note|
|
|
note.rescale!(x_scale, y_scale)
|
|
end
|
|
end
|
|
|
|
def update_ugoira_frame_data(upload)
|
|
post.pixiv_ugoira_frame_data.destroy if post.pixiv_ugoira_frame_data.present?
|
|
upload.ugoira_service.save_frame_data(post) if post.is_ugoira?
|
|
end
|
|
|
|
module SearchMethods
|
|
def post_tags_match(query)
|
|
PostQueryBuilder.new(query).build(self.joins(:post))
|
|
end
|
|
|
|
def search(params = {})
|
|
q = super
|
|
|
|
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: User.name_to_id(params[:creator_name]))
|
|
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.apply_default_order(params)
|
|
end
|
|
end
|
|
|
|
module PresenterMethods
|
|
def comment_replacement_message
|
|
%("#{creator.name}":[/users/#{creator.id}] replaced this post with a new image:\n\n#{replacement_message})
|
|
end
|
|
|
|
def replacement_message
|
|
linked_source = linked_source(replacement_url)
|
|
linked_source_was = linked_source(post.source_was)
|
|
|
|
<<-EOS.strip_heredoc
|
|
[table]
|
|
[tbody]
|
|
[tr]
|
|
[th]Old[/th]
|
|
[td]#{linked_source_was}[/td]
|
|
[td]#{post.md5_was}[/td]
|
|
[td]#{post.file_ext_was}[/td]
|
|
[td]#{post.image_width_was} x #{post.image_height_was}[/td]
|
|
[td]#{post.file_size_was.to_s(:human_size, precision: 4)}[/td]
|
|
[/tr]
|
|
[tr]
|
|
[th]New[/th]
|
|
[td]#{linked_source}[/td]
|
|
[td]#{post.md5}[/td]
|
|
[td]#{post.file_ext}[/td]
|
|
[td]#{post.image_width} x #{post.image_height}[/td]
|
|
[td]#{post.file_size.to_s(:human_size, precision: 4)}[/td]
|
|
[/tr]
|
|
[/tbody]
|
|
[/table]
|
|
EOS
|
|
end
|
|
|
|
def linked_source(source)
|
|
# truncate long sources in the middle: "www.pixiv.net...lust_id=23264933"
|
|
truncated_source = source.gsub(%r{\Ahttps?://}, "").truncate(64, omission: "...#{source.last(32)}")
|
|
|
|
if source =~ %r{\Ahttps?://}i
|
|
%("#{truncated_source}":[#{source}])
|
|
else
|
|
truncated_source
|
|
end
|
|
end
|
|
|
|
def suggested_tags_for_removal
|
|
tags = post.tag_array.select { |tag| Danbooru.config.remove_tag_after_replacement?(tag) }
|
|
tags = tags.map { |tag| "-#{tag}" }
|
|
tags.join(" ")
|
|
end
|
|
end
|
|
|
|
include PresenterMethods
|
|
extend SearchMethods
|
|
end
|