From 812510b44afa644523fd486debd3874f1142a5ed Mon Sep 17 00:00:00 2001 From: Benjamin Neff Date: Sun, 3 Jan 2016 03:12:52 +0100 Subject: [PATCH] refactoring tests again closes #6595 --- .../federation/federation_helper.rb | 68 ++++++-- .../federation_messages_generation.rb | 164 ------------------ .../receive_federation_messages_spec.rb | 161 +++++++---------- .../federation/shared_receive_relayable.rb | 87 ++++++---- .../federation/shared_receive_retraction.rb | 55 +++--- .../federation/shared_receive_stream_items.rb | 138 +++++++-------- 6 files changed, 272 insertions(+), 401 deletions(-) delete mode 100644 spec/integration/federation/federation_messages_generation.rb diff --git a/spec/integration/federation/federation_helper.rb b/spec/integration/federation/federation_helper.rb index 6570f7c0a..dd3609b71 100644 --- a/spec/integration/federation/federation_helper.rb +++ b/spec/integration/federation/federation_helper.rb @@ -1,34 +1,68 @@ def remote_user_on_pod_b - @remote_on_b ||= FactoryGirl.build(:user).tap do |user| - user.person = FactoryGirl.create(:person, - profile: FactoryGirl.build(:profile), - serialized_public_key: user.encryption_key.public_key.export, - diaspora_handle: "#{user.username}@remote-b.net") - end + @remote_on_b ||= create_remote_user("remote-b.net") end def remote_user_on_pod_c - @remote_on_c ||= FactoryGirl.build(:user).tap do |user| + @remote_on_c ||= create_remote_user("remote-c.net") +end + +def create_remote_user(pod) + FactoryGirl.build(:user).tap do |user| user.person = FactoryGirl.create(:person, profile: FactoryGirl.build(:profile), serialized_public_key: user.encryption_key.public_key.export, - diaspora_handle: "#{user.username}@remote-c.net") + diaspora_handle: "#{user.username}@#{pod}") + allow(DiasporaFederation.callbacks).to receive(:trigger) + .with(:fetch_private_key_by_diaspora_id, user.diaspora_handle) { + user.encryption_key + } end end -def generate_xml(entity, remote_user, user) - if @public +def create_relayable_entity(entity_name, target, diaspora_id, parent_author_key) + target_entity_type = FactoryGirl.factory_by_name(entity_name).build_class.get_target_entity_type(@entity.to_h) + expect(DiasporaFederation.callbacks).to receive(:trigger) + .with( + :fetch_author_private_key_by_entity_guid, + target_entity_type, + target.guid + ) + .and_return(parent_author_key) + + FactoryGirl.build( + entity_name, + conversation_guid: target.guid, + parent_guid: target.guid, + diaspora_id: diaspora_id, + poll_answer_guid: target.respond_to?(:poll_answers) ? target.poll_answers.first.guid : nil + ) +end + +def generate_xml(entity, remote_user, recipient=nil) + if recipient + DiasporaFederation::Salmon::EncryptedSlap.generate_xml( + remote_user.diaspora_handle, + OpenSSL::PKey::RSA.new(remote_user.encryption_key), + entity, + OpenSSL::PKey::RSA.new(recipient.encryption_key) + ) + else DiasporaFederation::Salmon::Slap.generate_xml( remote_user.diaspora_handle, OpenSSL::PKey::RSA.new(remote_user.encryption_key), entity ) - else - DiasporaFederation::Salmon::EncryptedSlap.generate_xml( - remote_user.diaspora_handle, - OpenSSL::PKey::RSA.new(remote_user.encryption_key), - entity, - OpenSSL::PKey::RSA.new(user.encryption_key) - ) + end +end + +def post_message(xml, recipient=nil) + if recipient + inlined_jobs do + post "/receive/users/#{recipient.guid}", guid: recipient.guid, xml: xml + end + else + inlined_jobs do + post "/receive/public", xml: xml + end end end diff --git a/spec/integration/federation/federation_messages_generation.rb b/spec/integration/federation/federation_messages_generation.rb deleted file mode 100644 index 3e6b466db..000000000 --- a/spec/integration/federation/federation_messages_generation.rb +++ /dev/null @@ -1,164 +0,0 @@ -def generate_profile - @entity = FactoryGirl.build(:profile_entity, diaspora_id: remote_user_on_pod_b.person.diaspora_handle) - - generate_xml(@entity, remote_user_on_pod_b, alice) -end - -def generate_conversation - @entity = FactoryGirl.build( - :conversation_entity, - diaspora_id: remote_user_on_pod_b.diaspora_handle, - participant_ids: "#{remote_user_on_pod_b.diaspora_handle};#{alice.diaspora_handle}" - ) - - generate_xml(@entity, remote_user_on_pod_b, alice) -end - -def generate_status_message - @entity = FactoryGirl.build( - :status_message_entity, - diaspora_id: remote_user_on_pod_b.diaspora_handle, - public: @public - ) - - generate_xml(@entity, remote_user_on_pod_b, alice) -end - -def generate_forged_status_message - substitute_wrong_key(remote_user_on_pod_b, 1) - generate_status_message -end - -def generate_reshare - @entity = FactoryGirl.build( - :reshare_entity, - root_diaspora_id: alice.diaspora_handle, - root_guid: @local_target.guid, - diaspora_id: remote_user_on_pod_b.diaspora_handle, - public: true - ) - - generate_xml(@entity, remote_user_on_pod_b, alice) -end - -def mock_private_key_for_user(user) - expect(DiasporaFederation.callbacks).to receive(:trigger) - .with(:fetch_private_key_by_diaspora_id, user.person.diaspora_handle) - .and_return(user.encryption_key) -end - -def retraction_mock_callbacks(entity, sender) - return unless [ - DiasporaFederation::Entities::SignedRetraction, - DiasporaFederation::Entities::RelayableRetraction - ].include?(entity.class) - - mock_private_key_for_user(sender) - - allow(DiasporaFederation.callbacks).to receive(:trigger) - .with( - :fetch_entity_author_id_by_guid, - entity.target_type, - entity.target_guid - ) - .and_return(sender.encryption_key) -end - -def generate_retraction(entity_name, target_object, sender=remote_user_on_pod_b) - @entity = FactoryGirl.build( - entity_name, - diaspora_id: sender.diaspora_handle, - target_guid: target_object.guid, - target_type: target_object.class.to_s - ) - - retraction_mock_callbacks(@entity, sender) - - generate_xml(@entity, sender, alice) -end - -def generate_forged_retraction(entity_name, target_object, sender=remote_user_on_pod_b) - times = 1 - if %i(signed_retraction_entity relayable_retraction_entity).include?(entity_name) - times += 2 - end - - substitute_wrong_key(sender, times) - generate_retraction(entity_name, target_object, sender) -end - -def generate_relayable_entity(entity_name, target, diaspora_id) - @entity = FactoryGirl.build( - entity_name, - conversation_guid: target.guid, - parent_guid: target.guid, - diaspora_id: diaspora_id, - poll_answer_guid: target.respond_to?(:poll_answers) ? target.poll_answers.first.guid : nil - ) -end - -def mock_entity_author_private_key_unavailable(klass) - expect(DiasporaFederation.callbacks).to receive(:trigger) - .with( - :fetch_author_private_key_by_entity_guid, - klass.get_target_entity_type(@entity.to_h), - kind_of(String) - ) - .and_return(nil) -end - -def mock_entity_author_private_key_as(klass, key) - expect(DiasporaFederation.callbacks).to receive(:trigger) - .with( - :fetch_author_private_key_by_entity_guid, - klass.get_target_entity_type(@entity.to_h), - @remote_target.guid - ) - .and_return(key) -end - -def generate_relayable_local_parent(entity_name) - klass = FactoryGirl.factory_by_name(entity_name).build_class - generate_relayable_entity(entity_name, @local_target, remote_user_on_pod_b.person.diaspora_handle) - - mock_private_key_for_user(remote_user_on_pod_b) - mock_entity_author_private_key_unavailable(klass) - - generate_xml(@entity, remote_user_on_pod_b, alice) -end - -def generate_relayable_remote_parent(entity_name) - klass = FactoryGirl.factory_by_name(entity_name).build_class - generate_relayable_entity(entity_name, @remote_target, remote_user_on_pod_c.person.diaspora_handle) - - mock_private_key_for_user(remote_user_on_pod_c) - mock_entity_author_private_key_as(klass, remote_user_on_pod_b.encryption_key) - - generate_xml(@entity, remote_user_on_pod_b, alice) -end - -def substitute_wrong_key(user, times_number) - expect(user).to receive(:encryption_key).exactly(times_number).times.and_return( - OpenSSL::PKey::RSA.new(1024) - ) -end - -# Checks when a remote pod wants to send us a relayable without having a key for declared diaspora ID -def generate_relayable_local_parent_wrong_author_key(entity_name) - substitute_wrong_key(remote_user_on_pod_b, 2) - generate_relayable_local_parent(entity_name) -end - -# Checks when a remote pod B wants to send us a relayable with authorship from a remote pod C user -# without having correct signature from him. -def generate_relayable_remote_parent_wrong_author_key(entity_name) - substitute_wrong_key(remote_user_on_pod_c, 1) - generate_relayable_remote_parent(entity_name) -end - -# Checks when a remote pod C wants to send us a relayable from its user, but bypassing the pod B where -# remote status came from. -def generate_relayable_remote_parent_wrong_parent_key(entity_name) - substitute_wrong_key(remote_user_on_pod_b, 2) - generate_relayable_remote_parent(entity_name) -end diff --git a/spec/integration/federation/receive_federation_messages_spec.rb b/spec/integration/federation/receive_federation_messages_spec.rb index b3697a3ac..ab114e8e7 100644 --- a/spec/integration/federation/receive_federation_messages_spec.rb +++ b/spec/integration/federation/receive_federation_messages_spec.rb @@ -1,101 +1,64 @@ require "spec_helper" -require "diaspora_federation/test" require "integration/federation/federation_helper" -require "integration/federation/federation_messages_generation" require "integration/federation/shared_receive_relayable" require "integration/federation/shared_receive_retraction" require "integration/federation/shared_receive_stream_items" -def post_private_message(recipient_guid, xml) - inlined_jobs do - post "/receive/users/#{recipient_guid}", guid: recipient_guid, xml: xml - end -end - -def post_public_message(xml) - inlined_jobs do - post "/receive/public", xml: xml - end -end - -def post_message(recipient_guid, xml) - if @public - post_public_message(xml) - else - post_private_message(recipient_guid, xml) - end -end - -def set_up_sharing - contact = alice.contacts.find_or_initialize_by(person_id: remote_user_on_pod_b.person.id) - contact.sharing = true - contact.save -end - describe "Receive federation messages feature" do before do allow(DiasporaFederation.callbacks).to receive(:trigger) .with(:queue_public_receive, any_args).and_call_original allow(DiasporaFederation.callbacks).to receive(:trigger) .with(:queue_private_receive, any_args).and_call_original - allow(DiasporaFederation.callbacks).to receive(:trigger) - .with(:save_person_after_webfinger, any_args).and_call_original end + let(:sender) { remote_user_on_pod_b } + let(:sender_id) { remote_user_on_pod_b.diaspora_handle } + context "with public receive" do - before do - @public = true - end + let(:recipient) { nil } it "receives account deletion correctly" do - post_public_message( - generate_xml( - DiasporaFederation::Entities::AccountDeletion.new(diaspora_id: remote_user_on_pod_b.diaspora_handle), - remote_user_on_pod_b, - nil - ) - ) + post_message(generate_xml(DiasporaFederation::Entities::AccountDeletion.new(diaspora_id: sender_id), sender)) - expect(AccountDeletion.where(diaspora_handle: remote_user_on_pod_b.diaspora_handle).exists?).to be(true) + expect(AccountDeletion.exists?(diaspora_handle: sender_id)).to be_truthy end it "rejects account deletion with wrong diaspora_id" do delete_id = FactoryGirl.generate(:diaspora_id) - post_public_message( - generate_xml( - DiasporaFederation::Entities::AccountDeletion.new(diaspora_id: delete_id), - remote_user_on_pod_b, - nil - ) - ) + post_message(generate_xml(DiasporaFederation::Entities::AccountDeletion.new(diaspora_id: delete_id), sender)) - expect(AccountDeletion.where(diaspora_handle: delete_id).exists?).to be(false) - expect(AccountDeletion.where(diaspora_handle: remote_user_on_pod_b.diaspora_handle).exists?).to be(false) + expect(AccountDeletion.exists?(diaspora_handle: delete_id)).to be_falsey + expect(AccountDeletion.exists?(diaspora_handle: sender_id)).to be_falsey end - it "reshare of public post passes" do - @local_target = FactoryGirl.create(:status_message, author: alice.person, public: true) - post_public_message(generate_reshare) + context "reshare" do + it "reshare of public post passes" do + post = FactoryGirl.create(:status_message, author: alice.person, public: true) + reshare = FactoryGirl.build( + :reshare_entity, root_diaspora_id: alice.diaspora_handle, root_guid: post.guid, diaspora_id: sender_id) + post_message(generate_xml(reshare, sender)) - expect( - Reshare.where(root_guid: @local_target.guid, diaspora_handle: remote_user_on_pod_b.diaspora_handle).first - ).not_to be_nil - end + expect(Reshare.exists?(root_guid: post.guid, diaspora_handle: sender_id)).to be_truthy + end - it "reshare of private post fails" do - @local_target = FactoryGirl.create(:status_message, author: alice.person, public: false) - post_public_message(generate_reshare) + it "reshare of private post fails" do + post = FactoryGirl.create(:status_message, author: alice.person, public: false) + reshare = FactoryGirl.build( + :reshare_entity, root_diaspora_id: alice.diaspora_handle, root_guid: post.guid, diaspora_id: sender_id) + post_message(generate_xml(reshare, sender)) - expect( - Reshare.where(root_guid: @local_target.guid, diaspora_handle: remote_user_on_pod_b.diaspora_handle).first - ).to be_nil + expect(Reshare.exists?(root_guid: post.guid, diaspora_handle: sender_id)).to be_falsey + end end it_behaves_like "messages which are indifferent about sharing fact" context "with sharing" do before do - set_up_sharing + contact = alice.contacts.find_or_initialize_by(person_id: sender.person.id) + contact.sharing = true + contact.save end it_behaves_like "messages which are indifferent about sharing fact" @@ -104,74 +67,84 @@ describe "Receive federation messages feature" do end context "with private receive" do - before do - @public = false - end + let(:recipient) { alice } it "treats sharing request recive correctly" do entity = FactoryGirl.build(:request_entity, recipient_id: alice.diaspora_handle) expect(Diaspora::Fetcher::Public).to receive(:queue_for).exactly(1).times - post_private_message(alice.guid, generate_xml(entity, remote_user_on_pod_b, alice)) + post_message(generate_xml(entity, sender, alice), alice) expect(alice.contacts.count).to eq(2) new_contact = alice.contacts.order(created_at: :asc).last expect(new_contact).not_to be_nil expect(new_contact.sharing).to eq(true) - expect(new_contact.person.diaspora_handle).to eq(remote_user_on_pod_b.diaspora_handle) + expect(new_contact.person.diaspora_handle).to eq(sender_id) expect( - Notifications::StartedSharing.where( + Notifications::StartedSharing.exists?( recipient_id: alice.id, target_type: "Person", - target_id: remote_user_on_pod_b.person.id - ).first - ).not_to be_nil + target_id: sender.person.id + ) + ).to be_truthy end it "doesn't save the private status message if there is no sharing" do - post_private_message(alice.guid, generate_status_message) + entity = FactoryGirl.build(:status_message_entity, diaspora_id: sender_id, public: false) + post_message(generate_xml(entity, sender, alice), alice) - expect(StatusMessage.exists?(guid: @entity.guid)).to be(false) + expect(StatusMessage.exists?(guid: entity.guid)).to be_falsey end context "with sharing" do before do - set_up_sharing + contact = alice.contacts.find_or_initialize_by(person_id: sender.person.id) + contact.sharing = true + contact.save end it_behaves_like "messages which are indifferent about sharing fact" it_behaves_like "messages which can't be send without sharing" it "treats profile receive correctly" do - post_private_message(alice.guid, generate_profile) + entity = FactoryGirl.build(:profile_entity, diaspora_id: sender_id) + post_message(generate_xml(entity, sender, alice), alice) - expect(Profile.where(diaspora_handle: @entity.diaspora_id).exists?).to be(true) + expect(Profile.exists?(diaspora_handle: entity.diaspora_id)).to be_truthy end it "receives conversation correctly" do - post_private_message(alice.guid, generate_conversation) + entity = FactoryGirl.build( + :conversation_entity, + diaspora_id: sender_id, + participant_ids: "#{sender_id};#{alice.diaspora_handle}" + ) + post_message(generate_xml(entity, sender, alice), alice) - expect(Conversation.exists?(guid: @entity.guid)).to be(true) + expect(Conversation.exists?(guid: entity.guid)).to be_truthy end context "with message" do - before do - @local_target = FactoryGirl.build(:conversation, author: alice.person) - @local_target.participants << remote_user_on_pod_b.person - @local_target.participants << remote_user_on_pod_c.person - @local_target.save - @remote_target = FactoryGirl.build(:conversation, author: remote_user_on_pod_b.person) - @remote_target.participants << alice.person - @remote_target.participants << remote_user_on_pod_c.person - @remote_target.save - end + let(:local_target) { + FactoryGirl.build(:conversation, author: alice.person).tap do |target| + target.participants << remote_user_on_pod_b.person + target.participants << remote_user_on_pod_c.person + target.save + end + } + let(:remote_target) { + FactoryGirl.build(:conversation, author: remote_user_on_pod_b.person).tap do |target| + target.participants << alice.person + target.participants << remote_user_on_pod_c.person + target.save + end + } + let(:entity_name) { :message_entity } + let(:klass) { Message } - it_behaves_like "it deals correctly with a relayable" do - let(:entity_name) { :message_entity } - let(:klass) { Message } - end + it_behaves_like "it deals correctly with a relayable" end end end diff --git a/spec/integration/federation/shared_receive_relayable.rb b/spec/integration/federation/shared_receive_relayable.rb index 7a8f25fa9..71c675743 100644 --- a/spec/integration/federation/shared_receive_relayable.rb +++ b/spec/integration/federation/shared_receive_relayable.rb @@ -1,44 +1,59 @@ shared_examples_for "it deals correctly with a relayable" do - it "treats upstream receive correctly" do - expect(Postzord::Dispatcher).to receive(:build).with(alice, kind_of(klass)).and_call_original - post_message(alice.guid, generate_relayable_local_parent(entity_name)) - received_entity = klass.find_by(guid: @entity.guid) - expect(received_entity).not_to be_nil - expect(received_entity.author.diaspora_handle).to eq(remote_user_on_pod_b.person.diaspora_handle) + context "local" do + let(:entity) { create_relayable_entity(entity_name, local_target, sender_id, nil) } + + it "treats upstream receive correctly" do + expect(Postzord::Dispatcher).to receive(:build).with(alice, kind_of(klass)).and_call_original + post_message(generate_xml(entity, sender, recipient), recipient) + + received_entity = klass.find_by(guid: entity.guid) + expect(received_entity).not_to be_nil + expect(received_entity.author.diaspora_handle).to eq(remote_user_on_pod_b.diaspora_handle) + end + + # Checks when a remote pod wants to send us a relayable without having a key for declared diaspora ID + it "rejects an upstream entity with a malformed author signature" do + expect(Postzord::Dispatcher).not_to receive(:build) + allow(remote_user_on_pod_b).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024)) + post_message(generate_xml(entity, sender, recipient), recipient) + + expect(klass.exists?(guid: entity.guid)).to be_falsey + end end - it "rejects an upstream entity with a malformed author signature" do - expect(Postzord::Dispatcher).not_to receive(:build) - post_message( - alice.guid, - generate_relayable_local_parent_wrong_author_key(entity_name) - ) - expect(klass.exists?(guid: @entity.guid)).to be(false) - end + context "remote" do + let(:author_id) { remote_user_on_pod_c.diaspora_handle } + let(:entity) { create_relayable_entity(entity_name, remote_target, author_id, sender.encryption_key) } - it "treats downstream receive correctly" do - expect(Postzord::Dispatcher).to receive(:build).with(alice, kind_of(klass)).and_call_original unless @public - post_message(alice.guid, generate_relayable_remote_parent(entity_name)) - received_entity = klass.find_by(guid: @entity.guid) - expect(received_entity).not_to be_nil - expect(received_entity.author.diaspora_handle).to eq(remote_user_on_pod_c.person.diaspora_handle) - end + it "treats downstream receive correctly" do + expect(Postzord::Dispatcher).to receive(:build) + .with(alice, kind_of(klass)).and_call_original unless recipient.nil? - it "rejects a downstream entity with a malformed author signature" do - expect(Postzord::Dispatcher).not_to receive(:build) - post_message( - alice.guid, - generate_relayable_remote_parent_wrong_author_key(entity_name) - ) - expect(klass.exists?(guid: @entity.guid)).to be(false) - end + post_message(generate_xml(entity, sender, recipient), recipient) - it "declines downstream receive when sender signed with a wrong key" do - expect(Postzord::Dispatcher).not_to receive(:build) - post_message( - alice.guid, - generate_relayable_remote_parent_wrong_parent_key(entity_name) - ) - expect(klass.exists?(guid: @entity.guid)).to be(false) + received_entity = klass.find_by(guid: entity.guid) + expect(received_entity).not_to be_nil + expect(received_entity.author.diaspora_handle).to eq(remote_user_on_pod_c.diaspora_handle) + end + + # Checks when a remote pod B wants to send us a relayable with authorship from a remote pod C user + # without having correct signature from him. + it "rejects a downstream entity with a malformed author signature" do + expect(Postzord::Dispatcher).not_to receive(:build) + allow(remote_user_on_pod_c).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024)) + post_message(generate_xml(entity, sender, recipient), recipient) + + expect(klass.exists?(guid: entity.guid)).to be_falsey + end + + # Checks when a remote pod C wants to send us a relayable from its user, but bypassing the pod B where + # remote status came from. + it "declines downstream receive when sender signed with a wrong key" do + expect(Postzord::Dispatcher).not_to receive(:build) + allow(sender).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024)) + post_message(generate_xml(entity, sender, recipient), recipient) + + expect(klass.exists?(guid: entity.guid)).to be_falsey + end end end diff --git a/spec/integration/federation/shared_receive_retraction.rb b/spec/integration/federation/shared_receive_retraction.rb index 71ae13905..c9182e539 100644 --- a/spec/integration/federation/shared_receive_retraction.rb +++ b/spec/integration/federation/shared_receive_retraction.rb @@ -1,44 +1,57 @@ +def retraction_entity(entity_name, target_object, sender) + allow(DiasporaFederation.callbacks).to receive(:trigger) + .with( + :fetch_entity_author_id_by_guid, + target_object.class.to_s, + target_object.guid + ) + .and_return(sender.encryption_key) + + FactoryGirl.build( + entity_name, + diaspora_id: sender.diaspora_handle, + target_guid: target_object.guid, + target_type: target_object.class.to_s + ) +end + shared_examples_for "it retracts non-relayable object" do it "retracts object by a correct retraction message" do - target_klass = target_object.class.to_s.constantize - post_message(alice.guid, generate_retraction(entity_name, target_object)) + entity = retraction_entity(entity_name, target_object, sender) + post_message(generate_xml(entity, sender, recipient), recipient) - expect(target_klass.exists?(guid: target_object.guid)).to be(false) + expect(target_object.class.exists?(guid: target_object.guid)).to be_falsey end it "doesn't retract object when retraction has wrong signatures" do - target_klass = target_object.class.to_s.constantize - post_message(alice.guid, generate_forged_retraction(entity_name, target_object)) + allow(sender).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024)) + entity = retraction_entity(entity_name, target_object, sender) + post_message(generate_xml(entity, sender, recipient), recipient) - expect(target_klass.exists?(guid: target_object.guid)).to be(true) + expect(target_object.class.exists?(guid: target_object.guid)).to be_truthy end it "doesn't retract object when sender is different from target object" do - target_klass = target_object.class.to_s.constantize - post_message( - alice.guid, - generate_retraction(entity_name, target_object, remote_user_on_pod_c) - ) + entity = retraction_entity(entity_name, target_object, remote_user_on_pod_c) + post_message(generate_xml(entity, remote_user_on_pod_c, recipient), recipient) - expect(target_klass.exists?(guid: target_object.guid)).to be(true) + expect(target_object.class.exists?(guid: target_object.guid)).to be_truthy end end shared_examples_for "it retracts relayable object" do it "retracts object by a correct message" do - target_klass = target_object.class.to_s.constantize - post_message(alice.guid, generate_retraction(entity_name, target_object, sender)) + entity = retraction_entity(entity_name, target_object, sender) + post_message(generate_xml(entity, sender, recipient), recipient) - expect(target_klass.exists?(guid: target_object.guid)).to be(false) + expect(target_object.class.exists?(guid: target_object.guid)).to be_falsey end it "doesn't retract object when retraction has wrong signatures" do - target_klass = target_object.class.to_s.constantize - post_message( - alice.guid, - generate_forged_retraction(entity_name, target_object, sender) - ) + allow(sender).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024)) + entity = retraction_entity(entity_name, target_object, sender) + post_message(generate_xml(entity, sender, recipient), recipient) - expect(target_klass.exists?(guid: target_object.guid)).to be(true) + expect(target_object.class.exists?(guid: target_object.guid)).to be_truthy end end diff --git a/spec/integration/federation/shared_receive_stream_items.rb b/spec/integration/federation/shared_receive_stream_items.rb index 109488bcc..93e876481 100644 --- a/spec/integration/federation/shared_receive_stream_items.rb +++ b/spec/integration/federation/shared_receive_stream_items.rb @@ -1,73 +1,83 @@ # by "stream items" we mean everything that could appear in the stream - post, comment, like, poll, etc and therefore # could be send either publicly or privately -def set_up_messages - @local_target = FactoryGirl.create(:status_message, author: alice.person, public: @public) - @remote_target = FactoryGirl.create(:status_message, author: remote_user_on_pod_b.person, public: @public) -end - shared_examples_for "messages which are indifferent about sharing fact" do - it "treats status message receive correctly" do - post_message(alice.guid, generate_status_message) + let(:public) { recipient.nil? } - expect(StatusMessage.exists?(guid: @entity.guid)).to be(true) + it "treats status message receive correctly" do + entity = FactoryGirl.build(:status_message_entity, diaspora_id: sender_id, public: public) + + post_message(generate_xml(entity, sender, recipient), recipient) + + expect(StatusMessage.exists?(guid: entity.guid)).to be_truthy end it "doesn't accept status message with wrong signature" do - post_message(alice.guid, generate_forged_status_message) + allow(sender).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024)) + entity = FactoryGirl.build(:status_message_entity, diaspora_id: sender_id, public: public) - expect(StatusMessage.exists?(guid: @entity.guid)).to be(false) + post_message(generate_xml(entity, sender, recipient), recipient) + + expect(StatusMessage.exists?(guid: entity.guid)).to be_falsey end describe "with messages which require a status to operate on" do - before do - set_up_messages - end + let(:local_target) { FactoryGirl.create(:status_message, author: alice.person, public: public) } + let(:remote_target) { FactoryGirl.create(:status_message, author: remote_user_on_pod_b.person, public: public) } describe "notifications are sent where required" do it "for comment on local post" do - post_message(alice.guid, generate_relayable_local_parent(:comment_entity)) + entity = create_relayable_entity(:comment_entity, local_target, remote_user_on_pod_b.diaspora_handle, nil) + post_message(generate_xml(entity, sender, recipient), recipient) expect( - Notifications::CommentOnPost.where( + Notifications::CommentOnPost.exists?( recipient_id: alice.id, target_type: "Post", - target_id: @local_target.id - ).first - ).not_to be_nil + target_id: local_target.id + ) + ).to be_truthy end it "for like on local post" do - post_message(alice.guid, generate_relayable_local_parent(:like_entity)) + entity = create_relayable_entity(:like_entity, local_target, remote_user_on_pod_b.diaspora_handle, nil) + post_message(generate_xml(entity, sender, recipient), recipient) expect( - Notifications::Liked.where( + Notifications::Liked.exists?( recipient_id: alice.id, target_type: "Post", - target_id: @local_target.id - ).first - ).not_to be_nil + target_id: local_target.id + ) + ).to be_truthy end end %w(comment like participation).each do |entity| context "with #{entity}" do - it_behaves_like "it deals correctly with a relayable" do - let(:entity_name) { "#{entity}_entity".to_sym } - let(:klass) { entity.camelize.constantize } - end + let(:entity_name) { "#{entity}_entity".to_sym } + let(:klass) { entity.camelize.constantize } + + it_behaves_like "it deals correctly with a relayable" end end context "with poll_participation" do - before do - @local_target = FactoryGirl.create(:poll, status_message: @local_target) - @remote_target = FactoryGirl.create(:poll, status_message: @remote_target) - end + let(:local_target) { + FactoryGirl.create( + :poll, + status_message: FactoryGirl.create(:status_message, author: alice.person, public: public) + ) + } + let(:remote_target) { + FactoryGirl.create( + :poll, + status_message: FactoryGirl.create(:status_message, author: remote_user_on_pod_b.person, public: public) + ) + } + let(:entity_name) { :poll_participation_entity } + let(:klass) { PollParticipation } - it_behaves_like "it deals correctly with a relayable" do - let(:entity_name) { :poll_participation_entity } - let(:klass) { PollParticipation } - end + it_behaves_like "it deals correctly with a relayable" end end end @@ -75,17 +85,15 @@ end shared_examples_for "messages which can't be send without sharing" do # retractions shouldn't depend on sharing fact describe "retractions for non-relayable objects" do - %w( - retraction - signed_retraction - ).each do |retraction_entity_name| + %w(retraction signed_retraction).each do |retraction_entity_name| context "with #{retraction_entity_name}" do + let(:entity_name) { "#{retraction_entity_name}_entity".to_sym } + %w(status_message photo).each do |target| context "with #{target}" do - it_behaves_like "it retracts non-relayable object" do - let(:target_object) { FactoryGirl.create(target.to_sym, author: remote_user_on_pod_b.person) } - let(:entity_name) { "#{retraction_entity_name}_entity".to_sym } - end + let(:target_object) { FactoryGirl.create(target.to_sym, author: remote_user_on_pod_b.person) } + + it_behaves_like "it retracts non-relayable object" end end end @@ -93,70 +101,62 @@ shared_examples_for "messages which can't be send without sharing" do end describe "with messages which require a status to operate on" do - before do - set_up_messages - end + let(:public) { recipient.nil? } + let(:local_target) { FactoryGirl.create(:status_message, author: alice.person, public: public) } + let(:remote_target) { FactoryGirl.create(:status_message, author: remote_user_on_pod_b.person, public: public) } # this one shouldn't depend on the sharing fact. this must be fixed describe "notifications are sent where required" do it "for comment on remote post where we participate" do - alice.participate!(@remote_target) - post_message(alice.guid, generate_relayable_remote_parent(:comment_entity)) + alice.participate!(remote_target) + author_id = remote_user_on_pod_c.diaspora_handle + entity = create_relayable_entity(:comment_entity, remote_target, author_id, sender.encryption_key) + post_message(generate_xml(entity, sender, recipient), recipient) expect( - Notifications::AlsoCommented.where( + Notifications::AlsoCommented.exists?( recipient_id: alice.id, target_type: "Post", - target_id: @remote_target.id - ).first - ).not_to be_nil + target_id: remote_target.id + ) + ).to be_truthy end end describe "retractions for relayable objects" do - %w( - retraction - signed_retraction - relayable_retraction - ).each do |retraction_entity_name| + %w(retraction signed_retraction relayable_retraction).each do |retraction_entity_name| context "with #{retraction_entity_name}" do + let(:entity_name) { "#{retraction_entity_name}_entity".to_sym } + context "with comment" do it_behaves_like "it retracts relayable object" do # case for to-upstream federation - let(:entity_name) { "#{retraction_entity_name}_entity".to_sym } let(:target_object) { - FactoryGirl.create(:comment, author: remote_user_on_pod_b.person, post: @local_target) + FactoryGirl.create(:comment, author: remote_user_on_pod_b.person, post: local_target) } - let(:sender) { remote_user_on_pod_b } end it_behaves_like "it retracts relayable object" do # case for to-downsteam federation let(:target_object) { - FactoryGirl.create(:comment, author: remote_user_on_pod_c.person, post: @remote_target) + FactoryGirl.create(:comment, author: remote_user_on_pod_c.person, post: remote_target) } - let(:entity_name) { "#{retraction_entity_name}_entity".to_sym } - let(:sender) { remote_user_on_pod_b } end end context "with like" do it_behaves_like "it retracts relayable object" do # case for to-upstream federation - let(:entity_name) { "#{retraction_entity_name}_entity".to_sym } let(:target_object) { - FactoryGirl.create(:like, author: remote_user_on_pod_b.person, target: @local_target) + FactoryGirl.create(:like, author: remote_user_on_pod_b.person, target: local_target) } - let(:sender) { remote_user_on_pod_b } end it_behaves_like "it retracts relayable object" do # case for to-downsteam federation let(:target_object) { - FactoryGirl.create(:like, author: remote_user_on_pod_c.person, target: @remote_target) + FactoryGirl.create(:like, author: remote_user_on_pod_c.person, target: remote_target) } - let(:entity_name) { "#{retraction_entity_name}_entity".to_sym } - let(:sender) { remote_user_on_pod_b } end end end