Added post report feature
You can report a single post by clicking the correct icon in the controler section Workflow: * Report a post as offensive * Trigger alerts to every pod-admin * Pod-admin can review it in the admin interface * Delete the post or mark it as reviewed
This commit is contained in:
parent
1a8541ff1a
commit
5c9a3aaf3e
21 changed files with 306 additions and 3 deletions
|
|
@ -25,7 +25,7 @@
|
|||
* Collapse aspect list and tag followings list when switching to other views [#4462](https://github.com/diaspora/diaspora/pull/4462)
|
||||
* Highlight current stream in left sidebar [#4445](https://github.com/diaspora/diaspora/pull/4445)
|
||||
* Added ignore user icon [#4417](https://github.com/diaspora/diaspora/pull/4417)
|
||||
|
||||
* You can report a single post by clicking the correct icon in the controler section [#4517](https://github.com/diaspora/diaspora/pull/4517)
|
||||
|
||||
# 0.2.0.0
|
||||
|
||||
|
|
|
|||
BIN
app/assets/images/icons/postreport.png
Normal file
BIN
app/assets/images/icons/postreport.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 173 B |
3
app/assets/javascripts/app/models/post_report.js
Normal file
3
app/assets/javascripts/app/models/post_report.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
app.models.PostReport = Backbone.Model.extend({
|
||||
urlRoot: '/post_report'
|
||||
});
|
||||
|
|
@ -19,6 +19,7 @@ app.views.StreamPost = app.views.Post.extend({
|
|||
|
||||
"click .remove_post": "destroyModel",
|
||||
"click .hide_post": "hidePost",
|
||||
"click .post_report": "postReport",
|
||||
"click .block_user": "blockUser"
|
||||
},
|
||||
|
||||
|
|
@ -106,6 +107,21 @@ app.views.StreamPost = app.views.Post.extend({
|
|||
this.remove();
|
||||
},
|
||||
|
||||
postReport : function(evt) {
|
||||
if(evt) { evt.preventDefault(); }
|
||||
var text = prompt(Diaspora.I18n.t('post_report_prompt'),
|
||||
Diaspora.I18n.t('post_report_prompt_default'));
|
||||
|
||||
var postReport = new app.models.PostReport();
|
||||
postReport.fetch({
|
||||
data: {
|
||||
post_id: this.model.id,
|
||||
text: text
|
||||
},
|
||||
type: 'POST'
|
||||
});
|
||||
},
|
||||
|
||||
focusCommentTextarea: function(evt){
|
||||
evt.preventDefault();
|
||||
this.$(".new_comment_form_wrapper").removeClass("hidden");
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
@import 'opengraph'
|
||||
@import 'help'
|
||||
@import 'profile'
|
||||
@import 'post_report'
|
||||
|
||||
/* ====== media ====== */
|
||||
.media
|
||||
|
|
@ -267,6 +268,13 @@ ul.as-selections
|
|||
:z-index 6
|
||||
:float right
|
||||
|
||||
.post_report
|
||||
:display inline-block
|
||||
|
||||
.icons-postreport
|
||||
:height 14px
|
||||
:width 14px
|
||||
|
||||
.block_user
|
||||
:display inline-block
|
||||
|
||||
|
|
|
|||
16
app/assets/stylesheets/post_report.css.scss
Normal file
16
app/assets/stylesheets/post_report.css.scss
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#post_report {
|
||||
padding-top: 2em;
|
||||
span {
|
||||
display: block;
|
||||
}
|
||||
.content {
|
||||
float: left;
|
||||
}
|
||||
.options {
|
||||
float: right;
|
||||
}
|
||||
.clear {
|
||||
clear: both;
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,9 @@
|
|||
{{#if loggedIn}}
|
||||
<div class="controls">
|
||||
{{#unless authorIsCurrentUser}}
|
||||
<a href="#" rel="nofollow" class="post_report" title="{{t "post_report"}}">
|
||||
<div class="icons-postreport control_icon"/>
|
||||
</a>
|
||||
<a href="#" rel="nofollow" class="block_user" title="{{t "ignore"}}">
|
||||
<div class="icons-ignoreuser control_icon"></div>
|
||||
</a>
|
||||
|
|
|
|||
61
app/controllers/post_report_controller.rb
Normal file
61
app/controllers/post_report_controller.rb
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
class PostReportController < ApplicationController
|
||||
before_filter :authenticate_user!
|
||||
before_filter :redirect_unless_admin, :except => [:create]
|
||||
|
||||
def index
|
||||
@post_report = PostReport.where(reviewed: false).all
|
||||
end
|
||||
|
||||
def update
|
||||
if PostReport.exists?(post_id: params[:id])
|
||||
mark_as_reviewed
|
||||
end
|
||||
redirect_to :action => :index and return
|
||||
end
|
||||
|
||||
def destroy
|
||||
if Post.exists?(params[:id])
|
||||
delete_post
|
||||
mark_as_reviewed
|
||||
end
|
||||
redirect_to :action => :index and return
|
||||
end
|
||||
|
||||
def create
|
||||
username = current_user.username
|
||||
unless PostReport.where(post_id: params[:post_id]).exists?(user_id: username)
|
||||
post = PostReport.new(
|
||||
:post_id => params[:post_id],
|
||||
:user_id => username,
|
||||
:text => params[:text])
|
||||
result = post.save
|
||||
status(( 200 if result ) || ( 422 if !result ))
|
||||
else
|
||||
status(409)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def delete_post
|
||||
post = Post.find(params[:id])
|
||||
current_user.retract(post)
|
||||
flash[:notice] = I18n.t 'post_report.status.destroyed'
|
||||
end
|
||||
|
||||
def mark_as_reviewed id = params[:id]
|
||||
posts = PostReport.where(post_id: id)
|
||||
posts.each do |post|
|
||||
post.update_attributes(reviewed: true)
|
||||
end
|
||||
flash[:notice] = I18n.t 'post_report.status.marked'
|
||||
end
|
||||
|
||||
def status(code)
|
||||
if code == 200
|
||||
flash[:notice] = I18n.t 'post_report.status.created'
|
||||
else
|
||||
flash[:error] = I18n.t 'post_report.status.failed'
|
||||
end
|
||||
render :nothing => true, :status => code
|
||||
end
|
||||
end
|
||||
18
app/mailers/post_report_mailer.rb
Normal file
18
app/mailers/post_report_mailer.rb
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
class PostReportMailer < ActionMailer::Base
|
||||
default :from => AppConfig.mail.sender_address
|
||||
|
||||
def new_report
|
||||
Role.admins.each do |role|
|
||||
email = User.find_by_id(role.person_id).email
|
||||
format(email).deliver
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def format(email)
|
||||
mail(to: email, subject: I18n.t('notifier.post_report_email.subject')) do |format|
|
||||
format.text { render 'post_report/post_report_email' }
|
||||
format.html { render 'post_report/post_report_email' }
|
||||
end
|
||||
end
|
||||
end
|
||||
15
app/models/post_report.rb
Normal file
15
app/models/post_report.rb
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
class PostReport < ActiveRecord::Base
|
||||
validates :user_id, presence: true
|
||||
validates :post_id, presence: true
|
||||
|
||||
belongs_to :user
|
||||
belongs_to :post
|
||||
|
||||
has_many :post_reports
|
||||
|
||||
after_create :send_report_notification
|
||||
|
||||
def send_report_notification
|
||||
Workers::Mail::PostReportWorker.perform_async
|
||||
end
|
||||
end
|
||||
|
|
@ -2,6 +2,8 @@
|
|||
class Role < ActiveRecord::Base
|
||||
belongs_to :person
|
||||
|
||||
scope :admins, -> { where(name: 'admin') }
|
||||
|
||||
def self.is_admin?(person)
|
||||
find_by_person_id_and_name(person.id, 'admin')
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
%li= link_to t('.user_search'), user_search_path
|
||||
%li= link_to t('.weekly_user_stats'), weekly_user_stats_path
|
||||
%li= link_to t('.pod_stats'), pod_stats_path
|
||||
%li= link_to t('.post_report'), post_report_index_path
|
||||
%li= link_to t('.correlations'), correlations_path
|
||||
%li= link_to t('.sidekiq_monitor'), sidekiq_path
|
||||
|
||||
|
|
|
|||
21
app/views/post_report/index.html.haml
Normal file
21
app/views/post_report/index.html.haml
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
.span-24
|
||||
= render :partial => 'admins/admin_bar'
|
||||
|
||||
.span-24.last
|
||||
%h1
|
||||
= t('post_report.title')
|
||||
%div#post_report
|
||||
- @post_report.each do |report|
|
||||
%div.content
|
||||
%span
|
||||
= raw t('post_report.post_label', title: link_to(post_page_title(Post.find_by_id(report.post_id)), post_path(report.post_id)))
|
||||
%span
|
||||
= raw t('post_report.reported_label', person: link_to(report.user_id, user_profile_path(report.user_id)))
|
||||
%span
|
||||
= t('post_report.reason_label', text: report.text)
|
||||
%div.options
|
||||
%span
|
||||
= link_to t('post_report.review_link'), post_report_path(report.post_id), method: :put
|
||||
%span
|
||||
= link_to t('post_report.delete_link'), post_report_path(report.post_id), method: :delete
|
||||
%div.clear
|
||||
2
app/views/post_report/post_report_email.markerb
Normal file
2
app/views/post_report/post_report_email.markerb
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<%= t('notifier.post_report_email.body') %>
|
||||
|
||||
12
app/workers/mail/post_report_worker.rb
Normal file
12
app/workers/mail/post_report_worker.rb
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
module Workers
|
||||
module Mail
|
||||
class PostReportWorker < Base
|
||||
sidekiq_options queue: :mail
|
||||
|
||||
def perform
|
||||
PostReportMailer.new_report
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -91,6 +91,7 @@ en:
|
|||
user_search: "User Search"
|
||||
weekly_user_stats: "Weekly User Stats"
|
||||
pod_stats: "Pod Stats"
|
||||
post_report: "Reported Posts"
|
||||
correlations: "Correlations"
|
||||
sidekiq_monitor: "Sidekiq monitor"
|
||||
correlations:
|
||||
|
|
@ -716,6 +717,9 @@ en:
|
|||
confirm_email:
|
||||
subject: "Please activate your new email address %{unconfirmed_email}"
|
||||
click_link: "To activate your new email address %{unconfirmed_email}, please follow this link:"
|
||||
post_report_email:
|
||||
subject: "A new post was marked as offensive"
|
||||
body: "Please review as soon as possible!"
|
||||
accept_invite: "Accept Your diaspora* invite!"
|
||||
invited_you: "%{name} invited you to diaspora*"
|
||||
invite:
|
||||
|
|
@ -845,6 +849,19 @@ en:
|
|||
other: "%{count} photos by %{author}"
|
||||
reshare_by: "Reshare by %{author}"
|
||||
|
||||
post_report:
|
||||
title: "Marked Reports Overview"
|
||||
post_label: "<b>Post</b>: %{title}"
|
||||
reported_label: "<b>Reported by</b> %{person}"
|
||||
reason_label: "Reason: %{text}"
|
||||
review_link: "Mark as reviewed"
|
||||
delete_link: "Delete post"
|
||||
status:
|
||||
marked: "The report was marked as reviewed"
|
||||
destroyed: "The post was destroyed"
|
||||
created: "A report was created"
|
||||
failed: "Something went wrong"
|
||||
|
||||
share_visibilites:
|
||||
update:
|
||||
post_hidden_and_muted: "%{name}'s post has been hidden, and notifications have been muted."
|
||||
|
|
|
|||
|
|
@ -6,8 +6,11 @@
|
|||
en:
|
||||
javascripts:
|
||||
confirm_dialog: "Are you sure?"
|
||||
post_report_prompt: "Please enter a reason:"
|
||||
post_report_prompt_default: "offensive content"
|
||||
delete: "Delete"
|
||||
ignore: "Ignore"
|
||||
post_report: "Report"
|
||||
ignore_user: "Ignore this user?"
|
||||
and: "and"
|
||||
comma: ","
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
require 'sidekiq/web'
|
||||
|
||||
Diaspora::Application.routes.draw do
|
||||
resources :post_report, :except => [:edit]
|
||||
|
||||
if Rails.env.production?
|
||||
mount RailsAdmin::Engine => '/admin_panel', :as => 'rails_admin'
|
||||
end
|
||||
|
|
|
|||
13
db/migrate/20131017093025_create_post_reports.rb
Normal file
13
db/migrate/20131017093025_create_post_reports.rb
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
class CreatePostReports < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :post_reports do |t|
|
||||
t.integer :post_id, :null => false
|
||||
t.string :user_id
|
||||
t.boolean :reviewed, :default => false
|
||||
t.text :text
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
add_index :post_reports, :post_id
|
||||
end
|
||||
end
|
||||
15
db/schema.rb
15
db/schema.rb
|
|
@ -11,7 +11,7 @@
|
|||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20130801063213) do
|
||||
ActiveRecord::Schema.define(:version => 20131017093025) do
|
||||
|
||||
create_table "account_deletions", :force => true do |t|
|
||||
t.string "diaspora_handle"
|
||||
|
|
@ -283,6 +283,17 @@ ActiveRecord::Schema.define(:version => 20130801063213) do
|
|||
t.datetime "updated_at", :null => false
|
||||
end
|
||||
|
||||
create_table "post_reports", :force => true do |t|
|
||||
t.integer "post_id", :null => false
|
||||
t.string "user_id"
|
||||
t.boolean "reviewed", :default => false
|
||||
t.text "text"
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
end
|
||||
|
||||
add_index "post_reports", ["post_id"], :name => "index_post_reports_on_post_id"
|
||||
|
||||
create_table "posts", :force => true do |t|
|
||||
t.integer "author_id", :null => false
|
||||
t.boolean "public", :default => false, :null => false
|
||||
|
|
@ -316,8 +327,8 @@ ActiveRecord::Schema.define(:version => 20130801063213) do
|
|||
t.boolean "favorite", :default => false
|
||||
t.string "facebook_id"
|
||||
t.string "tweet_id"
|
||||
t.text "tumblr_ids"
|
||||
t.integer "open_graph_cache_id"
|
||||
t.text "tumblr_ids"
|
||||
end
|
||||
|
||||
add_index "posts", ["author_id", "root_guid"], :name => "index_posts_on_author_id_and_root_guid", :unique => true
|
||||
|
|
|
|||
79
spec/controllers/post_report_controller_spec.rb
Normal file
79
spec/controllers/post_report_controller_spec.rb
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe PostReportController do
|
||||
before do
|
||||
sign_in alice
|
||||
@message = alice.post(:status_message, :text => "hey", :to => alice.aspects.first.id)
|
||||
end
|
||||
|
||||
describe '#index' do
|
||||
context 'admin not signed in' do
|
||||
it 'is behind redirect_unless_admin' do
|
||||
get :index
|
||||
response.should redirect_to stream_path
|
||||
end
|
||||
end
|
||||
|
||||
context 'admin signed in' do
|
||||
before do
|
||||
Role.add_admin(alice.person)
|
||||
end
|
||||
it 'succeeds and renders index' do
|
||||
get :index
|
||||
response.should render_template('index')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#create' do
|
||||
context 'report offensive content' do
|
||||
it 'succeeds' do
|
||||
put :create, :post_id => @message.id, :text => 'offensive content'
|
||||
response.status.should == 200
|
||||
PostReport.exists?(:post_id => @message.id).should be_true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#update' do
|
||||
context 'mark report as user' do
|
||||
it 'is behind redirect_unless_admin' do
|
||||
put :update, :id => @message.id
|
||||
response.should redirect_to stream_path
|
||||
PostReport.where(:reviewed => false, :post_id => @message.id).should be_true
|
||||
end
|
||||
end
|
||||
|
||||
context 'mark report as admin' do
|
||||
before do
|
||||
Role.add_admin(alice.person)
|
||||
end
|
||||
it 'succeeds' do
|
||||
put :update, :id => @message.id
|
||||
response.status.should == 302
|
||||
PostReport.where(:reviewed => true, :post_id => @message.id).should be_true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#destroy' do
|
||||
context 'destroy post as user' do
|
||||
it 'is behind redirect_unless_admin' do
|
||||
delete :destroy, :id => @message.id
|
||||
response.should redirect_to stream_path
|
||||
PostReport.where(:reviewed => false, :post_id => @message.id).should be_true
|
||||
end
|
||||
end
|
||||
|
||||
context 'destroy post as admin' do
|
||||
before do
|
||||
Role.add_admin(alice.person)
|
||||
end
|
||||
it 'succeeds' do
|
||||
delete :destroy, :id => @message.id
|
||||
response.status.should == 302
|
||||
PostReport.where(:reviewed => true, :post_id => @message.id).should be_true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Reference in a new issue