summaryrefslogtreecommitdiff
path: root/app/controllers/duplicate_reports_controller.rb
blob: 5668ef510682d3b111c1eda8f48ead48c2f88812 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# 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