Drop comments, likes, and PMs from people who the (post/conversation) owner is ignoring.

This commit is contained in:
Sarah Mei 2012-02-01 17:51:17 -08:00
parent 488e064e11
commit 085d6552b3
8 changed files with 69 additions and 21 deletions

View file

@ -50,7 +50,7 @@ class AccountDeleter
end
def ignored_ar_user_associations
[:followed_tags, :invited_by, :contact_people, :applications, :aspect_memberships]
[:followed_tags, :invited_by, :contact_people, :applications, :aspect_memberships, :ignored_people]
end
def delete_standard_user_associations

View file

@ -33,10 +33,9 @@ class Comment < ActiveRecord::Base
alias_attribute :post, :commentable
belongs_to :author, :class_name => 'Person'
validates :text, :presence => true, :length => { :maximum => 2500 }
validates :text, :presence => true, :length => {:maximum => 2500}
validates :parent, :presence => true #should be in relayable (pending on fixing Message)
scope :including_author, includes(:author => :profile)
scope :for_a_stream, including_author.merge(order('created_at ASC'))

View file

@ -40,13 +40,20 @@ class User < ActiveRecord::Base
has_many :aspects, :order => 'order_id ASC'
belongs_to :auto_follow_back_aspect, :class_name => 'Aspect'
has_many :aspect_memberships, :through => :aspects
has_many :contacts
has_many :contact_people, :through => :contacts, :source => :person
has_many :services
has_many :user_preferences
has_many :tag_followings
has_many :followed_tags, :through => :tag_followings, :source => :tag, :order => 'tags.name'
has_many :blocks
has_many :ignored_people, :through => :blocks, :source => :person
has_many :notifications, :foreign_key => :recipient_id
has_many :authorizations, :class_name => 'OAuth2::Provider::Models::ActiveRecord::Authorization', :foreign_key => :resource_owner_id

View file

@ -15,11 +15,23 @@ module Diaspora
validates_associated :parent
validates :author, :presence => true
validate :author_is_not_ignored
delegate :public?, :to => :parent
end
end
def author_is_not_ignored
if self.new_record? && self.parent.present?
post_author = self.parent.author
relayable_author = self.author
if post_author.local? && post_author.owner.ignored_people.include?(relayable_author)
self.errors.add(:author_id, 'This person is ignored by the post author')
end
end
end
# @return [Boolean] true
def relayable?
true
@ -49,19 +61,20 @@ module Diaspora
def receive(user, person=nil)
comment_or_like = self.class.where(:guid => self.guid).first || self
#check to make sure the signature of the comment or like comes from the person claiming to authoring said comment or like
# Check to make sure the signature of the comment or like comes from the person claiming to author it
unless comment_or_like.parent.author == user.person || comment_or_like.verify_parent_author_signature
Rails.logger.info("event=receive status=abort reason='object signature not valid' recipient=#{user.diaspora_handle} sender=#{self.parent.author.diaspora_handle} payload_type=#{self.class} parent_id=#{self.parent.id}")
return
end
#as the owner of the post being liked or commented on, you need to add your own signature in order to pass it to the people who received your original post
# As the owner of the post being liked or commented on, you need to add your own signature in order to
# pass it to the people who received your original post
if user.owns? comment_or_like.parent
comment_or_like.parent_author_signature = comment_or_like.sign_with_key(user.encryption_key)
comment_or_like.save!
end
#dispatch object DOWNSTREAM, received it via UPSTREAM
# Dispatch object DOWNSTREAM, received it via UPSTREAM
unless user.owns?(comment_or_like)
comment_or_like.save!
Postzord::Dispatcher.build(user, comment_or_like).post

View file

@ -3,7 +3,7 @@
# the COPYRIGHT file.
require 'spec_helper'
require File.join(Rails.root, "spec", "shared_behaviors", "relayable")
require Rails.root.join("spec", "shared_behaviors", "relayable")
describe Comment do
before do
@ -111,6 +111,8 @@ describe Comment do
@object_on_remote_parent = @local_luke.comment!(@remote_parent, "Yeah, it was great")
end
let(:build_object) { alice.build_comment(:post => @status, :text => "why so formal?") }
it_should_behave_like 'it is relayable'
end

View file

@ -111,6 +111,8 @@ describe Like do
@object_on_remote_parent = @local_luke.like(0, :target => @remote_parent)
end
let(:build_object) { alice.build_like(:target => @status, :positive => 1) }
it_should_behave_like 'it is relayable'
end

View file

@ -3,36 +3,34 @@
# the COPYRIGHT file.
require 'spec_helper'
require File.join(Rails.root, "spec", "shared_behaviors", "relayable")
require Rails.root.join("spec", "shared_behaviors", "relayable")
describe Message do
before do
@user1 = alice
@user2 = bob
@create_hash = {
:author => @user1.person,
:participant_ids => [@user1.contacts.first.person.id, @user1.person.id],
:author => bob.person,
:participant_ids => [bob.person.id, alice.person.id],
:subject => "cool stuff",
:messages_attributes => [ {:author => @user1.person, :text => 'stuff'} ]
:messages_attributes => [ {:author => bob.person, :text => 'stuff'} ]
}
@cnv = Conversation.create!(@create_hash)
@message = @cnv.messages.first
@conversation = Conversation.create!(@create_hash)
@message = @conversation.messages.first
@xml = @message.to_diaspora_xml
end
it 'validates that the author is a participant in the conversation' do
msg = Message.new(:text => 'yo', :author => eve.person, :conversation_id => @cnv.id)
message = Message.new(:text => 'yo', :author => eve.person, :conversation_id => @conversation.id)
message.should_not be_valid
end
describe '#notification_type' do
it 'does not return anything for the author' do
@message.notification_type(@user1, @user1.person).should be_nil
@message.notification_type(bob, bob.person).should be_nil
end
it 'returns private mesage for an actual receiver' do
@message.notification_type(@user2, @user1.person).should == Notifications::PrivateMessage
@message.notification_type(alice, bob.person).should == Notifications::PrivateMessage
end
end
@ -94,13 +92,15 @@ describe Message do
@object_on_remote_parent = Message.create(msg_hash)
Postzord::Dispatcher.build(@local_luke, @object_on_remote_parent).post
end
let(:build_object) { Message.new(:author => @alice.person, :text => "ohai!", :conversation => @conversation) }
it_should_behave_like 'it is relayable'
describe '#after_receive' do
it 'increments the conversation visiblity for the conversation' do
ConversationVisibility.where(:conversation_id => @object_by_recipient.reload.conversation.id,
:person_id => @local_luke.person.id).first.unread.should == 0
@object_by_recipient.receive(@local_luke, @local_leia.person)
ConversationVisibility.where(:conversation_id => @object_by_recipient.reload.conversation.id,
:person_id => @local_luke.person.id).first.unread.should == 1

View file

@ -7,6 +7,31 @@ require 'spec_helper'
describe Diaspora::Relayable do
shared_examples_for "it is relayable" do
describe 'validations' do
describe 'on :author_id' do
it "is invalid if the author is on the parent post author's ignore list when object is created" do
bob.blocks.create(:person => alice.person)
relayable = build_object
relayable.should_not be_valid
relayable.should have(1).error_on(:author_id)
end
it "works if the object has no parent" do # This can happen if we get a comment for a post that's been deleted
bob.blocks.create(:person => alice.person)
relayable = build_object
relayable.parent = nil
expect { relayable.valid? }.to_not raise_exception
end
it "is valid if the author is added to the parent post author's ignore list later" do
relayable = build_object
relayable.save!
bob.blocks.create(:person => alice.person)
relayable.should be_valid
end
end
end
context 'encryption' do
describe '#parent_author_signature' do
it 'should sign the object if the user is the post author' do
@ -37,7 +62,7 @@ describe Diaspora::Relayable do
context 'propagation' do
describe '#receive' do
it 'does not overwrite a object that is already in the db' do
lambda{
lambda {
@dup_object_by_parent_author.receive(@local_leia, @local_luke.person)
}.should_not change(@dup_object_by_parent_author.class, :count)
end