diff --git a/lib/diaspora/federation/receive.rb b/lib/diaspora/federation/receive.rb index 4ef4e459d..b760ce4d3 100644 --- a/lib/diaspora/federation/receive.rb +++ b/lib/diaspora/federation/receive.rb @@ -245,10 +245,11 @@ module Diaspora private_class_method :save_status_message def self.retract_if_author_ignored(relayable) - parent_author = relayable.parent.author - return unless parent_author.local? && parent_author.owner.ignored_people.include?(relayable.author) + parent_author = relayable.parent.author.owner + return unless parent_author && parent_author.ignored_people.include?(relayable.author) - # TODO: send retraction + retraction = Retraction.for(relayable, parent_author) + Diaspora::Federation::Dispatcher.build(parent_author, retraction, subscribers: [relayable.author]).dispatch raise Diaspora::Federation::AuthorIgnored end diff --git a/spec/lib/diaspora/federation/receive_spec.rb b/spec/lib/diaspora/federation/receive_spec.rb index b7dc03902..33605b636 100644 --- a/spec/lib/diaspora/federation/receive_spec.rb +++ b/spec/lib/diaspora/federation/receive_spec.rb @@ -2,7 +2,7 @@ require "spec_helper" describe Diaspora::Federation::Receive do let(:sender) { FactoryGirl.create(:person) } - let(:post) { alice.post(:status_message, text: "hello", public: true) } + let(:post) { FactoryGirl.create(:status_message, text: "hello", public: true, author: alice.person) } describe ".account_deletion" do let(:account_deletion_entity) { FactoryGirl.build(:account_deletion_entity, author: sender.diaspora_handle) } @@ -39,9 +39,9 @@ describe Diaspora::Federation::Receive do expect(comment.post).to eq(post) end - it_behaves_like "it ignores existing object received twice", Comment, :comment do - let(:entity) { comment_entity } - end + let(:entity) { comment_entity } + it_behaves_like "it ignores existing object received twice", Comment, :comment + it_behaves_like "it rejects if the parent author ignores the author", Comment, :comment end describe ".contact" do @@ -155,9 +155,9 @@ describe Diaspora::Federation::Receive do expect(like.target).to eq(post) end - it_behaves_like "it ignores existing object received twice", Like, :like do - let(:entity) { like_entity } - end + let(:entity) { like_entity } + it_behaves_like "it ignores existing object received twice", Like, :like + it_behaves_like "it rejects if the parent author ignores the author", Like, :like end describe ".message" do @@ -291,7 +291,7 @@ describe Diaspora::Federation::Receive do end describe ".poll_participation" do - let(:post_with_poll) { FactoryGirl.create(:status_message_with_poll) } + let(:post_with_poll) { FactoryGirl.create(:status_message_with_poll, author: alice.person) } let(:poll_participation_entity) { FactoryGirl.build( :poll_participation_entity, @@ -320,9 +320,9 @@ describe Diaspora::Federation::Receive do expect(poll_participation.poll).to eq(post_with_poll.poll) end - it_behaves_like "it ignores existing object received twice", PollParticipation, :poll_participation do - let(:entity) { poll_participation_entity } - end + let(:entity) { poll_participation_entity } + it_behaves_like "it ignores existing object received twice", PollParticipation, :poll_participation + it_behaves_like "it rejects if the parent author ignores the author", PollParticipation, :poll_participation end describe ".profile" do diff --git a/spec/models/comment_spec.rb b/spec/models/comment_spec.rb index b791701cd..cd6cc88cb 100644 --- a/spec/models/comment_spec.rb +++ b/spec/models/comment_spec.rb @@ -84,7 +84,7 @@ describe Comment, :type => :model do @object_on_remote_parent = object_on_remote_parent end - let(:build_object) { alice.build_comment(post: status_bob, text: "why so formal?") } + let(:relayable) { Comment::Generator.new(alice, status_bob, "why so formal?").build } it_should_behave_like "it is relayable" end diff --git a/spec/models/like_spec.rb b/spec/models/like_spec.rb index 4f06c1ec2..a36702c72 100644 --- a/spec/models/like_spec.rb +++ b/spec/models/like_spec.rb @@ -59,7 +59,7 @@ describe Like, :type => :model do @object_on_remote_parent = @local_luke.like!(@remote_parent) end - let(:build_object) { Like::Generator.new(alice, @status).build } - it_should_behave_like 'it is relayable' + let(:relayable) { Like::Generator.new(alice, @status).build } + it_should_behave_like "it is relayable" end end diff --git a/spec/models/message_spec.rb b/spec/models/message_spec.rb index 4fb3172af..844b086aa 100644 --- a/spec/models/message_spec.rb +++ b/spec/models/message_spec.rb @@ -54,8 +54,8 @@ describe Message, :type => :model do Diaspora::Federation::Dispatcher.build(@local_luke, @object_on_remote_parent).dispatch end - let(:build_object) { Message.new(:author => @alice.person, :text => "ohai!", :conversation => @conversation) } - it_should_behave_like 'it is relayable' + let(:relayable) { Message.new(author: @alice.person, text: "ohai!", conversation: @conversation) } + it_should_behave_like "it is relayable" describe '#increase_unread' do it 'increments the conversation visiblity for the conversation' do diff --git a/spec/models/participation_spec.rb b/spec/models/participation_spec.rb index 5c681185d..20f549364 100644 --- a/spec/models/participation_spec.rb +++ b/spec/models/participation_spec.rb @@ -16,9 +16,8 @@ describe Participation, :type => :model do @object_on_remote_parent = @local_luke.participate!(@remote_parent) end - let(:build_object) { Participation::Generator.new(alice, @status).build } - - it_should_behave_like 'it is relayable' + let(:relayable) { Participation::Generator.new(alice, @status).build } + it_should_behave_like "it is relayable" end describe "#unparticipate" do diff --git a/spec/models/poll_participation_spec.rb b/spec/models/poll_participation_spec.rb index 959c831aa..86a19f4b0 100644 --- a/spec/models/poll_participation_spec.rb +++ b/spec/models/poll_participation_spec.rb @@ -45,7 +45,7 @@ describe PollParticipation, :type => :model do @object_on_remote_parent = @local_luke.participate_in_poll!(@remote_parent, @remote_parent.poll.poll_answers.first) end - let(:build_object) { PollParticipation::Generator.new(alice, @status, @poll.poll_answers.first).build } - it_should_behave_like 'it is relayable' + let(:relayable) { PollParticipation::Generator.new(alice, @status, @poll.poll_answers.first).build } + it_should_behave_like "it is relayable" end end diff --git a/spec/shared_behaviors/receiving.rb b/spec/shared_behaviors/receiving.rb index 2637ff49e..36b69fd7d 100644 --- a/spec/shared_behaviors/receiving.rb +++ b/spec/shared_behaviors/receiving.rb @@ -14,3 +14,41 @@ shared_examples_for "it ignores existing object received twice" do |klass, metho Diaspora::Federation::Receive.public_send(method, entity) end end + +shared_examples_for "it rejects if the parent author ignores the author" do |klass, method| + it "saves the relayable if the author is not ignored" do + Diaspora::Federation::Receive.public_send(method, entity) + + expect(klass.find_by!(guid: entity.guid)).to be_instance_of(klass) + end + + context "if the author is ignored" do + before do + alice.blocks.create(person: sender) + end + + it "raises an error and does not save the relayable" do + expect { + Diaspora::Federation::Receive.public_send(method, entity) + }.to raise_error Diaspora::Federation::AuthorIgnored + + expect(klass.find_by(guid: entity.guid)).to be_nil + end + + it "it sends a retraction back to the author" do + dispatcher = double + expect(Diaspora::Federation::Dispatcher).to receive(:build) do |retraction_sender, retraction, opts| + expect(retraction_sender).to eq(alice) + expect(retraction.data[:target_guid]).to eq(entity.guid) + expect(retraction.data[:target_type]).to eq(klass.to_s) + expect(opts).to eq(subscribers: [sender]) + dispatcher + end + expect(dispatcher).to receive(:dispatch) + + expect { + Diaspora::Federation::Receive.public_send(method, entity) + }.to raise_error Diaspora::Federation::AuthorIgnored + end + end +end diff --git a/spec/shared_behaviors/relayable.rb b/spec/shared_behaviors/relayable.rb index 5a6400477..415c1d045 100644 --- a/spec/shared_behaviors/relayable.rb +++ b/spec/shared_behaviors/relayable.rb @@ -2,14 +2,12 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -require 'spec_helper' +require "spec_helper" shared_examples_for "it is relayable" do - - describe 'interacted_at' do - it 'sets the interacted at of the parent to the created at of the relayable post' do + describe "interacted_at" do + it "sets the interacted at of the parent to the created at of the relayable post" do Timecop.freeze Time.now do - relayable = build_object relayable.save if relayable.parent.respond_to?(:interacted_at) #I'm sorry. expect(relayable.parent.interacted_at.to_i).to eq(relayable.created_at.to_i) @@ -18,36 +16,28 @@ shared_examples_for "it is relayable" do end end - describe 'validations' do - describe 'on :author_id' do + describe "validations" do + context "author ignored by parent author" do context "the author is on the parent object author's ignore list when object is created" do before do - bob.blocks.create(:person => alice.person) - @relayable = build_object + bob.blocks.create(person: alice.person) end it "is invalid" do - expect(@relayable).not_to be_valid - expect(@relayable.errors[:author_id].size).to eq(1) - end - - it "sends a retraction for the object" do - skip 'need to figure out how to test this' - expect(Retraction).to receive(:for) - @relayable.valid? + expect(relayable).not_to be_valid + expect(relayable.errors[:author_id].size).to eq(1) 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 - @relayable.parent = nil - expect { @relayable.valid? }.to_not raise_exception + relayable.parent = nil + expect { relayable.valid? }.to_not raise_exception end end context "the author is added to the parent object author's ignore list later" do it "is valid" do - relayable = build_object relayable.save! - bob.blocks.create(:person => alice.person) + bob.blocks.create(person: alice.person) expect(relayable).to be_valid end end