# frozen_string_literal: true class DuplicateReportsController < ApplicationController before_action :filter_banned_users, only: [:create] before_action :require_user, only: [:create, :mass_reject] before_action :load_report, except: [:index, :create, :mass_reject] skip_authorization_check only: [:show] def index @title = 'Duplicate Reports' authorize! :manage, DuplicateReport # see #load_report for reasoning on this query @duplicate_reports = DuplicateReport.includes(:user, post: [:tags], duplicate_of_post: [:tags]) .where(state: parse_states) .order(parse_order) .page(params[:page]).per(25) end def show @title = "Visual Diff: #{@duplicate_report.post_id} → #{@duplicate_report.duplicate_of_post_id}" @post = @duplicate_report.post @duplicate_of_post = @duplicate_report.duplicate_of_post end def create authorize! :create, DuplicateReport @duplicate_report = DuplicateReport.new(duplicate_report_params) if @duplicate_report.save flash[:notice] = 'Your duplicate report was submitted' else flash[:alert] = @duplicate_report.errors.full_messages.first end redirect_to short_post_path(params[:post_id]) end def mass_reject authorize! :reject, DuplicateReport @duplicate_reports = DuplicateReport.where(id: params[:duplicate_report_ids].split(',').map(&:to_i)) @duplicate_reports.each { |dr| dr.reject!(current_user) } flash[:notice] = "#{@duplicate_reports.size} reports successfully rejected" maybe_redirect_back duplicate_reports_path end def dupe_graph @title = 'Duplicate Reports' authorize! :manage, DuplicateReport seed_report = DuplicateReport.find(params[:id]) dupe_ids = [seed_report.id] build_graph(seed_report, dupe_ids, 5) @duplicate_reports = DuplicateReport.includes(:user, post: [:tags], duplicate_of_post: [:tags]) .where(id: dupe_ids) .where(state: parse_states) .order(parse_order) @duplicate_reports = Kaminari::PaginatableArray.new(@duplicate_reports, limit: @duplicate_reports.size, offset: 0, total_count: @duplicate_reports.size) render 'index' end private def build_graph(report, output, max_levels) return if max_levels == 0 related_reports = DuplicateReport.where(post_id: report.post_id) .or(DuplicateReport.where(duplicate_of_post_id: report.post_id)) .or(DuplicateReport.where(post_id: report.duplicate_of_post_id)) .or(DuplicateReport.where(duplicate_of_post_id: report.duplicate_of_post_id)) .where.not(id: output) related_reports.each do |r| output << r.id build_graph(r, output, max_levels - 1) end end def load_report # this should make ActiveRecord do its best to try and load the dupe report, its images, and their tags # in as few queries as possible. @duplicate_report = DuplicateReport.includes(:user, post: [:tags], duplicate_of_post: [:tags]).find(params[:id]) end def duplicate_report_params params.permit(:post_id, :duplicate_of_post_id, :reason).merge(user: current_user) end def parse_states states = %w[open claimed] valid_states = %w[open rejected accepted claimed] states = params[:states].split(',').map { |s| s.strip.downcase }.select { |s| valid_states.include?(s) } if params[:states] states end def parse_order params[:random].present? ? 'RANDOM()' : { created_at: :desc } end end