diff --git a/app/controllers/moderation_reports_controller.rb b/app/controllers/moderation_reports_controller.rb new file mode 100644 index 000000000..7ea5e08d1 --- /dev/null +++ b/app/controllers/moderation_reports_controller.rb @@ -0,0 +1,48 @@ +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) + 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 diff --git a/app/javascript/src/styles/base/040_colors.css b/app/javascript/src/styles/base/040_colors.css index 860fd1663..9c8bf226a 100644 --- a/app/javascript/src/styles/base/040_colors.css +++ b/app/javascript/src/styles/base/040_colors.css @@ -67,6 +67,9 @@ --forum-vote-meh-color: goldenrod; --forum-vote-down-color: red; + --moderation-report-text-color: red; + --moderation-report-border: 2px solid red; + --comment-sticky-background-color: var(--subnav-menu-background-color); --post-tooltip-background-color: var(--body-background-color); @@ -333,6 +336,9 @@ body[data-current-user-theme="dark"] { --forum-vote-meh-color: var(--yellow-1); --forum-vote-down-color: var(--red-1); + --moderation-report-text-color: var(--red-1); + --moderation-report-border: 2px solid var(--red-1); + --jquery-ui-widget-content-text-color: var(--text-color); --jquery-ui-widget-content-background: var(--grey-2); --jquery-ui-dialog-box-shadow: 0 0 8px var(--grey-1); diff --git a/app/javascript/src/styles/specific/comments.scss b/app/javascript/src/styles/specific/comments.scss index 42e9fe5a8..5bf5d95f9 100644 --- a/app/javascript/src/styles/specific/comments.scss +++ b/app/javascript/src/styles/specific/comments.scss @@ -1,6 +1,12 @@ @import "../base/000_vars.scss"; div.comments-for-post { + div.moderation-comments-notice { + margin: 1em 0; + font-weight: bold; + color: var(--moderation-report-text-color); + } + div.hidden-comments-notice { margin: 1em 0; } @@ -13,6 +19,10 @@ div.comments-for-post { background: var(--comment-sticky-background-color); } + &[data-is-reported="true"] { + border: var(--moderation-report-border); + } + &[data-is-voted="true"] { .comment-vote-up-link, .comment-vote-down-link { display: none; diff --git a/app/javascript/src/styles/specific/forum.scss b/app/javascript/src/styles/specific/forum.scss index 8cc4bab06..686ad6e65 100644 --- a/app/javascript/src/styles/specific/forum.scss +++ b/app/javascript/src/styles/specific/forum.scss @@ -1,5 +1,14 @@ div.list-of-forum-posts { + div.moderation-forums-notice { + font-weight: bold; + color: var(--moderation-report-text-color); + } + article.forum-post { + &[data-is-reported="true"] { + border: var(--moderation-report-border); + } + a.voted { font-weight: bold; } diff --git a/app/javascript/src/styles/specific/users.scss b/app/javascript/src/styles/specific/users.scss index cfa0c5579..ff90e48ea 100644 --- a/app/javascript/src/styles/specific/users.scss +++ b/app/javascript/src/styles/specific/users.scss @@ -1,5 +1,11 @@ div#c-users { div#a-show { + div.moderation-users-notice { + margin: 1em 0; + font-weight: bold; + color: var(--moderation-report-text-color); + } + div.box { margin-bottom: 2em; } diff --git a/app/models/comment.rb b/app/models/comment.rb index c9111dd16..005e3c68d 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -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)) diff --git a/app/models/forum_post.rb b/app/models/forum_post.rb index 6c797731b..860f3791c 100644 --- a/app/models/forum_post.rb +++ b/app/models/forum_post.rb @@ -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? || diff --git a/app/models/forum_topic.rb b/app/models/forum_topic.rb index 458aad16d..48aa8dd4d 100644 --- a/app/models/forum_topic.rb +++ b/app/models/forum_topic.rb @@ -14,6 +14,7 @@ class ForumTopic < ApplicationRecord belongs_to_creator belongs_to_updater has_many :posts, -> {order("forum_posts.id asc")}, :class_name => "ForumPost", :foreign_key => "topic_id", :dependent => :destroy + has_many :moderation_reports, through: :posts has_one :original_post, -> {order("forum_posts.id asc")}, class_name: "ForumPost", foreign_key: "topic_id", inverse_of: :topic has_many :subscriptions, :class_name => "ForumSubscription" before_validation :initialize_is_deleted, :on => :create @@ -181,4 +182,8 @@ class ForumTopic < ApplicationRecord def update_orignal_post original_post&.update_columns(:updater_id => CurrentUser.id, :updated_at => Time.now) end + + def viewable_moderation_reports + CurrentUser.is_moderator? ? moderation_reports.recent : [] + end end diff --git a/app/models/moderation_report.rb b/app/models/moderation_report.rb new file mode 100644 index 000000000..5c75176e5 --- /dev/null +++ b/app/models/moderation_report.rb @@ -0,0 +1,61 @@ +class ModerationReport < ApplicationRecord + belongs_to :model, polymorphic: true + belongs_to_creator + + validates :reason, presence: true + after_create :create_forum_post! + + scope :user, -> { where(model_type: "User") } + scope :comment, -> { where(model_type: "Comment") } + scope :forum_post, -> { where(model_type: "ForumPost") } + scope :recent, -> { where("moderation_reports.created_at >= ?", 1.week.ago) } + + 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 diff --git a/app/models/post.rb b/app/models/post.rb index 6b7326079..cf7b5c254 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -49,6 +49,7 @@ class Post < ApplicationRecord has_many :votes, :class_name => "PostVote", :dependent => :destroy has_many :notes, :dependent => :destroy has_many :comments, -> {order("comments.id")}, :dependent => :destroy + has_many :moderation_reports, through: :comments has_many :children, -> {order("posts.id")}, :class_name => "Post", :foreign_key => "parent_id" has_many :approvals, :class_name => "PostApproval", :dependent => :destroy has_many :disapprovals, :class_name => "PostDisapproval", :dependent => :destroy @@ -1811,4 +1812,8 @@ class Post < ApplicationRecord save end + + def viewable_moderation_reports + CurrentUser.is_moderator? ? moderation_reports.recent : [] + end end diff --git a/app/models/user.rb b/app/models/user.rb index 411d29799..e325e5304 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -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 @@ -807,4 +812,8 @@ class User < ApplicationRecord def presenter @presenter ||= UserPresenter.new(self) end + + def viewable_moderation_reports + CurrentUser.is_moderator? ? moderation_reports.recent : [] + end end diff --git a/app/views/comments/_index_by_comment.html.erb b/app/views/comments/_index_by_comment.html.erb index e70882dfa..478c06557 100644 --- a/app/views/comments/_index_by_comment.html.erb +++ b/app/views/comments/_index_by_comment.html.erb @@ -8,7 +8,7 @@ <%= link_to(image_tag(comment.post.preview_file_url), post_path(comment.post)) %> <% end %> - <%= render partial: "comments/partials/show/comment", collection: [comment], locals: { context: :index_by_comment, dtext_data: DText.preprocess(@comments.map(&:body)) } %> + <%= render partial: "comments/partials/show/comment", collection: [comment], locals: { context: :index_by_comment, dtext_data: DText.preprocess(@comments.map(&:body)), moderation_reports: [] } %> <% end %> <% end %> <% end %> diff --git a/app/views/comments/index_for_post.js.erb b/app/views/comments/index_for_post.js.erb index af2b8cab0..622567c51 100644 --- a/app/views/comments/index_for_post.js.erb +++ b/app/views/comments/index_for_post.js.erb @@ -1,5 +1,5 @@ $("#threshold-comments-notice-for-<%= @post.id %>").hide(); var current_comment_section = $("div.comments-for-post[data-post-id=<%= @post.id %>] div.list-of-comments"); -current_comment_section.html("<%= j(render(partial: 'comments/partials/show/comment', collection: @comments, locals: { context: :index_for_post, dtext_data: DText.preprocess(@comments.map(&:body)) })) %>"); +current_comment_section.html("<%= j(render(partial: 'comments/partials/show/comment', collection: @comments, locals: { context: :index_for_post, dtext_data: DText.preprocess(@comments.map(&:body)), moderation_reports: @post.viewable_moderation_reports })) %>"); $(window).trigger("danbooru:index_for_post", [<%= @post.id %>]); diff --git a/app/views/comments/partials/index/_list.html.erb b/app/views/comments/partials/index/_list.html.erb index be56922dd..20a2f3422 100644 --- a/app/views/comments/partials/index/_list.html.erb +++ b/app/views/comments/partials/index/_list.html.erb @@ -3,6 +3,13 @@ <%= render "comments/partials/index/header", :post => post %> <% end %> + <% if post.viewable_moderation_reports.present? %> +
+ + This post has comments reported for moderation! (<%= pluralize(post.viewable_moderation_reports.length, "report") %>) + +
+ <% end %> <% if post.comments.hidden(CurrentUser.user).any? || (page == :comments && post.comments.size > 6) %>
@@ -13,7 +20,7 @@
<% if comments.present? %> - <%= render partial: "comments/partials/show/comment", collection: comments, locals: { context: :index_by_post, dtext_data: DText.preprocess(comments.map(&:body)) } %> + <%= render partial: "comments/partials/show/comment", collection: comments, locals: { context: :index_by_post, dtext_data: DText.preprocess(comments.map(&:body)), moderation_reports: post.viewable_moderation_reports } %> <% elsif post.last_commented_at.present? %>

There are no visible comments.

<% else %> diff --git a/app/views/comments/partials/show/_comment.html.erb b/app/views/comments/partials/show/_comment.html.erb index f08b42014..8205ae503 100644 --- a/app/views/comments/partials/show/_comment.html.erb +++ b/app/views/comments/partials/show/_comment.html.erb @@ -1,4 +1,4 @@ -<%# locals: comment, context, dtext_data %> +<%# locals: comment, context, dtext_data, moderation_reports %> <% if CurrentUser.is_moderator? || (params[:search] && params[:search][:is_deleted] =~ /t/) || !comment.is_deleted? %> @@ -12,6 +12,9 @@ data-is-deleted="<%= comment.is_deleted? %>" data-is-sticky="<%= comment.is_sticky? %>" data-below-threshold="<%= comment.score < CurrentUser.user.comment_threshold %>" + <% if CurrentUser.is_moderator? %> + data-is-reported="<%= moderation_reports.pluck(:model_id).include?(comment.id) %>" + <% end %> data-is-voted="<%= comment.voted_by?(CurrentUser.user) %>">

@@ -53,6 +56,9 @@ + <% if comment.reportable_by?(CurrentUser.user) %> +
  • <%= link_to "Report comment", new_moderation_report_path(moderation_report: { model_type: "Comment", model_id: comment.id }), remote: true %>
  • + <% end %> <% if comment.editable_by?(CurrentUser.user) %> <%= render "comments/form", comment: comment, hidden: true %> diff --git a/app/views/forum_posts/_forum_post.html.erb b/app/views/forum_posts/_forum_post.html.erb index 88cacfef8..32fb3c166 100644 --- a/app/views/forum_posts/_forum_post.html.erb +++ b/app/views/forum_posts/_forum_post.html.erb @@ -1,5 +1,10 @@ <% if forum_post.visible?(CurrentUser.user, ActiveModel::Type::Boolean.new.cast(params.dig(:search, :is_deleted))) %> -
    +
    + data-is-reported="<%= moderation_reports.pluck(:model_id).include?(forum_post.id) %>" + <% end %> + data-creator="<%= forum_post.creator.name %>">

    <%= link_to_user forum_post.creator %> @@ -32,6 +37,9 @@
  • <%= link_to "Edit", edit_forum_post_path(forum_post.id), :id => "edit_forum_post_link_#{forum_post.id}", :class => "edit_forum_post_link" %>
  • <% end %> <% end %> + <% if forum_post.reportable_by?(CurrentUser.user) %> +
  • <%= link_to "Report forum", new_moderation_report_path(moderation_report: { model_type: "ForumPost", model_id: forum_post.id }), remote: true %>
  • + <% end %> <% if forum_post.votable? %>
      <%= render "forum_post_votes/list", votes: forum_post.votes, forum_post: forum_post %> diff --git a/app/views/forum_posts/_listing.html.erb b/app/views/forum_posts/_listing.html.erb index 0612f2522..5bea63030 100644 --- a/app/views/forum_posts/_listing.html.erb +++ b/app/views/forum_posts/_listing.html.erb @@ -1,9 +1,18 @@ <%- # forum_post %> <%- # original_forum_post_id %> <%- # dtext_data %> +<%- # moderation_reports %>
      + <% if moderation_reports.present? %> +
      + + This topic has forum posts reported for moderation! (<%= pluralize(moderation_reports.length, "report") %>) + +
      + <% end %> + <% forum_posts.each do |forum_post| %> - <%= render "forum_posts/forum_post", forum_post: forum_post, original_forum_post_id: original_forum_post_id, dtext_data: dtext_data %> + <%= render "forum_posts/forum_post", forum_post: forum_post, original_forum_post_id: original_forum_post_id, dtext_data: dtext_data, moderation_reports: moderation_reports %> <% end %>
      diff --git a/app/views/forum_topics/show.html.erb b/app/views/forum_topics/show.html.erb index c8d64d5dc..5bab6d482 100644 --- a/app/views/forum_topics/show.html.erb +++ b/app/views/forum_topics/show.html.erb @@ -20,7 +20,7 @@

    <% end %> - <%= render "forum_posts/listing", forum_posts: @forum_posts, original_forum_post_id: @forum_topic.original_post.id, dtext_data: DText.preprocess(@forum_posts.map(&:body)) %> + <%= render "forum_posts/listing", forum_posts: @forum_posts, original_forum_post_id: @forum_topic.original_post.id, dtext_data: DText.preprocess(@forum_posts.map(&:body)), moderation_reports: @forum_topic.viewable_moderation_reports %> <% if CurrentUser.is_member? %> <% if CurrentUser.is_moderator? || !@forum_topic.is_locked? %> diff --git a/app/views/moderation_reports/_new.html.erb b/app/views/moderation_reports/_new.html.erb new file mode 100644 index 000000000..e0e948144 --- /dev/null +++ b/app/views/moderation_reports/_new.html.erb @@ -0,0 +1,14 @@ +
    +
    + <%= format_text(WikiPage.titled(Danbooru.config.report_notice_wiki_page).first.try(&:body)) %> +
    + + <%# 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 %> +
    diff --git a/app/views/moderation_reports/create.js.erb b/app/views/moderation_reports/create.js.erb new file mode 100644 index 000000000..755f3d075 --- /dev/null +++ b/app/views/moderation_reports/create.js.erb @@ -0,0 +1 @@ +Danbooru.notice("Report submitted."); \ No newline at end of file diff --git a/app/views/moderation_reports/index.html.erb b/app/views/moderation_reports/index.html.erb new file mode 100644 index 000000000..93507dbd1 --- /dev/null +++ b/app/views/moderation_reports/index.html.erb @@ -0,0 +1,27 @@ +
    +
    +

    Moderation reports

    + <%= 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| %> + + <%= format_text report.reason, inline: true %> + + <% end %> + <% t.column "Creator", width: "10%" do |report| %> + <%= compact_time report.created_at %> +
    by <%= link_to_user report.creator %> + <% end %> + <% end %> + + <%= numbered_paginator(@moderation_reports) %> +
    +
    diff --git a/app/views/moderation_reports/new.html.erb b/app/views/moderation_reports/new.html.erb new file mode 100644 index 000000000..70ebcbda7 --- /dev/null +++ b/app/views/moderation_reports/new.html.erb @@ -0,0 +1,5 @@ +
    +
    + <%= render "moderation_reports/new", moderation_report: @moderation_report %> +
    +
    diff --git a/app/views/moderation_reports/new.js.erb b/app/views/moderation_reports/new.js.erb new file mode 100644 index 000000000..8f83b844a --- /dev/null +++ b/app/views/moderation_reports/new.js.erb @@ -0,0 +1 @@ +Danbooru.Utility.dialog("Send report", "<%= j render "moderation_reports/new", moderation_report: @moderation_report %>"); diff --git a/app/views/static/site_map.html.erb b/app/views/static/site_map.html.erb index 8951e50ce..32a695924 100644 --- a/app/views/static/site_map.html.erb +++ b/app/views/static/site_map.html.erb @@ -155,6 +155,7 @@ <% end %> <% if CurrentUser.is_moderator? %> +
  • <%= link_to("Moderation Reports", moderation_reports_path) %>
  • <%= link_to("IP Addresses", ip_addresses_path) %>
  • <%= link_to("IP Bans", ip_bans_path) %>
  • <% end %> diff --git a/app/views/users/_secondary_links.html.erb b/app/views/users/_secondary_links.html.erb index ab204888f..26571d8fb 100644 --- a/app/views/users/_secondary_links.html.erb +++ b/app/views/users/_secondary_links.html.erb @@ -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? %> diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index 665b2b5d1..957f8b3f7 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -2,6 +2,14 @@

    <%= link_to_user @user %>

    + <% if @user.viewable_moderation_reports.present? %> +
    + + This user has been reported for moderation! (<%= pluralize(@user.viewable_moderation_reports.length, "report") %>) + +
    + <% end %> + <%= render "statistics", presenter: @user.presenter, user: @user %> <%= render "posts/partials/common/inline_blacklist" %> diff --git a/config/danbooru_default_config.rb b/config/danbooru_default_config.rb index 409d9f35f..42b134975 100644 --- a/config/danbooru_default_config.rb +++ b/config/danbooru_default_config.rb @@ -305,6 +305,10 @@ module Danbooru "help:appeal_notice" end + def report_notice_wiki_page + "help:report_notice" + end + def replacement_notice_wiki_page "help:replacement_notice" end diff --git a/config/routes.rb b/config/routes.rb index a0e692beb..f7a750ca3 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -160,6 +160,7 @@ Rails.application.routes.draw do end end resources :mod_actions + resources :moderation_reports, only: [:new, :create, :index] resources :news_updates resources :notes do collection do diff --git a/db/migrate/20200117220602_create_moderation_reports.rb b/db/migrate/20200117220602_create_moderation_reports.rb new file mode 100644 index 000000000..38f83f26e --- /dev/null +++ b/db/migrate/20200117220602_create_moderation_reports.rb @@ -0,0 +1,12 @@ +class CreateModerationReports < ActiveRecord::Migration[6.0] + def change + create_table :moderation_reports do |t| + t.timestamps + t.references :model, polymorphic: true, null: false + t.integer :creator_id, null: false + t.text :reason, null: false + end + + add_index :moderation_reports, :creator_id + end +end diff --git a/db/structure.sql b/db/structure.sql index 5f00617b0..b545e73e6 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -2408,6 +2408,40 @@ CREATE SEQUENCE public.mod_actions_id_seq ALTER SEQUENCE public.mod_actions_id_seq OWNED BY public.mod_actions.id; +-- +-- Name: moderation_reports; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.moderation_reports ( + id bigint NOT NULL, + created_at timestamp(6) without time zone NOT NULL, + updated_at timestamp(6) without time zone NOT NULL, + model_type character varying NOT NULL, + model_id bigint NOT NULL, + creator_id integer NOT NULL, + reason text NOT NULL +); + + +-- +-- Name: moderation_reports_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.moderation_reports_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: moderation_reports_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.moderation_reports_id_seq OWNED BY public.moderation_reports.id; + + -- -- Name: news_updates; Type: TABLE; Schema: public; Owner: - -- @@ -4080,6 +4114,13 @@ ALTER TABLE ONLY public.ip_bans ALTER COLUMN id SET DEFAULT nextval('public.ip_b ALTER TABLE ONLY public.mod_actions ALTER COLUMN id SET DEFAULT nextval('public.mod_actions_id_seq'::regclass); +-- +-- Name: moderation_reports id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.moderation_reports ALTER COLUMN id SET DEFAULT nextval('public.moderation_reports_id_seq'::regclass); + + -- -- Name: news_updates id; Type: DEFAULT; Schema: public; Owner: - -- @@ -4440,6 +4481,14 @@ ALTER TABLE ONLY public.mod_actions ADD CONSTRAINT mod_actions_pkey PRIMARY KEY (id); +-- +-- Name: moderation_reports moderation_reports_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.moderation_reports + ADD CONSTRAINT moderation_reports_pkey PRIMARY KEY (id); + + -- -- Name: news_updates news_updates_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -6514,6 +6563,20 @@ CREATE INDEX index_mod_actions_on_created_at ON public.mod_actions USING btree ( CREATE INDEX index_mod_actions_on_creator_id ON public.mod_actions USING btree (creator_id); +-- +-- Name: index_moderation_reports_on_creator_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_moderation_reports_on_creator_id ON public.moderation_reports USING btree (creator_id); + + +-- +-- Name: index_moderation_reports_on_model_type_and_model_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_moderation_reports_on_model_type_and_model_id ON public.moderation_reports USING btree (model_type, model_id); + + -- -- Name: index_news_updates_on_created_at; Type: INDEX; Schema: public; Owner: - -- @@ -7415,6 +7478,7 @@ INSERT INTO "schema_migrations" (version) VALUES ('20191223032633'), ('20200114204550'), ('20200115010442'), +('20200117220602'), ('20200118015014'); diff --git a/test/factories/moderation_report.rb b/test/factories/moderation_report.rb new file mode 100644 index 000000000..55cdbaa78 --- /dev/null +++ b/test/factories/moderation_report.rb @@ -0,0 +1,5 @@ +FactoryBot.define do + factory(:moderation_report) do + reason {"xxx"} + end +end diff --git a/test/functional/moderation_reports_controller_test.rb b/test/functional/moderation_reports_controller_test.rb new file mode 100644 index 000000000..3d18bc445 --- /dev/null +++ b/test/functional/moderation_reports_controller_test.rb @@ -0,0 +1,66 @@ +require 'test_helper' + +class ModerationReportsControllerTest < ActionDispatch::IntegrationTest + context "The moderation reports controller" do + setup do + travel_to(2.weeks.ago) do + @user = create(:user) + @builder = create(:builder_user) + @mod = create(:moderator_user) + end + + @user.as_current do + @comment = create(:comment) + end + end + + context "new action" do + should "render the access denied page" do + get_auth new_moderation_report_path, @user + assert_response 403 + assert_select "h1", /Access Denied/ + end + + should "render" do + get_auth new_moderation_report_path, @mod, params: {:moderation_report => {:model_id => @comment.id, :model_type => "Comment"}} + assert_response :success + end + end + + context "index action" do + setup do + @builder.as_current do + create(:moderation_report, model: @comment) + end + end + + should "render the access denied page" do + get_auth moderation_reports_path, @builder + assert_response 403 + assert_select "h1", /Access Denied/ + end + + should "render" do + get_auth moderation_reports_path, @mod + assert_response :success + end + + context "with search parameters" do + should "render" do + get_auth moderation_reports_path, @mod, params: {:search => {:model_id => @comment.id}} + assert_response :success + end + end + + context "create action" do + should "create a new moderation report" do + assert_difference("ModerationReport.count", 1) do + assert_difference("ModerationReport.count") do + post_auth moderation_reports_path, @builder, params: {:format => "js", :moderation_report => {:model_id => @comment.id, :model_type => "Comment", :reason => "xxx"}} + end + end + end + end + end + end +end