Create the ability to send reports to moderators

- Limited to Builders+
-- Moderator+ can also use as they may be too busy ATM
- Only on users, comments, and forum posts
- Multiple reports can be generated per instance
- Primarily posts to a moderator-only topic for viewability
- Secondarily has a table for searchability
-- Viewable only by moderators
This commit is contained in:
BrokenEagle
2020-01-18 05:34:46 +00:00
parent 4a7322b197
commit 4cef0e45c2
17 changed files with 255 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
class ModerationReportsController < ApplicationController
respond_to :html, :xml, :json, :js
before_action :builder_only, only: [:new, :create]
before_action :moderator_only, only: [:index]
def new
check_privilege
@moderation_report = ModerationReport.new(moderation_report_params)
respond_with(@moderation_report)
end
def index
@moderation_reports = ModerationReport.paginated_search(params).includes(:creator, :model)
respond_with(@moderation_reports)
end
def create
check_privilege
@moderation_report = ModerationReport.create(moderation_report_params)
@moderation_report.create_forum_post!
respond_with(@moderation_report)
end
private
def model_type
params.fetch(:moderation_report, {}).fetch(:model_type)
end
def model_id
params.fetch(:moderation_report, {}).fetch(:model_id)
end
def check_privilege
case model_type
when "User"
return if User.find(model_id).reportable_by?(CurrentUser.user)
when "Comment"
return if Comment.find(model_id).reportable_by?(CurrentUser.user)
when "ForumPost"
return if ForumPost.find(model_id).reportable_by?(CurrentUser.user)
end
raise User::PrivilegeError
end
def moderation_report_params
params.fetch(:moderation_report, {}).permit(%i[model_type model_id reason])
end
end

View File

@@ -7,6 +7,7 @@ class Comment < ApplicationRecord
belongs_to :post
belongs_to_creator
belongs_to_updater
has_many :moderation_reports, as: :model
has_many :votes, :class_name => "CommentVote", :dependent => :destroy
after_create :update_last_commented_at_on_create
after_update(:if => ->(rec) {(!rec.is_deleted? || !rec.saved_change_to_is_deleted?) && CurrentUser.id != rec.creator_id}) do |rec|
@@ -127,6 +128,10 @@ class Comment < ApplicationRecord
updater_id == user.id || user.is_moderator?
end
def reportable_by?(user)
user.is_builder? && creator_id != user.id && !creator.is_moderator?
end
def voted_by?(user)
return false if user.is_anonymous?
user.id.in?(votes.map(&:user_id))

View File

@@ -6,6 +6,7 @@ class ForumPost < ApplicationRecord
belongs_to_updater
belongs_to :topic, :class_name => "ForumTopic"
has_many :dtext_links, as: :model, dependent: :destroy
has_many :moderation_reports, as: :model
has_many :votes, class_name: "ForumPostVote"
has_one :tag_alias
has_one :tag_implication
@@ -93,6 +94,10 @@ class ForumPost < ApplicationRecord
bulk_update_request || tag_alias || tag_implication
end
def reportable_by?(user)
user.is_builder? && creator_id != user.id && !creator.is_moderator?
end
def votable?
TagAlias.where(forum_post_id: id).exists? ||
TagImplication.where(forum_post_id: id).exists? ||

View File

@@ -0,0 +1,57 @@
class ModerationReport < ApplicationRecord
belongs_to :model, polymorphic: true
belongs_to_creator
scope :user, -> { where(model_type: "User") }
scope :comment, -> { where(model_type: "Comment") }
scope :forum_post, -> { where(model_type: "ForumPost") }
def forum_topic_title
"Reports requiring moderation"
end
def forum_topic_body
"This topic deals with moderation events as reported by Builders. Reports can be filed against users, comments, or forum posts."
end
def forum_topic
topic = ForumTopic.find_by_title(forum_topic_title)
if topic.nil?
topic = CurrentUser.as_system do
ForumTopic.create(title: forum_topic_title, category_id: 0, min_level: User::Levels::MODERATOR, original_post_attributes: {body: forum_topic_body})
end
end
topic
end
def forum_post_message
messages = ["[b]Submitted by:[/b] @#{creator.name}"]
case model_type
when "User"
messages << "[b]Submitted against:[/b] @#{model.name}"
when "Comment"
messages << "[b]Submitted against[/b]: comment ##{model_id}"
when "ForumPost"
messages << "[b]Submitted against[/b]: forum ##{model_id}"
end
messages << ""
messages << "[quote]"
messages << "[b]Reason:[/b]"
messages << ""
messages << reason
messages << "[/quote]"
messages.join("\n")
end
def create_forum_post!
updater = ForumUpdater.new(forum_topic)
updater.update(forum_post_message)
end
def self.search(params)
q = super
q = q.search_attributes(params, :model_type, :model_id, :creator_id)
q.apply_default_order(params)
end
end

View File

@@ -93,6 +93,7 @@ class User < ApplicationRecord
has_many :wiki_page_versions, foreign_key: :updater_id
has_many :feedback, :class_name => "UserFeedback", :dependent => :destroy
has_many :forum_post_votes, dependent: :destroy, foreign_key: :creator_id
has_many :moderation_reports, as: :model
has_many :posts, :foreign_key => "uploader_id"
has_many :post_appeals, foreign_key: :creator_id
has_many :post_approvals, :dependent => :destroy
@@ -791,6 +792,10 @@ class User < ApplicationRecord
end
end
def reportable_by?(user)
user.is_builder? && id != user.id && !is_moderator?
end
def hide_favorites?
!CurrentUser.is_admin? && enable_private_favorites? && CurrentUser.user.id != id
end

View File

@@ -53,6 +53,9 @@
<li class="comment-unvote-link">
<%= link_to "Unvote", comment_comment_votes_path(comment_id: comment.id), method: :delete, remote: true %>
</li>
<% if comment.reportable_by?(CurrentUser.user) %>
<li><%= link_to "Report comment", new_moderation_report_path(moderation_report: { model_type: "Comment", model_id: comment.id }), remote: true %></li>
<% end %>
</menu>
<% if comment.editable_by?(CurrentUser.user) %>
<%= render "comments/form", comment: comment, hidden: true %>

View File

@@ -32,6 +32,9 @@
<li><%= link_to "Edit", edit_forum_post_path(forum_post.id), :id => "edit_forum_post_link_#{forum_post.id}", :class => "edit_forum_post_link" %></li>
<% end %>
<% end %>
<% if forum_post.reportable_by?(CurrentUser.user) %>
<li><%= link_to "Report forum", new_moderation_report_path(moderation_report: { model_type: "ForumPost", model_id: forum_post.id }), remote: true %></li>
<% end %>
<% if forum_post.votable? %>
<ul class="votes" id="forum-post-votes-for-<%= forum_post.id %>">
<%= render "forum_post_votes/list", votes: forum_post.votes, forum_post: forum_post %>

View File

@@ -0,0 +1,14 @@
<div class="report-dialog-body">
<div class="prose">
<%= format_text(WikiPage.titled(Danbooru.config.report_notice_wiki_page).first.try(&:body)) %>
</div>
<%# XXX dtext_field expects there to be a `moderation_report` instance variable. %>
<% @moderation_report = moderation_report %>
<%= edit_form_for(@moderation_report, format: :js, remote: true) do |f| %>
<%= f.hidden_field :model_type %>
<%= f.hidden_field :model_id %>
<%= dtext_field "moderation_report", "reason", preview_id: "dtext-preview-for-moderation-report", type: "string" %>
<%= dtext_preview_button "moderation_report", "reason", preview_id: "dtext-preview-for-moderation-report" %>
<% end %>
</div>

View File

@@ -0,0 +1 @@
Danbooru.notice("Report submitted.");

View File

@@ -0,0 +1,27 @@
<div id="c-moderation-reports">
<div id="a-index">
<h1>Moderation reports</h1>
<%= table_for @moderation_reports, width: "100%" do |t| %>
<% t.column "Reported", width: "10%" do |report| %>
<% if report.model_type == "User" %>
<%= link_to_user report.model %>
<% elsif report.model_type == "Comment" %>
<%= link_to "comment ##{report.model_id}", comment_path(report.model_id) %>
<% elsif report.model_type == "ForumPost" %>
<%= link_to "forum ##{report.model_id}", forum_post_path(report.model_id) %>
<% end %>
<% end %>
<% t.column "Reason" do |report| %>
<span class="prose">
<%= format_text report.reason, inline: true %>
</span>
<% end %>
<% t.column "Creator", width: "10%" do |report| %>
<%= compact_time report.created_at %>
<br> by <%= link_to_user report.creator %>
<% end %>
<% end %>
<%= numbered_paginator(@moderation_reports) %>
</div>
</div>

View File

@@ -0,0 +1 @@
Danbooru.Utility.dialog("Send report", "<%= j render "moderation_reports/new", moderation_report: @moderation_report %>");

View File

@@ -155,6 +155,7 @@
<% end %>
<% if CurrentUser.is_moderator? %>
<li><%= link_to("Moderation Reports", moderation_reports_path) %></li>
<li><%= link_to("IP Addresses", ip_addresses_path) %></li>
<li><%= link_to("IP Bans", ip_bans_path) %></li>
<% end %>

View File

@@ -22,6 +22,9 @@
<% if !@user.is_platinum? %>
<%= subnav_link_to "Gift upgrade", new_user_upgrade_path(:user_id => @user.id) %>
<% end %>
<% if @user.reportable_by?(CurrentUser.user) %>
<%= subnav_link_to "Report user", new_moderation_report_path(moderation_report: { model_type: "User", model_id: @user.id }), remote: true %>
<% end %>
<% end %>
<% if CurrentUser.user.is_moderator? %>