From ecbb9d4ab14abfa7a62bc8afda68ddbc6a09ba9c Mon Sep 17 00:00:00 2001 From: Andy Zhao Date: Tue, 19 Jun 2018 16:41:31 -0400 Subject: [PATCH] [Done] New Reporting System MVP (#408) * Move validations from controller to model * Add new columns to feedback message model * Use polymorphic notes relationship * MVP of ticketing system * Use new URL for reported_url param * Add missing files * Add validations and tests for feedback_messages * Clean up some html * Update create spec and add update spec * Add mail tests and lint * Add link to user profile --- .../utilities/buildCommentHTML.js.erb | 2 +- app/assets/stylesheets/feedback_messages.scss | 24 ++++++++ .../feedback_messages_controller.rb | 34 ++++------- .../internal/feedback_messages_controller.rb | 37 ++++++++++++ app/controllers/pages_controller.rb | 7 +++ app/dashboards/feedback_message_dashboard.rb | 6 +- app/mailers/notify_mailer.rb | 11 ++++ app/models/feedback_message.rb | 40 ++++++++++++- app/models/note.rb | 8 +-- app/models/user.rb | 7 ++- app/services/user_role_service.rb | 5 +- app/views/comments/_comment.html.erb | 2 +- app/views/feedback_messages/_form.html.erb | 46 ++++++++++---- app/views/feedback_messages/index.html.erb | 23 +------ app/views/feedback_messages/show.html.erb | 30 ++++++++++ .../_feedback_message.html.erb | 60 +++++++++++++++++++ .../internal/feedback_messages/index.html.erb | 31 ++++++++++ app/views/layouts/internal.html.erb | 12 ++-- .../notify_mailer/new_report_email.html.erb | 6 ++ .../notify_mailer/new_report_email.text.erb | 4 ++ app/views/pages/report-abuse.html.erb | 2 +- config/routes.rb | 11 ++-- ...160906_add_columns_to_feedback_messages.rb | 18 ++++++ ...80608195204_change_notes_to_polymorphic.rb | 6 ++ db/schema.rb | 19 +++++- public/500.html | 4 +- spec/factories/feedback_messages.rb | 25 ++++++++ spec/mailers/notify_mailer_spec.rb | 39 ++++++++++++ .../mailers/previews/notify_mailer_preview.rb | 4 ++ spec/models/feedback_message_spec.rb | 49 +++++++++++++++ .../requests/feedback_messages_create_spec.rb | 54 ++++++++++++++--- .../internal_feedback_messages_update_spec.rb | 42 +++++++++++++ 32 files changed, 572 insertions(+), 96 deletions(-) create mode 100644 app/assets/stylesheets/feedback_messages.scss create mode 100644 app/controllers/internal/feedback_messages_controller.rb create mode 100644 app/views/feedback_messages/show.html.erb create mode 100644 app/views/internal/feedback_messages/_feedback_message.html.erb create mode 100644 app/views/internal/feedback_messages/index.html.erb create mode 100644 app/views/mailers/notify_mailer/new_report_email.html.erb create mode 100644 app/views/mailers/notify_mailer/new_report_email.text.erb create mode 100644 db/migrate/20180603160906_add_columns_to_feedback_messages.rb create mode 100644 db/migrate/20180608195204_change_notes_to_polymorphic.rb create mode 100644 spec/factories/feedback_messages.rb create mode 100644 spec/models/feedback_message_spec.rb create mode 100644 spec/requests/internal_feedback_messages_update_spec.rb diff --git a/app/assets/javascripts/utilities/buildCommentHTML.js.erb b/app/assets/javascripts/utilities/buildCommentHTML.js.erb index 1e9cf4251..0f5d8edc0 100644 --- a/app/assets/javascripts/utilities/buildCommentHTML.js.erb +++ b/app/assets/javascripts/utilities/buildCommentHTML.js.erb @@ -45,7 +45,7 @@ function buildCommentHTML(comment) { \ Permalink\ \ - Report Abuse\ + Report Abuse\ \ \ \ diff --git a/app/assets/stylesheets/feedback_messages.scss b/app/assets/stylesheets/feedback_messages.scss new file mode 100644 index 000000000..1ee4097b4 --- /dev/null +++ b/app/assets/stylesheets/feedback_messages.scss @@ -0,0 +1,24 @@ +.dialog{ + background: rgb(236, 236, 236); + border: 1px solid rgb(217, 217, 217); + text-align: center; + padding: 20px 30px; + margin: 20vh auto; + max-width: 60%; + height: 100%; + color: rgb(44, 46, 50); + border-radius: 5px; + @media screen and (max-width: 321px) { + h1,h2,h3,h4,h5,h6{ + font-size: 15px; + } + } + @media screen and (max-width: 768px) { + h3{ + word-break: break-all; + } + } +} +.blankmessage{ + font-style: italic; +} diff --git a/app/controllers/feedback_messages_controller.rb b/app/controllers/feedback_messages_controller.rb index 236d282cd..7e1207661 100644 --- a/app/controllers/feedback_messages_controller.rb +++ b/app/controllers/feedback_messages_controller.rb @@ -3,23 +3,24 @@ class FeedbackMessagesController < ApplicationController def create flash.clear - @feedback = FeedbackMessage.new(feedback_message_params.merge(user_id: current_user&.id)) - if authorize_send? + @feedback_message = FeedbackMessage.new( + feedback_message_params.merge(reporter_id: current_user&.id)) + if recaptcha_verified? && @feedback_message.save send_slack_message - @feedback.save - render :index + NotifyMailer.new_report_email(@feedback_message).deliver if @feedback_message.reporter_id? + redirect_to @feedback_message.path elsif feedback_message_params[:feedback_type] == "bug-reports" - flash.now[:notice] = "Make sure the forms are filled 🤖 " + flash[:notice] = "Make sure the forms are filled 🤖 " render file: "public/500.html", status: 500, layout: false else - flash.now[:notice] = "Make sure the forms are filled 🤖 " + flash[:notice] = "Make sure the forms are filled 🤖 " @previous_message = feedback_message_params[:message] render "pages/report-abuse.html.erb" end end - def authorize_send? - recaptcha_verified? && form_filled? + def show + @feedback_message = FeedbackMessage.find_by(slug: params[:slug]) end private @@ -40,7 +41,7 @@ class FeedbackMessagesController < ApplicationController def generate_message <<~HEREDOC #{generate_user_detail} - Category: #{feedback_message_params[:category_selection]} + Category: #{feedback_message_params[:category]} Message: #{feedback_message_params[:message]} URL: #{params[:url]} HEREDOC @@ -50,22 +51,13 @@ class FeedbackMessagesController < ApplicationController return "" unless current_user <<~HEREDOC *Logged in user:* - username: #{current_user.username} - email: #{current_user.email} + username: #{current_user.username} - https://dev.to/#{current_user.username} + email: twitter: #{current_user.twitter_username} github: #{current_user.github_username} HEREDOC end - def form_filled? - if feedback_message_params[:feedback_type] == "abuse-reports" - feedback_message_params[:category_selection].present? - else - feedback_message_params[:message].present? || - feedback_message_params[:category_selection].present? - end - end - def emoji_for_feedback(feedback_type) case feedback_type when "abuse-reports" @@ -78,6 +70,6 @@ class FeedbackMessagesController < ApplicationController end def feedback_message_params - params[:feedback_message].permit(:message, :feedback_type, :category_selection) + params[:feedback_message].permit(:message, :feedback_type, :category, :reported_url) end end diff --git a/app/controllers/internal/feedback_messages_controller.rb b/app/controllers/internal/feedback_messages_controller.rb new file mode 100644 index 000000000..21ef95195 --- /dev/null +++ b/app/controllers/internal/feedback_messages_controller.rb @@ -0,0 +1,37 @@ +class Internal::FeedbackMessagesController < Internal::ApplicationController + layout "internal" + + def index + @feedback_type = params[:state] || "abuse-reports" + @feedback_messages = FeedbackMessage. + where(feedback_type: @feedback_type). + order("created_at DESC"). + page(params[:page] || 1).per(25) + end + + def update + @feedback_message = FeedbackMessage.find(params[:id]) + @feedback_message.status = feedback_message_params[:status] + @feedback_message.reviewer_id = feedback_message_params[:reviewer_id] + note = @feedback_message.find_or_create_note(@feedback_message.feedback_type) + note.content = feedback_message_params[:note][:content] + if @feedback_message.save! && note.save! + @feedback_message.touch(:last_reviewed_at) + flash[:success] = "Report ##{@feedback_message.id} saved. Remember to send emails!" + redirect_to "/internal/reports?state=#{@feedback_message.feedback_type}" + else + @feedback_messages = FeedbackMessage.where(feedback_type: @feedback_type) + flash[:error] = @feedback_message.errors.full_messages + render "index.html.erb", state: @feedback_message.feedback_type + end + end + + private + + def feedback_message_params + params[:feedback_message].permit( + :status, :reviewer_id, + note: [:content, :reason], + ) + end +end diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb index 7a01a1423..23530b098 100644 --- a/app/controllers/pages_controller.rb +++ b/app/controllers/pages_controller.rb @@ -24,6 +24,13 @@ class PagesController < ApplicationController render "membership_form", layout: false end + def report_abuse + @feedback_message = FeedbackMessage.new( + reported_url: params[:reported_url] || params[:url] || request.referrer, + ) + render "pages/report-abuse" + end + def rlyweb set_surrogate_key_header "rlyweb" end diff --git a/app/dashboards/feedback_message_dashboard.rb b/app/dashboards/feedback_message_dashboard.rb index fdd66049a..b67e792ea 100644 --- a/app/dashboards/feedback_message_dashboard.rb +++ b/app/dashboards/feedback_message_dashboard.rb @@ -12,7 +12,7 @@ class FeedbackMessageDashboard < Administrate::BaseDashboard id: Field::Number, message: Field::Text, feedback_type: Field::String, - category_selection: Field::String, + category: Field::String, }.freeze # COLLECTION_ATTRIBUTES @@ -34,7 +34,7 @@ class FeedbackMessageDashboard < Administrate::BaseDashboard :id, :message, :feedback_type, - :category_selection, + :category, ].freeze # FORM_ATTRIBUTES @@ -44,7 +44,7 @@ class FeedbackMessageDashboard < Administrate::BaseDashboard :user, :message, :feedback_type, - :category_selection, + :category, ].freeze # Overwrite this method to customize how feedback messages are displayed diff --git a/app/mailers/notify_mailer.rb b/app/mailers/notify_mailer.rb index 3fb005ef1..3fc31a9f7 100644 --- a/app/mailers/notify_mailer.rb +++ b/app/mailers/notify_mailer.rb @@ -48,4 +48,15 @@ class NotifyMailer < ApplicationMailer @badge = @badge_achievement.badge mail(to: @user.email, subject: "You just got a badge") end + + def new_report_email(report) + @feedback_message = report + @user = report.reporter + mail(to: @user.email, subject: "Thank you for your report") + end + + def reporter_resolution_email(report) + @feedback_message = report + @user = report.reporter + end end diff --git a/app/models/feedback_message.rb b/app/models/feedback_message.rb index ed65606b6..32222314a 100644 --- a/app/models/feedback_message.rb +++ b/app/models/feedback_message.rb @@ -1,3 +1,41 @@ class FeedbackMessage < ApplicationRecord - belongs_to :user, optional: true + belongs_to :offender, foreign_key: "offender_id", class_name: "User", optional: true + belongs_to :reviewer, foreign_key: "reviewer_id", class_name: "User", optional: true + belongs_to :reporter, foreign_key: "reporter_id", class_name: "User", optional: true + belongs_to :victim, foreign_key: "victim_id", class_name: "User", optional: true + has_one :note, as: :noteable, dependent: :destroy + + validates_presence_of :feedback_type, :message + validates_presence_of :reported_url, :category, if: :abuse_report? + validates :category, + inclusion: { + in: ["spam", "other", "rude or vulgar", "harassment", "bug"], + } + + before_validation :generate_slug + + def abuse_report? + feedback_type == "abuse-reports" + end + + def generate_slug + self.slug = SecureRandom.hex(10) unless slug? + end + + def capitalize_status + self.status = status.capitalize unless status.blank? + end + + def to_eastern_strftime(time) + return if time.nil? + time.in_time_zone("America/New_York").strftime("%A, %b %d %Y - %I:%M %p %Z") + end + + def path + "/reports/#{slug}" + end + + def find_or_create_note(reason) + note || Note.new(reason: reason, noteable_id: id, noteable_type: "FeedbackMessage") + end end diff --git a/app/models/note.rb b/app/models/note.rb index e2a54fb2f..c2135b9bf 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -1,6 +1,6 @@ class Note < ApplicationRecord - belongs_to :user - validates :user_id, :reason, :content, presence: true - validates :user_id, uniqueness: - { scope: :reason, message: "limited to one note per user per reason" } + belongs_to :noteable, polymorphic: true + validates :reason, :content, presence: true + validates :noteable_id, uniqueness: + { scope: :reason, message: "limited to one note per noteable per reason" } end diff --git a/app/models/user.rb b/app/models/user.rb index 9577d4cd4..1d1112a39 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -22,13 +22,14 @@ class User < ApplicationRecord has_many :identities has_many :mentions has_many :messages - has_many :notes + has_many :notes, as: :noteable has_many :notifications has_many :reactions has_many :tweets has_many :chat_channel_memberships has_many :chat_channels, through: :chat_channel_memberships has_many :notification_subscriptions + has_many :feedback_messages mount_uploader :profile_image, ProfileImageUploader @@ -224,12 +225,12 @@ class User < ApplicationRecord def reason_for_ban return if notes.where(reason: "banned").blank? - Note.find_by(user_id: id, reason: "banned").content + Note.find_by(noteable_id: id, noteable_type: "User", reason: "banned").content end def reason_for_warning return if notes.where(reason: "warned").blank? - Note.find_by(user_id: id, reason: "warned").content + Note.find_by(noteable_id: id, noteable_type: "User", reason: "warned").content end def scholar diff --git a/app/services/user_role_service.rb b/app/services/user_role_service.rb index ffe668d45..e5dd1e022 100644 --- a/app/services/user_role_service.rb +++ b/app/services/user_role_service.rb @@ -67,10 +67,11 @@ class UserRoleService end def create_or_update_note(reason, content) - note = Note.find_by(user_id: @user.id, reason: reason) + note = Note.find_by(noteable_id: @user.id, noteable_type: "User", reason: reason) if note.nil? Note.create( - user_id: @user.id, + noteable_id: @user.id, + noteable_type: "User", reason: reason, content: content, ) diff --git a/app/views/comments/_comment.html.erb b/app/views/comments/_comment.html.erb index ab472147f..eb8a1321d 100644 --- a/app/views/comments/_comment.html.erb +++ b/app/views/comments/_comment.html.erb @@ -44,7 +44,7 @@ - Report Abuse + Report Abuse diff --git a/app/views/feedback_messages/_form.html.erb b/app/views/feedback_messages/_form.html.erb index 22f87a7c3..c5f9fa6ee 100644 --- a/app/views/feedback_messages/_form.html.erb +++ b/app/views/feedback_messages/_form.html.erb @@ -1,31 +1,51 @@ -<%= form_for FeedbackMessage.new do |f| %> + +<%= form_for feedback_message do |f| %> <%= f.hidden_field :feedback_type, value:"abuse-reports" %> -
  • - <%= f.radio_button :category_selection, "rude or vulgar", required: 'required' %> - <%= label_tag(:category_selection_rude, "Rude or vulgar") %> + <%= f.radio_button :category, "rude or vulgar", required: 'required' %> + <%= label_tag(:category_rude, "Rude or vulgar") %>
  • - <%= f.radio_button :category_selection, "harassment" %> - <%= label_tag(:category_selection_harassment, "Harassment or hate speech") %> + <%= f.radio_button :category, "harassment" %> + <%= label_tag(:category_harassment, "Harassment or hate speech") %>
  • - <%= f.radio_button :category_selection, "spam" %> - <%= label_tag(:category_selection_spam, "Spam or copyright issue") %> + <%= f.radio_button :category, "spam" %> + <%= label_tag(:category_spam, "Spam or copyright issue") %>
  • - <%= f.radio_button :category_selection, "other" %> - <%= label_tag(:category_selection_other, "Other") %> + <%= f.radio_button :category, "other" %> + <%= label_tag(:category_other, "Other") %>
+ Reported URL: + <%= f.text_field :reported_url, class: "reportedurlfield", value: feedback_message.reported_url, style: "width:100%;font-size: 18px; border-radius:3px;", required: true %>

- <%= f.text_area :message, style:"width:100%;resize:none;font-size:18px;height:100px;border-radius:3px;", placeholder:"Please provide any additional information, such as an URL, that will help us understand and handle the situation.", value: @previous_message %> + <%= f.label :message %>: + <%= f.text_area :message, class: "messagefield", placeholder:"Please provide any additional information or context that will help us understand and handle the situation.", value: @previous_message %>

- +
+
<% if flash[:notice] %>
@@ -33,6 +53,6 @@
<% end %> <%= recaptcha_tags site_key: ENV['RECAPTCHA_SITE'] %> - +
<% end %> diff --git a/app/views/feedback_messages/index.html.erb b/app/views/feedback_messages/index.html.erb index e056b0c88..ee303236a 100644 --- a/app/views/feedback_messages/index.html.erb +++ b/app/views/feedback_messages/index.html.erb @@ -1,25 +1,6 @@ - - -
-

Thank you.

-

Return to home page

+

Thank you for your report. You can view the
status of your report here.

+

Return to home page

diff --git a/app/views/feedback_messages/show.html.erb b/app/views/feedback_messages/show.html.erb new file mode 100644 index 000000000..ce28c3898 --- /dev/null +++ b/app/views/feedback_messages/show.html.erb @@ -0,0 +1,30 @@ + +
+

Thank you for your report. You can use this link to check for any updates on your report:

+

https://dev.to<%= @feedback_message.path %>

+

Note that the link above is public, but secret.

+
+

Current Status: <%= @feedback_message.status %>

+ <% if @feedback_message.feedback_type == "abuse-reports" %> +

+ Reported URL: <%= link_to @feedback_message.reported_url, @feedback_message.reported_url, target: "_blank" %> +
+ (Opens in a new tab) +

+
+

Category: <%= @feedback_message.category %>

+ <% end %> +

Message:

+

+ <% if @feedback_message.message.blank? %> + No message was left. + <% else %> + <%= @feedback_message.message %> + <% end %> +

+
+
+

+ Questions? Send an email to yo@dev.to +

+
diff --git a/app/views/internal/feedback_messages/_feedback_message.html.erb b/app/views/internal/feedback_messages/_feedback_message.html.erb new file mode 100644 index 000000000..80b94aaa3 --- /dev/null +++ b/app/views/internal/feedback_messages/_feedback_message.html.erb @@ -0,0 +1,60 @@ + + +

+ Report #<%= feedback_message.id %> - Submitted on: <%= feedback_message.to_eastern_strftime(feedback_message.created_at) %> +
+ Reporter: + <% if feedback_message.reporter_id? %> + <%= feedback_message.reporter.name %> + @<%= feedback_message.reporter.username %> + -- + Email: <%= feedback_message.reporter.email %> + <% else %> + Anonymous + <% end %> +

+

+ Reported URL (new tab): +
+ <%= feedback_message.reported_url %> +

+

Category: <%= feedback_message.category %>

+

+ Message: +

+

+ <% if feedback_message.message.blank? %> + No message was left. + <% else %> + <%= feedback_message.message %> + <% end %> +

+
+

+ Status: <%= f.select :status, ['Open', 'Closed', 'Resolved'] %> +

+

Note:

+ <%= f.fields_for :note do |note| %> + <%= note.hidden_field :reason, value: feedback_message.feedback_type %> + <%= note.text_area :content, value: feedback_message.note&.content, placeholder: "Leave some notes about the status and context of this report.", class: "notefield" %> + <% end %> + <%= f.hidden_field :reviewer_id, value: current_user.id %> + <% if feedback_message.reviewer_id %> +

Last reviewed by: <%= feedback_message.reviewer.name %>

+

Last reviewed on: <%= feedback_message.to_eastern_strftime(feedback_message.last_reviewed_at) %>

+ <% else %> +

Last reviewed by: No one yet

+ <% end %> +
+ diff --git a/app/views/internal/feedback_messages/index.html.erb b/app/views/internal/feedback_messages/index.html.erb new file mode 100644 index 000000000..981ebb5a6 --- /dev/null +++ b/app/views/internal/feedback_messages/index.html.erb @@ -0,0 +1,31 @@ + + +

+ ">Abuse Reports | + ">Bug Reports +

+ +

<%= @feedback_type.titleize %>

+ +<%= paginate @feedback_messages %> + + <% @feedback_messages.each do |feedback_message| %> +
+ <%= form_for [:internal, feedback_message] do |f| %> + <%= render "feedback_message", f: f, feedback_message: feedback_message %> + <% end %> +
+ <% end %> +
+
diff --git a/app/views/layouts/internal.html.erb b/app/views/layouts/internal.html.erb index 48d2559d6..11c2e9639 100644 --- a/app/views/layouts/internal.html.erb +++ b/app/views/layouts/internal.html.erb @@ -89,14 +89,10 @@ diff --git a/app/views/mailers/notify_mailer/new_report_email.html.erb b/app/views/mailers/notify_mailer/new_report_email.html.erb new file mode 100644 index 000000000..0e59288a1 --- /dev/null +++ b/app/views/mailers/notify_mailer/new_report_email.html.erb @@ -0,0 +1,6 @@ +Thank you for your report. You can check the status of your report here: +
+https://dev.to<%= @feedback_message.path %> +
+
+ If you have any questions, feel free to reply to this email, or send an email to yo@dev.to. \ No newline at end of file diff --git a/app/views/mailers/notify_mailer/new_report_email.text.erb b/app/views/mailers/notify_mailer/new_report_email.text.erb new file mode 100644 index 000000000..377f86665 --- /dev/null +++ b/app/views/mailers/notify_mailer/new_report_email.text.erb @@ -0,0 +1,4 @@ +Thank you for your report. You can check the status of your report here: +https://dev.to<%= @feedback_message.path %> + +If you have any questions, feel free to reply to this email, or send an email to yo@dev.to. \ No newline at end of file diff --git a/app/views/pages/report-abuse.html.erb b/app/views/pages/report-abuse.html.erb index fddf1a9f3..1f306430c 100644 --- a/app/views/pages/report-abuse.html.erb +++ b/app/views/pages/report-abuse.html.erb @@ -24,6 +24,6 @@

Thank you for reporting any abuse that violates our code of conduct or terms and conditions. We continue to try to make this environment a great one for everybody.

- <%= render 'feedback_messages/form' %> + <%= render 'feedback_messages/form', feedback_message: @feedback_message %> diff --git a/config/routes.rb b/config/routes.rb index eb49c4a00..55cbba4fe 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -32,6 +32,8 @@ Rails.application.routes.draw do end resources :members, only: [:index] resources :events + resources :feedback_messages, only: [:update] + resources :reports, only: [:index, :update], controller: "feedback_messages" mount Flipflop::Engine => "/features" end @@ -72,10 +74,11 @@ Rails.application.routes.draw do resources :messages, only: [:create] resources :chat_channels, only: [:index, :show] resources :articles, only: [:update,:create,:destroy] - resources :comments, only:[:create,:update,:destroy] - resources :users, only:[:update] - resources :reactions, only: [:index,:create] + resources :comments, only: [:create,:update,:destroy] + resources :users, only: [:update] + resources :reactions, only: [:index, :create] resources :feedback_messages, only: [:create] + get "/reports/:slug", to: "feedback_messages#show" resources :organizations, only: [:update, :create] resources :followed_articles, only: [:index] resources :follows, only: [:index,:show,:create] @@ -158,7 +161,7 @@ Rails.application.routes.draw do get "/rlyweb" => "pages#rlyweb" get "/rly" => "pages#rlyweb" get "/code-of-conduct" => "pages#code_of_conduct" - get "/report-abuse" => "pages#report-abuse" + get "/report-abuse" => "pages#report_abuse" get "/infiniteloop" => "pages#infinite_loop" get "/faq" => "pages#faq" get "/live" => "pages#live" diff --git a/db/migrate/20180603160906_add_columns_to_feedback_messages.rb b/db/migrate/20180603160906_add_columns_to_feedback_messages.rb new file mode 100644 index 000000000..68f0eb5c7 --- /dev/null +++ b/db/migrate/20180603160906_add_columns_to_feedback_messages.rb @@ -0,0 +1,18 @@ +class AddColumnsToFeedbackMessages < ActiveRecord::Migration[5.1] + def change + add_column :feedback_messages, :created_at, :datetime + add_column :feedback_messages, :updated_at, :datetime + add_column :feedback_messages, :last_reviewed_at, :datetime + add_column :feedback_messages, :status, :string, default: "Open" + add_column :feedback_messages, :victim_email_sent?, :boolean, default: false + add_column :feedback_messages, :reporter_email_sent?, :boolean, default: false + add_column :feedback_messages, :offender_email_sent?, :boolean, default: false + add_column :feedback_messages, :slug, :string + add_column :feedback_messages, :reported_url, :string + rename_column :feedback_messages, :user_id, :reporter_id + rename_column :feedback_messages, :category_selection, :category + add_column :feedback_messages, :reviewer_id, :integer + add_column :feedback_messages, :offender_id, :integer + add_column :feedback_messages, :victim_id, :integer + end +end diff --git a/db/migrate/20180608195204_change_notes_to_polymorphic.rb b/db/migrate/20180608195204_change_notes_to_polymorphic.rb new file mode 100644 index 000000000..0fc9f28ae --- /dev/null +++ b/db/migrate/20180608195204_change_notes_to_polymorphic.rb @@ -0,0 +1,6 @@ +class ChangeNotesToPolymorphic < ActiveRecord::Migration[5.1] + def change + rename_column :notes, :user_id, :noteable_id + add_column :notes, :noteable_type, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 2250e83cc..bb64b43a6 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -272,10 +272,22 @@ ActiveRecord::Schema.define(version: 20180612214259) do end create_table "feedback_messages", force: :cascade do |t| - t.string "category_selection" + t.string "category" + t.datetime "created_at" t.string "feedback_type" + t.datetime "last_reviewed_at" t.text "message" - t.integer "user_id" + t.boolean "offender_email_sent?", default: false + t.integer "offender_id" + t.string "reported_url" + t.boolean "reporter_email_sent?", default: false + t.integer "reporter_id" + t.integer "reviewer_id" + t.string "slug" + t.string "status", default: "Open" + t.datetime "updated_at" + t.boolean "victim_email_sent?", default: false + t.integer "victim_id" end create_table "flipflop_features", force: :cascade do |t| @@ -373,9 +385,10 @@ ActiveRecord::Schema.define(version: 20180612214259) do create_table "notes", id: :serial, force: :cascade do |t| t.text "content" t.datetime "created_at", null: false + t.integer "noteable_id" + t.string "noteable_type" t.string "reason" t.datetime "updated_at", null: false - t.integer "user_id" end create_table "notifications", id: :serial, force: :cascade do |t| diff --git a/public/500.html b/public/500.html index 74f61dd96..b8fdfd518 100644 --- a/public/500.html +++ b/public/500.html @@ -55,7 +55,7 @@ - +
@@ -67,6 +67,8 @@
+ +
diff --git a/spec/factories/feedback_messages.rb b/spec/factories/feedback_messages.rb new file mode 100644 index 000000000..bb44c3974 --- /dev/null +++ b/spec/factories/feedback_messages.rb @@ -0,0 +1,25 @@ +FactoryBot.define do + factory :feedback_message do + transient do + reporter_id 1 + end + + after(:create) do |feedback_message, evaluator| + feedback_message.update(reporter_id: evaluator.reporter_id) + end + end + + + trait :abuse_report do + feedback_type { "abuse-reports" } + message { "this is spam" } + category { "spam" } + reported_url { "https://dev.to" } + end + + trait :bug_report do + feedback_type { "bug-reports" } + message { "i clicked something and this happened" } + category { "bugs" } + end +end diff --git a/spec/mailers/notify_mailer_spec.rb b/spec/mailers/notify_mailer_spec.rb index 4b3c82540..f03a6218a 100644 --- a/spec/mailers/notify_mailer_spec.rb +++ b/spec/mailers/notify_mailer_spec.rb @@ -12,6 +12,7 @@ RSpec.describe NotifyMailer, type: :mailer do new_reply_email = described_class.new_reply_email(comment) expect(new_reply_email.subject).to include("replied to your") end + it "renders proper receiver" do new_reply_email = described_class.new_reply_email(comment) expect(new_reply_email.to).to eq([comment.user.email]) @@ -24,6 +25,7 @@ RSpec.describe NotifyMailer, type: :mailer do new_follower_email = described_class.new_follower_email(Follow.last) expect(new_follower_email.subject).to eq("#{user2.name} just followed you on dev.to") end + it "renders proper receiver" do user2.follow(user) new_follower_email = described_class.new_follower_email(Follow.last) @@ -37,11 +39,48 @@ RSpec.describe NotifyMailer, type: :mailer do new_mention_email = described_class.new_mention_email(mention) expect(new_mention_email.subject).to include("#{comment.user.name} just mentioned you") end + it "renders proper receiver" do mention = create(:mention, user_id: user2.id, mentionable_id: comment.id) new_mention_email = described_class.new_mention_email(mention) expect(new_mention_email.to).to eq([user2.email]) end end + + describe "#new_badge_email" do + let(:badge) { create(:badge) } + + it "renders proper subject" do + badge_achievement = BadgeAchievement.create(user_id: user.id, + badge_id: badge.id, + rewarder_id: user2.id, + rewarding_context_message_markdown: "Hello [Yoho](/hey)") + new_badge_email = described_class.new_badge_email(badge_achievement) + expect(new_badge_email.subject).to eq("You just got a badge") + end + + it "renders proper receiver" do + badge_achievement = BadgeAchievement.create(user_id: user.id, + badge_id: badge.id, + rewarder_id: user2.id, + rewarding_context_message_markdown: "Hello [Yoho](/hey)") + new_badge_email = described_class.new_badge_email(badge_achievement) + expect(new_badge_email.to).to eq([user.email]) + end + end + + describe "#new_report_email" do + it "renders proper subject" do + feedback_message = create(:feedback_message, :abuse_report, reporter_id: user.id) + new_report_email = described_class.new_report_email(feedback_message) + expect(new_report_email.subject).to eq("Thank you for your report") + end + + it "renders proper receiver" do + feedback_message = create(:feedback_message, :abuse_report, reporter_id: user.id) + new_report_email = described_class.new_report_email(feedback_message) + expect(new_report_email.to).to eq([user.email]) + end + end end end diff --git a/spec/mailers/previews/notify_mailer_preview.rb b/spec/mailers/previews/notify_mailer_preview.rb index 1fcb2f671..a2a74b030 100644 --- a/spec/mailers/previews/notify_mailer_preview.rb +++ b/spec/mailers/previews/notify_mailer_preview.rb @@ -23,4 +23,8 @@ class NotifyMailerPreview < ActionMailer::Preview def new_badge_email NotifyMailer.new_badge_email(BadgeAchievement.first) end + + def new_report_email + NotifyMailer.new_report_email(FeedbackMessage.first) + end end diff --git a/spec/models/feedback_message_spec.rb b/spec/models/feedback_message_spec.rb new file mode 100644 index 000000000..819e39662 --- /dev/null +++ b/spec/models/feedback_message_spec.rb @@ -0,0 +1,49 @@ +require "rails_helper" + +RSpec.describe FeedbackMessage, type: :model do + let(:user) { create(:user) } + let(:abuse_report) { create(:feedback_message, :abuse_report) } + + describe "validations for an abuse report" do + subject do + FeedbackMessage.new( + feedback_type: "abuse-reports", + reported_url: "https://dev.to", + category: "spam", + message: "something", + ) + end + + it { is_expected.to validate_presence_of(:feedback_type) } + it { is_expected.to validate_presence_of(:reported_url) } + it { is_expected.to validate_presence_of(:message) } + + it do + is_expected.to validate_inclusion_of(:category). + in_array(["spam", "other", "rude or vulgar", "harassment", "bug"]) + end + end + + describe "validations for a bug report" do + subject do + FeedbackMessage.new( + feedback_type: "bug-reports", + category: "bug", + message: "something", + ) + end + + it { is_expected.to validate_presence_of(:feedback_type) } + it { is_expected.to validate_presence_of(:message) } + it { is_expected.not_to validate_presence_of(:reported_url) } + + it do + is_expected.to validate_inclusion_of(:category). + in_array(["spam", "other", "rude or vulgar", "harassment", "bug"]) + end + end + + it "always generates a slug" do + expect(abuse_report.slug).not_to be_nil + end +end diff --git a/spec/requests/feedback_messages_create_spec.rb b/spec/requests/feedback_messages_create_spec.rb index 82398d03a..903e81b29 100644 --- a/spec/requests/feedback_messages_create_spec.rb +++ b/spec/requests/feedback_messages_create_spec.rb @@ -3,17 +3,53 @@ require "rails_helper" RSpec.describe "feedback_messages", type: :request do describe "POST /feedback_messages" do before do - allow_any_instance_of(FeedbackMessagesController).to receive(:recaptcha_verified?).and_return(true) + allow_any_instance_of(FeedbackMessagesController). + to receive(:recaptcha_verified?).and_return(true) allow_any_instance_of(Slack::Notifier).to receive(:ping).and_return(true) end - it "creates feedback message with filled form" do - new_body = "NEW BODY #{rand(100)}" - post "/feedback_messages", params: { - feedback_message: { feedback_type: "abuse-reports", - category_selection: "other", - message: new_body }, - } - expect(FeedbackMessage.last.message).to eq(new_body) + + valid_abuse_report_params = { + feedback_message: { + feedback_type: "abuse-reports", + category: "rude or vulgar", + reported_url: "https://dev.to", + message: "this was vulgar", + }, + } + + context "with valid params" do + before do + post "/feedback_messages", params: valid_abuse_report_params + end + + it "creates feedback message with filled form" do + expect(FeedbackMessage.last.message).to eq( + valid_abuse_report_params[:feedback_message][:message], + ) + end + + it "redirects to the ticket page" do + expect(response).to redirect_to(FeedbackMessage.last.path) + end + end + + context "when a logged in user submits report" do + let!(:user) { create(:user) } + let(:mail_message) { instance_double(Mail::Message, deliver: true) } + + before do + allow(NotifyMailer).to receive(:new_report_email).and_return(mail_message) + login_as(user) + post "/feedback_messages", params: valid_abuse_report_params + end + + it "adds the logged in user as as the reporter" do + expect(FeedbackMessage.find_by(reporter_id: user.id)).not_to eq(nil) + end + + it "sends an email to the reporter" do + expect(NotifyMailer).to have_received(:new_report_email) + end end end end diff --git a/spec/requests/internal_feedback_messages_update_spec.rb b/spec/requests/internal_feedback_messages_update_spec.rb new file mode 100644 index 000000000..098384823 --- /dev/null +++ b/spec/requests/internal_feedback_messages_update_spec.rb @@ -0,0 +1,42 @@ +require "rails_helper" + +RSpec.describe "/internal/feedback_messages", type: :request do + describe "PUTS /internal/feedback_messages" do + context "with a valid request" do + let(:feedback_message) { create(:feedback_message, :abuse_report) } + let(:admin) { create(:user, :super_admin) } + + valid_abuse_report_params = { + feedback_message: { + id: 1, + status: "Resolved", + note: { + content: "this is valid", + reason: "abuse-reports", + }, + }, + } + + before do + login_as(admin) + valid_abuse_report_params[:feedback_message][:reviewer_id] = admin.id + patch "/internal/feedback_messages/#{feedback_message.id}", params: + valid_abuse_report_params + end + + it "adds a note to a report" do + expect(FeedbackMessage.last.note.content).to eq( + valid_abuse_report_params[:feedback_message][:note][:content], + ) + end + + it "adds the current user as the reviewer" do + expect(FeedbackMessage.find_by(reviewer_id: admin.id)).not_to eq(nil) + end + + it "updates the last_reviewed_at timestamp" do + expect(FeedbackMessage.last.last_reviewed_at).not_to eq(nil) + end + end + end +end