refactoring tests again

closes #6595
This commit is contained in:
Benjamin Neff 2016-01-03 03:12:52 +01:00 committed by Dennis Schubert
parent b6c7f004e4
commit 812510b44a
6 changed files with 272 additions and 401 deletions

View file

@ -1,34 +1,68 @@
def remote_user_on_pod_b def remote_user_on_pod_b
@remote_on_b ||= FactoryGirl.build(:user).tap do |user| @remote_on_b ||= create_remote_user("remote-b.net")
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
end end
def remote_user_on_pod_c 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, user.person = FactoryGirl.create(:person,
profile: FactoryGirl.build(:profile), profile: FactoryGirl.build(:profile),
serialized_public_key: user.encryption_key.public_key.export, 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
end end
def generate_xml(entity, remote_user, user) def create_relayable_entity(entity_name, target, diaspora_id, parent_author_key)
if @public 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( DiasporaFederation::Salmon::Slap.generate_xml(
remote_user.diaspora_handle, remote_user.diaspora_handle,
OpenSSL::PKey::RSA.new(remote_user.encryption_key), OpenSSL::PKey::RSA.new(remote_user.encryption_key),
entity entity
) )
else end
DiasporaFederation::Salmon::EncryptedSlap.generate_xml( end
remote_user.diaspora_handle,
OpenSSL::PKey::RSA.new(remote_user.encryption_key), def post_message(xml, recipient=nil)
entity, if recipient
OpenSSL::PKey::RSA.new(user.encryption_key) 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
end end

View file

@ -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

View file

@ -1,101 +1,64 @@
require "spec_helper" require "spec_helper"
require "diaspora_federation/test"
require "integration/federation/federation_helper" require "integration/federation/federation_helper"
require "integration/federation/federation_messages_generation"
require "integration/federation/shared_receive_relayable" require "integration/federation/shared_receive_relayable"
require "integration/federation/shared_receive_retraction" require "integration/federation/shared_receive_retraction"
require "integration/federation/shared_receive_stream_items" 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 describe "Receive federation messages feature" do
before do before do
allow(DiasporaFederation.callbacks).to receive(:trigger) allow(DiasporaFederation.callbacks).to receive(:trigger)
.with(:queue_public_receive, any_args).and_call_original .with(:queue_public_receive, any_args).and_call_original
allow(DiasporaFederation.callbacks).to receive(:trigger) allow(DiasporaFederation.callbacks).to receive(:trigger)
.with(:queue_private_receive, any_args).and_call_original .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 end
let(:sender) { remote_user_on_pod_b }
let(:sender_id) { remote_user_on_pod_b.diaspora_handle }
context "with public receive" do context "with public receive" do
before do let(:recipient) { nil }
@public = true
end
it "receives account deletion correctly" do it "receives account deletion correctly" do
post_public_message( post_message(generate_xml(DiasporaFederation::Entities::AccountDeletion.new(diaspora_id: sender_id), sender))
generate_xml(
DiasporaFederation::Entities::AccountDeletion.new(diaspora_id: remote_user_on_pod_b.diaspora_handle),
remote_user_on_pod_b,
nil
)
)
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 end
it "rejects account deletion with wrong diaspora_id" do it "rejects account deletion with wrong diaspora_id" do
delete_id = FactoryGirl.generate(:diaspora_id) delete_id = FactoryGirl.generate(:diaspora_id)
post_public_message( post_message(generate_xml(DiasporaFederation::Entities::AccountDeletion.new(diaspora_id: delete_id), sender))
generate_xml(
DiasporaFederation::Entities::AccountDeletion.new(diaspora_id: delete_id),
remote_user_on_pod_b,
nil
)
)
expect(AccountDeletion.where(diaspora_handle: delete_id).exists?).to be(false) expect(AccountDeletion.exists?(diaspora_handle: delete_id)).to be_falsey
expect(AccountDeletion.where(diaspora_handle: remote_user_on_pod_b.diaspora_handle).exists?).to be(false) expect(AccountDeletion.exists?(diaspora_handle: sender_id)).to be_falsey
end end
it "reshare of public post passes" do context "reshare" do
@local_target = FactoryGirl.create(:status_message, author: alice.person, public: true) it "reshare of public post passes" do
post_public_message(generate_reshare) 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( expect(Reshare.exists?(root_guid: post.guid, diaspora_handle: sender_id)).to be_truthy
Reshare.where(root_guid: @local_target.guid, diaspora_handle: remote_user_on_pod_b.diaspora_handle).first end
).not_to be_nil
end
it "reshare of private post fails" do it "reshare of private post fails" do
@local_target = FactoryGirl.create(:status_message, author: alice.person, public: false) post = FactoryGirl.create(:status_message, author: alice.person, public: false)
post_public_message(generate_reshare) 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( expect(Reshare.exists?(root_guid: post.guid, diaspora_handle: sender_id)).to be_falsey
Reshare.where(root_guid: @local_target.guid, diaspora_handle: remote_user_on_pod_b.diaspora_handle).first end
).to be_nil
end end
it_behaves_like "messages which are indifferent about sharing fact" it_behaves_like "messages which are indifferent about sharing fact"
context "with sharing" do context "with sharing" do
before do before do
set_up_sharing contact = alice.contacts.find_or_initialize_by(person_id: sender.person.id)
contact.sharing = true
contact.save
end end
it_behaves_like "messages which are indifferent about sharing fact" it_behaves_like "messages which are indifferent about sharing fact"
@ -104,74 +67,84 @@ describe "Receive federation messages feature" do
end end
context "with private receive" do context "with private receive" do
before do let(:recipient) { alice }
@public = false
end
it "treats sharing request recive correctly" do it "treats sharing request recive correctly" do
entity = FactoryGirl.build(:request_entity, recipient_id: alice.diaspora_handle) entity = FactoryGirl.build(:request_entity, recipient_id: alice.diaspora_handle)
expect(Diaspora::Fetcher::Public).to receive(:queue_for).exactly(1).times 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) expect(alice.contacts.count).to eq(2)
new_contact = alice.contacts.order(created_at: :asc).last new_contact = alice.contacts.order(created_at: :asc).last
expect(new_contact).not_to be_nil expect(new_contact).not_to be_nil
expect(new_contact.sharing).to eq(true) 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( expect(
Notifications::StartedSharing.where( Notifications::StartedSharing.exists?(
recipient_id: alice.id, recipient_id: alice.id,
target_type: "Person", target_type: "Person",
target_id: remote_user_on_pod_b.person.id target_id: sender.person.id
).first )
).not_to be_nil ).to be_truthy
end end
it "doesn't save the private status message if there is no sharing" do 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 end
context "with sharing" do context "with sharing" do
before do before do
set_up_sharing contact = alice.contacts.find_or_initialize_by(person_id: sender.person.id)
contact.sharing = true
contact.save
end end
it_behaves_like "messages which are indifferent about sharing fact" it_behaves_like "messages which are indifferent about sharing fact"
it_behaves_like "messages which can't be send without sharing" it_behaves_like "messages which can't be send without sharing"
it "treats profile receive correctly" do 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 end
it "receives conversation correctly" do 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 end
context "with message" do context "with message" do
before do let(:local_target) {
@local_target = FactoryGirl.build(:conversation, author: alice.person) FactoryGirl.build(:conversation, author: alice.person).tap do |target|
@local_target.participants << remote_user_on_pod_b.person target.participants << remote_user_on_pod_b.person
@local_target.participants << remote_user_on_pod_c.person target.participants << remote_user_on_pod_c.person
@local_target.save target.save
@remote_target = FactoryGirl.build(:conversation, author: remote_user_on_pod_b.person) end
@remote_target.participants << alice.person }
@remote_target.participants << remote_user_on_pod_c.person let(:remote_target) {
@remote_target.save FactoryGirl.build(:conversation, author: remote_user_on_pod_b.person).tap do |target|
end 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 it_behaves_like "it deals correctly with a relayable"
let(:entity_name) { :message_entity }
let(:klass) { Message }
end
end end
end end
end end

View file

@ -1,44 +1,59 @@
shared_examples_for "it deals correctly with a relayable" do shared_examples_for "it deals correctly with a relayable" do
it "treats upstream receive correctly" do context "local" do
expect(Postzord::Dispatcher).to receive(:build).with(alice, kind_of(klass)).and_call_original let(:entity) { create_relayable_entity(entity_name, local_target, sender_id, nil) }
post_message(alice.guid, generate_relayable_local_parent(entity_name))
received_entity = klass.find_by(guid: @entity.guid) it "treats upstream receive correctly" do
expect(received_entity).not_to be_nil expect(Postzord::Dispatcher).to receive(:build).with(alice, kind_of(klass)).and_call_original
expect(received_entity.author.diaspora_handle).to eq(remote_user_on_pod_b.person.diaspora_handle) 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 end
it "rejects an upstream entity with a malformed author signature" do context "remote" do
expect(Postzord::Dispatcher).not_to receive(:build) let(:author_id) { remote_user_on_pod_c.diaspora_handle }
post_message( let(:entity) { create_relayable_entity(entity_name, remote_target, author_id, sender.encryption_key) }
alice.guid,
generate_relayable_local_parent_wrong_author_key(entity_name)
)
expect(klass.exists?(guid: @entity.guid)).to be(false)
end
it "treats downstream receive correctly" do it "treats downstream receive correctly" do
expect(Postzord::Dispatcher).to receive(:build).with(alice, kind_of(klass)).and_call_original unless @public expect(Postzord::Dispatcher).to receive(:build)
post_message(alice.guid, generate_relayable_remote_parent(entity_name)) .with(alice, kind_of(klass)).and_call_original unless recipient.nil?
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 "rejects a downstream entity with a malformed author signature" do post_message(generate_xml(entity, sender, recipient), recipient)
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
it "declines downstream receive when sender signed with a wrong key" do received_entity = klass.find_by(guid: entity.guid)
expect(Postzord::Dispatcher).not_to receive(:build) expect(received_entity).not_to be_nil
post_message( expect(received_entity.author.diaspora_handle).to eq(remote_user_on_pod_c.diaspora_handle)
alice.guid, end
generate_relayable_remote_parent_wrong_parent_key(entity_name)
) # Checks when a remote pod B wants to send us a relayable with authorship from a remote pod C user
expect(klass.exists?(guid: @entity.guid)).to be(false) # 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
end end

View file

@ -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 shared_examples_for "it retracts non-relayable object" do
it "retracts object by a correct retraction message" do it "retracts object by a correct retraction message" do
target_klass = target_object.class.to_s.constantize entity = retraction_entity(entity_name, target_object, sender)
post_message(alice.guid, generate_retraction(entity_name, target_object)) 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 end
it "doesn't retract object when retraction has wrong signatures" do it "doesn't retract object when retraction has wrong signatures" do
target_klass = target_object.class.to_s.constantize allow(sender).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024))
post_message(alice.guid, generate_forged_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(true) expect(target_object.class.exists?(guid: target_object.guid)).to be_truthy
end end
it "doesn't retract object when sender is different from target object" do it "doesn't retract object when sender is different from target object" do
target_klass = target_object.class.to_s.constantize entity = retraction_entity(entity_name, target_object, remote_user_on_pod_c)
post_message( post_message(generate_xml(entity, remote_user_on_pod_c, recipient), recipient)
alice.guid,
generate_retraction(entity_name, target_object, remote_user_on_pod_c)
)
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
end end
shared_examples_for "it retracts relayable object" do shared_examples_for "it retracts relayable object" do
it "retracts object by a correct message" do it "retracts object by a correct message" do
target_klass = target_object.class.to_s.constantize entity = retraction_entity(entity_name, target_object, sender)
post_message(alice.guid, generate_retraction(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 end
it "doesn't retract object when retraction has wrong signatures" do it "doesn't retract object when retraction has wrong signatures" do
target_klass = target_object.class.to_s.constantize allow(sender).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024))
post_message( entity = retraction_entity(entity_name, target_object, sender)
alice.guid, post_message(generate_xml(entity, sender, recipient), recipient)
generate_forged_retraction(entity_name, target_object, sender)
)
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
end end

View file

@ -1,73 +1,83 @@
# by "stream items" we mean everything that could appear in the stream - post, comment, like, poll, etc and therefore # 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 # 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 shared_examples_for "messages which are indifferent about sharing fact" do
it "treats status message receive correctly" do let(:public) { recipient.nil? }
post_message(alice.guid, generate_status_message)
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 end
it "doesn't accept status message with wrong signature" do 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 end
describe "with messages which require a status to operate on" do describe "with messages which require a status to operate on" do
before do let(:local_target) { FactoryGirl.create(:status_message, author: alice.person, public: public) }
set_up_messages let(:remote_target) { FactoryGirl.create(:status_message, author: remote_user_on_pod_b.person, public: public) }
end
describe "notifications are sent where required" do describe "notifications are sent where required" do
it "for comment on local post" 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( expect(
Notifications::CommentOnPost.where( Notifications::CommentOnPost.exists?(
recipient_id: alice.id, recipient_id: alice.id,
target_type: "Post", target_type: "Post",
target_id: @local_target.id target_id: local_target.id
).first )
).not_to be_nil ).to be_truthy
end end
it "for like on local post" do 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( expect(
Notifications::Liked.where( Notifications::Liked.exists?(
recipient_id: alice.id, recipient_id: alice.id,
target_type: "Post", target_type: "Post",
target_id: @local_target.id target_id: local_target.id
).first )
).not_to be_nil ).to be_truthy
end end
end end
%w(comment like participation).each do |entity| %w(comment like participation).each do |entity|
context "with #{entity}" do context "with #{entity}" do
it_behaves_like "it deals correctly with a relayable" do let(:entity_name) { "#{entity}_entity".to_sym }
let(:entity_name) { "#{entity}_entity".to_sym } let(:klass) { entity.camelize.constantize }
let(:klass) { entity.camelize.constantize }
end it_behaves_like "it deals correctly with a relayable"
end end
end end
context "with poll_participation" do context "with poll_participation" do
before do let(:local_target) {
@local_target = FactoryGirl.create(:poll, status_message: @local_target) FactoryGirl.create(
@remote_target = FactoryGirl.create(:poll, status_message: @remote_target) :poll,
end 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 it_behaves_like "it deals correctly with a relayable"
let(:entity_name) { :poll_participation_entity }
let(:klass) { PollParticipation }
end
end end
end end
end end
@ -75,17 +85,15 @@ end
shared_examples_for "messages which can't be send without sharing" do shared_examples_for "messages which can't be send without sharing" do
# retractions shouldn't depend on sharing fact # retractions shouldn't depend on sharing fact
describe "retractions for non-relayable objects" do describe "retractions for non-relayable objects" do
%w( %w(retraction signed_retraction).each do |retraction_entity_name|
retraction
signed_retraction
).each do |retraction_entity_name|
context "with #{retraction_entity_name}" do context "with #{retraction_entity_name}" do
let(:entity_name) { "#{retraction_entity_name}_entity".to_sym }
%w(status_message photo).each do |target| %w(status_message photo).each do |target|
context "with #{target}" do 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(:target_object) { FactoryGirl.create(target.to_sym, author: remote_user_on_pod_b.person) }
let(:entity_name) { "#{retraction_entity_name}_entity".to_sym } it_behaves_like "it retracts non-relayable object"
end
end end
end end
end end
@ -93,70 +101,62 @@ shared_examples_for "messages which can't be send without sharing" do
end end
describe "with messages which require a status to operate on" do describe "with messages which require a status to operate on" do
before do let(:public) { recipient.nil? }
set_up_messages let(:local_target) { FactoryGirl.create(:status_message, author: alice.person, public: public) }
end 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 # this one shouldn't depend on the sharing fact. this must be fixed
describe "notifications are sent where required" do describe "notifications are sent where required" do
it "for comment on remote post where we participate" do it "for comment on remote post where we participate" do
alice.participate!(@remote_target) alice.participate!(remote_target)
post_message(alice.guid, generate_relayable_remote_parent(:comment_entity)) 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( expect(
Notifications::AlsoCommented.where( Notifications::AlsoCommented.exists?(
recipient_id: alice.id, recipient_id: alice.id,
target_type: "Post", target_type: "Post",
target_id: @remote_target.id target_id: remote_target.id
).first )
).not_to be_nil ).to be_truthy
end end
end end
describe "retractions for relayable objects" do describe "retractions for relayable objects" do
%w( %w(retraction signed_retraction relayable_retraction).each do |retraction_entity_name|
retraction
signed_retraction
relayable_retraction
).each do |retraction_entity_name|
context "with #{retraction_entity_name}" do context "with #{retraction_entity_name}" do
let(:entity_name) { "#{retraction_entity_name}_entity".to_sym }
context "with comment" do context "with comment" do
it_behaves_like "it retracts relayable object" do it_behaves_like "it retracts relayable object" do
# case for to-upstream federation # case for to-upstream federation
let(:entity_name) { "#{retraction_entity_name}_entity".to_sym }
let(:target_object) { 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 end
it_behaves_like "it retracts relayable object" do it_behaves_like "it retracts relayable object" do
# case for to-downsteam federation # case for to-downsteam federation
let(:target_object) { 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
end end
context "with like" do context "with like" do
it_behaves_like "it retracts relayable object" do it_behaves_like "it retracts relayable object" do
# case for to-upstream federation # case for to-upstream federation
let(:entity_name) { "#{retraction_entity_name}_entity".to_sym }
let(:target_object) { 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 end
it_behaves_like "it retracts relayable object" do it_behaves_like "it retracts relayable object" do
# case for to-downsteam federation # case for to-downsteam federation
let(:target_object) { 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 end
end end