From 24f5244f766d1c7c0d277b40c52724239bbebb12 Mon Sep 17 00:00:00 2001 From: Benjamin Neff Date: Fri, 18 Dec 2015 01:13:20 +0100 Subject: [PATCH 1/8] move glue code back to the initializer --- app/models/person.rb | 30 ---------------------- config/initializers/diaspora_federation.rb | 30 ++++++++++++++++++++-- 2 files changed, 28 insertions(+), 32 deletions(-) diff --git a/app/models/person.rb b/app/models/person.rb index 03c929330..f338daf3b 100644 --- a/app/models/person.rb +++ b/app/models/person.rb @@ -317,36 +317,6 @@ class Person < ActiveRecord::Base self end - def webfinger - DiasporaFederation::Discovery::WebFinger.new( - acct_uri: "acct:#{diaspora_handle}", - alias_url: AppConfig.url_to("/people/#{guid}"), - hcard_url: AppConfig.url_to(DiasporaFederation::Engine.routes.url_helpers.hcard_path(guid)), - seed_url: AppConfig.pod_uri, - profile_url: profile_url, - atom_url: atom_url, - salmon_url: receive_url, - guid: guid, - public_key: serialized_public_key - ) - end - - def hcard - DiasporaFederation::Discovery::HCard.new( - guid: guid, - nickname: username, - full_name: "#{profile.first_name} #{profile.last_name}".strip, - url: AppConfig.pod_uri, - photo_large_url: image_url, - photo_medium_url: image_url(:thumb_medium), - photo_small_url: image_url(:thumb_small), - public_key: serialized_public_key, - searchable: searchable, - first_name: profile.first_name, - last_name: profile.last_name - ) - end - protected def clean_url diff --git a/config/initializers/diaspora_federation.rb b/config/initializers/diaspora_federation.rb index b9f3670d0..3cbb9e1e1 100644 --- a/config/initializers/diaspora_federation.rb +++ b/config/initializers/diaspora_federation.rb @@ -8,12 +8,38 @@ DiasporaFederation.configure do |config| config.define_callbacks do on :fetch_person_for_webfinger do |handle| person = Person.find_local_by_diaspora_handle(handle) - person.webfinger if person + if person + DiasporaFederation::Discovery::WebFinger.new( + acct_uri: "acct:#{person.diaspora_handle}", + alias_url: AppConfig.url_to("/people/#{person.guid}"), + hcard_url: AppConfig.url_to(DiasporaFederation::Engine.routes.url_helpers.hcard_path(person.guid)), + seed_url: AppConfig.pod_uri, + profile_url: person.profile_url, + atom_url: person.atom_url, + salmon_url: person.receive_url, + guid: person.guid, + public_key: person.serialized_public_key + ) + end end on :fetch_person_for_hcard do |guid| person = Person.find_local_by_guid(guid) - person.hcard if person + if person + DiasporaFederation::Discovery::HCard.new( + guid: person.guid, + nickname: person.username, + full_name: "#{person.profile.first_name} #{person.profile.last_name}".strip, + url: AppConfig.pod_uri, + photo_large_url: person.image_url, + photo_medium_url: person.image_url(:thumb_medium), + photo_small_url: person.image_url(:thumb_small), + public_key: person.serialized_public_key, + searchable: person.searchable, + first_name: person.profile.first_name, + last_name: person.profile.last_name + ) + end end on :save_person_after_webfinger do |person| From c036a6a4c38009504a3af892f6a57bda9319d122 Mon Sep 17 00:00:00 2001 From: Benjamin Neff Date: Fri, 18 Dec 2015 02:00:01 +0100 Subject: [PATCH 2/8] bump diaspora_federation --- Gemfile | 4 ++-- Gemfile.lock | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Gemfile b/Gemfile index 0d1a7c386..b6bd41bc7 100644 --- a/Gemfile +++ b/Gemfile @@ -12,7 +12,7 @@ gem "unicorn", "4.9.0", require: false # Federation -gem "diaspora_federation-rails", "0.0.9" +gem "diaspora_federation-rails", "0.0.10" # API and JSON @@ -270,7 +270,7 @@ group :test do gem "webmock", "1.22.1", require: false gem "shoulda-matchers", "3.0.0" - gem "diaspora_federation-test", "0.0.9" + gem "diaspora_federation-test", "0.0.10" end group :development, :test do diff --git a/Gemfile.lock b/Gemfile.lock index 0a7247275..86f84be61 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -152,17 +152,17 @@ GEM eventmachine (~> 1.0.8) http_parser.rb (~> 0.6) nokogiri (~> 1.6) - diaspora_federation (0.0.9) + diaspora_federation (0.0.10) faraday (~> 0.9.0) faraday_middleware (~> 0.10.0) - nokogiri (~> 1.6, >= 1.6.6.4) + nokogiri (~> 1.6, >= 1.6.7.1) typhoeus (~> 0.7) valid (~> 1.0) - diaspora_federation-rails (0.0.9) - diaspora_federation (= 0.0.9) + diaspora_federation-rails (0.0.10) + diaspora_federation (= 0.0.10) rails (~> 4.2) - diaspora_federation-test (0.0.9) - diaspora_federation (= 0.0.9) + diaspora_federation-test (0.0.10) + diaspora_federation (= 0.0.10) factory_girl (~> 4.5.0) diff-lcs (1.2.5) docile (1.1.5) @@ -778,8 +778,8 @@ DEPENDENCIES devise-token_authenticatable (~> 0.4.0) devise_lastseenable (= 0.0.6) diaspora-vines (~> 0.2.0.develop) - diaspora_federation-rails (= 0.0.9) - diaspora_federation-test (= 0.0.9) + diaspora_federation-rails (= 0.0.10) + diaspora_federation-test (= 0.0.10) entypo-rails (= 2.2.3) eye (= 0.7) facebox-rails (= 0.2.0) From 5c8f0c16714363f1a5967394728224277efefd32 Mon Sep 17 00:00:00 2001 From: Benjamin Neff Date: Fri, 18 Dec 2015 02:10:07 +0100 Subject: [PATCH 3/8] create queue callbacks and remove receive routes --- app/controllers/publics_controller.rb | 33 ----------- config/initializers/diaspora_federation.rb | 19 ++++++ config/routes.rb | 4 +- spec/controllers/publics_controller_spec.rb | 65 --------------------- spec/federation_callbacks_spec.rb | 35 +++++++++++ 5 files changed, 55 insertions(+), 101 deletions(-) diff --git a/app/controllers/publics_controller.rb b/app/controllers/publics_controller.rb index cca482bbd..5d7d0e0ed 100644 --- a/app/controllers/publics_controller.rb +++ b/app/controllers/publics_controller.rb @@ -7,7 +7,6 @@ class PublicsController < ApplicationController skip_before_action :set_header_data skip_before_action :set_grammatical_gender - before_action :check_for_xml, :only => [:receive, :receive_public] before_action :authenticate_user!, :only => [:index] respond_to :html @@ -18,36 +17,4 @@ class PublicsController < ApplicationController def hub render :text => params['hub.challenge'], :status => 202, :layout => false end - - def receive_public - logger.info "received a public message" - Workers::ReceiveUnencryptedSalmon.perform_async(CGI::unescape(params[:xml])) - render :nothing => true, :status => :ok - end - - def receive - person = Person.find_by_guid(params[:guid]) - - if person.nil? || person.owner_id.nil? - logger.error "Received post for nonexistent person #{params[:guid]}" - render :nothing => true, :status => 404 - return - end - - @user = person.owner - - logger.info "received a private message for user: #{@user.id}" - Workers::ReceiveEncryptedSalmon.perform_async(@user.id, CGI::unescape(params[:xml])) - - render :nothing => true, :status => 202 - end - - private - - def check_for_xml - if params[:xml].nil? - render :nothing => true, :status => 422 - return - end - end end diff --git a/config/initializers/diaspora_federation.rb b/config/initializers/diaspora_federation.rb index 3cbb9e1e1..58285b292 100644 --- a/config/initializers/diaspora_federation.rb +++ b/config/initializers/diaspora_federation.rb @@ -89,5 +89,24 @@ DiasporaFederation.configure do |config| on :fetch_entity_author_id_by_guid do |entity_type, guid| entity_type.constantize.where(guid: guid).joins(:author).pluck(:diaspora_handle).first end + + on :queue_public_receive do |xml| + Workers::ReceiveUnencryptedSalmon.perform_async(xml) + end + + on :queue_private_receive do |guid, xml| + person = Person.find_by_guid(guid) + + if person.nil? || person.owner_id.nil? + false + else + Workers::ReceiveEncryptedSalmon.perform_async(person.owner.id, xml) + true + end + end + + on :save_entity_after_receive do + # TODO + end end end diff --git a/config/routes.rb b/config/routes.rb index fe9c1e1cc..33e5847a1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -186,9 +186,7 @@ Diaspora::Application.routes.draw do # Federation controller :publics do - post 'receive/users/:guid' => :receive - post 'receive/public' => :receive_public - get 'hub' => :hub + get "hub" => :hub end diff --git a/spec/controllers/publics_controller_spec.rb b/spec/controllers/publics_controller_spec.rb index 5b105688b..3f3d089ba 100644 --- a/spec/controllers/publics_controller_spec.rb +++ b/spec/controllers/publics_controller_spec.rb @@ -5,71 +5,6 @@ require 'spec_helper' describe PublicsController, :type => :controller do - let(:fixture_path) { Rails.root.join('spec', 'fixtures') } - before do - @user = alice - @person = FactoryGirl.create(:person) - end - - describe '#receive_public' do - it 'succeeds' do - post :receive_public, :xml => "" - expect(response).to be_success - end - - it 'returns a 422 if no xml is passed' do - post :receive_public - expect(response.code).to eq('422') - end - - it 'enqueues a ReceiveUnencryptedSalmon job' do - xml = "stuff" - expect(Workers::ReceiveUnencryptedSalmon).to receive(:perform_async).with(xml) - post :receive_public, :xml => xml - end - end - - describe '#receive' do - let(:xml) { "" } - - it 'succeeds' do - post :receive, "guid" => @user.person.guid.to_s, "xml" => xml - expect(response).to be_success - end - - it 'enqueues a receive job' do - expect(Workers::ReceiveEncryptedSalmon).to receive(:perform_async).with(@user.id, xml).once - post :receive, "guid" => @user.person.guid.to_s, "xml" => xml - end - - it 'unescapes the xml before sending it to receive_salmon' do - aspect = @user.aspects.create(:name => 'foo') - post1 = @user.post(:status_message, :text => 'moms', :to => [aspect.id]) - xml2 = post1.to_diaspora_xml - user2 = FactoryGirl.create(:user) - - salmon_factory = Salmon::EncryptedSlap.create_by_user_and_activity(@user, xml2) - enc_xml = salmon_factory.xml_for(user2.person) - - expect(Workers::ReceiveEncryptedSalmon).to receive(:perform_async).with(@user.id, enc_xml).once - post :receive, "guid" => @user.person.guid.to_s, "xml" => CGI::escape(enc_xml) - end - - it 'returns a 422 if no xml is passed' do - post :receive, "guid" => @person.guid.to_s - expect(response.code).to eq('422') - end - - it 'returns a 404 if no user is found' do - post :receive, "guid" => @person.guid.to_s, "xml" => xml - expect(response).to be_not_found - end - it 'returns a 404 if no person is found' do - post :receive, :guid => '2398rq3948yftn', :xml => xml - expect(response).to be_not_found - end - end - describe '#hub' do it 'succeeds' do get :hub diff --git a/spec/federation_callbacks_spec.rb b/spec/federation_callbacks_spec.rb index 7c5cd9640..dc763b05c 100644 --- a/spec/federation_callbacks_spec.rb +++ b/spec/federation_callbacks_spec.rb @@ -266,4 +266,39 @@ describe "diaspora federation callbacks" do ).to be_nil end end + + describe ":queue_public_receive" do + it "enqueues a ReceiveUnencryptedSalmon job" do + xml = "" + expect(Workers::ReceiveUnencryptedSalmon).to receive(:perform_async).with(xml) + + DiasporaFederation.callbacks.trigger(:queue_public_receive, xml) + end + end + + describe ":queue_private_receive" do + let(:xml) { "" } + + it "returns true if the user is found" do + result = DiasporaFederation.callbacks.trigger(:queue_private_receive, alice.person.guid, xml) + expect(result).to be_truthy + end + + it "enqueues a ReceiveEncryptedSalmon job" do + expect(Workers::ReceiveEncryptedSalmon).to receive(:perform_async).with(alice.id, xml) + + DiasporaFederation.callbacks.trigger(:queue_private_receive, alice.person.guid, xml) + end + + it "returns false if the no user is found" do + person = FactoryGirl.create(:person) + result = DiasporaFederation.callbacks.trigger(:queue_private_receive, person.guid, xml) + expect(result).to be_falsey + end + + it "returns false if the no person is found" do + result = DiasporaFederation.callbacks.trigger(:queue_private_receive, "2398rq3948yftn", xml) + expect(result).to be_falsey + end + end end From 05e4c8dc51cd25efc272d8eed086da7e141105d5 Mon Sep 17 00:00:00 2001 From: Benjamin Neff Date: Sun, 20 Dec 2015 21:41:39 +0100 Subject: [PATCH 4/8] improve key specs in federation_callbacks_spec.rb --- spec/federation_callbacks_spec.rb | 90 +++++++++++++++---------------- 1 file changed, 42 insertions(+), 48 deletions(-) diff --git a/spec/federation_callbacks_spec.rb b/spec/federation_callbacks_spec.rb index dc763b05c..80d2ba6de 100644 --- a/spec/federation_callbacks_spec.rb +++ b/spec/federation_callbacks_spec.rb @@ -149,120 +149,114 @@ describe "diaspora federation callbacks" do end end - def create_a_local_person - FactoryGirl.create(:user).person - end + let(:local_person) { FactoryGirl.create(:user).person } + let(:remote_person) { FactoryGirl.create(:person) } + let(:post_by_a_local_person) { FactoryGirl.create(:status_message, author: local_person) } + let(:post_by_a_remote_person) { FactoryGirl.create(:status_message, author: remote_person) } - def create_a_remote_person - FactoryGirl.create(:person) - end - - def create_post_by_a_local_person - FactoryGirl.create(:status_message, author: create_a_local_person).guid - end - - def create_post_by_a_remote_person - FactoryGirl.create(:status_message, author: create_a_remote_person).guid - end - - describe :fetch_private_key_by_diaspora_id do + describe ":fetch_private_key_by_diaspora_id" do it "returns a private key for a local user" do - expect( - DiasporaFederation.callbacks.trigger(described_class, create_a_local_person.diaspora_handle) - ).not_to be_nil + key = DiasporaFederation.callbacks.trigger(:fetch_private_key_by_diaspora_id, local_person.diaspora_handle) + expect(key).to be_a(OpenSSL::PKey::RSA) + expect(key.to_s).to eq(local_person.owner.serialized_private_key) end it "returns nil for a remote user" do expect( - DiasporaFederation.callbacks.trigger(described_class, create_a_remote_person.diaspora_handle) + DiasporaFederation.callbacks.trigger(:fetch_private_key_by_diaspora_id, remote_person.diaspora_handle) ).to be_nil end it "returns nil for an unknown id" do expect( - DiasporaFederation.callbacks.trigger(described_class, FactoryGirl.generate(:diaspora_id)) + DiasporaFederation.callbacks.trigger(:fetch_private_key_by_diaspora_id, FactoryGirl.generate(:diaspora_id)) ).to be_nil end end - describe :fetch_author_private_key_by_entity_guid do + describe ":fetch_author_private_key_by_entity_guid" do it "returns a private key for a post by a local user" do - expect( - DiasporaFederation.callbacks.trigger(described_class, "Post", create_post_by_a_local_person) - ).not_to be_nil + key = DiasporaFederation.callbacks.trigger(:fetch_author_private_key_by_entity_guid, + "Post", post_by_a_local_person.guid) + expect(key).to be_a(OpenSSL::PKey::RSA) + expect(key.to_s).to eq(post_by_a_local_person.author.owner.serialized_private_key) end it "returns nil for a post by a remote user" do expect( - DiasporaFederation.callbacks.trigger(described_class, "Post", create_post_by_a_remote_person) + DiasporaFederation.callbacks.trigger(:fetch_author_private_key_by_entity_guid, + "Post", post_by_a_remote_person.guid) ).to be_nil end it "returns nil for an unknown post" do expect( - DiasporaFederation.callbacks.trigger(described_class, "Post", FactoryGirl.generate(:guid)) + DiasporaFederation.callbacks.trigger(:fetch_author_private_key_by_entity_guid, + "Post", FactoryGirl.generate(:guid)) ).to be_nil end end - describe :fetch_public_key_by_diaspora_id do + describe ":fetch_public_key_by_diaspora_id" do it "returns a public key for a person" do - expect( - DiasporaFederation.callbacks.trigger(described_class, create_a_remote_person.diaspora_handle) - ).not_to be_nil + key = DiasporaFederation.callbacks.trigger(:fetch_public_key_by_diaspora_id, remote_person.diaspora_handle) + expect(key).to be_a(OpenSSL::PKey::RSA) + expect(key.to_s).to eq(remote_person.serialized_public_key) end it "returns nil for an unknown person" do expect( - DiasporaFederation.callbacks.trigger(described_class, FactoryGirl.generate(:diaspora_id)) + DiasporaFederation.callbacks.trigger(:fetch_public_key_by_diaspora_id, FactoryGirl.generate(:diaspora_id)) ).to be_nil end end - describe :fetch_author_public_key_by_entity_guid do + describe ":fetch_author_public_key_by_entity_guid" do it "returns a public key for a known post" do - expect( - DiasporaFederation.callbacks.trigger(described_class, "Post", create_post_by_a_remote_person) - ).not_to be_nil + key = DiasporaFederation.callbacks.trigger(:fetch_author_public_key_by_entity_guid, + "Post", post_by_a_remote_person.guid) + expect(key).to be_a(OpenSSL::PKey::RSA) + expect(key.to_s).to eq(post_by_a_remote_person.author.serialized_public_key) end it "returns nil for an unknown post" do expect( - DiasporaFederation.callbacks.trigger(described_class, "Post", FactoryGirl.generate(:guid)) + DiasporaFederation.callbacks.trigger(:fetch_author_public_key_by_entity_guid, + "Post", FactoryGirl.generate(:guid)) ).to be_nil end end - describe :entity_author_is_local? do + describe ":entity_author_is_local?" do it "returns true for a post by a local user" do expect( - DiasporaFederation.callbacks.trigger(described_class, "Post", create_post_by_a_local_person) - ).to be(true) + DiasporaFederation.callbacks.trigger(:entity_author_is_local?, "Post", post_by_a_local_person.guid) + ).to be_truthy end it "returns false for a post by a remote user" do expect( - DiasporaFederation.callbacks.trigger(described_class, "Post", create_post_by_a_remote_person) - ).to be(false) + DiasporaFederation.callbacks.trigger(:entity_author_is_local?, "Post", post_by_a_remote_person.guid) + ).to be_falsey end it "returns false for a unknown post" do expect( - DiasporaFederation.callbacks.trigger(described_class, "Post", FactoryGirl.generate(:diaspora_id)) - ).to be(false) + DiasporaFederation.callbacks.trigger(:entity_author_is_local?, "Post", FactoryGirl.generate(:diaspora_id)) + ).to be_falsey end end - describe :fetch_entity_author_id_by_guid do + describe ":fetch_entity_author_id_by_guid" do it "returns id for a existing guid" do expect( - DiasporaFederation.callbacks.trigger(described_class, "Post", create_post_by_a_remote_person) - ).not_to be_nil + DiasporaFederation.callbacks.trigger(:fetch_entity_author_id_by_guid, "Post", post_by_a_remote_person.guid) + ).not_to eq(post_by_a_remote_person.author_id) end it "returns nil for a non-existing guid" do expect( - DiasporaFederation.callbacks.trigger(described_class, "Post", FactoryGirl.generate(:guid)) + DiasporaFederation.callbacks.trigger(:fetch_entity_author_id_by_guid, "Post", FactoryGirl.generate(:guid)) ).to be_nil end end From 082e300a4007ef7f0f1ae35cf80e42c551d8f700 Mon Sep 17 00:00:00 2001 From: Benjamin Neff Date: Mon, 21 Dec 2015 02:35:49 +0100 Subject: [PATCH 5/8] remove PublicsController completely --- app/controllers/publics_controller.rb | 20 -------------------- config/routes.rb | 10 +--------- spec/controllers/publics_controller_spec.rb | 14 -------------- 3 files changed, 1 insertion(+), 43 deletions(-) delete mode 100644 app/controllers/publics_controller.rb delete mode 100644 spec/controllers/publics_controller_spec.rb diff --git a/app/controllers/publics_controller.rb b/app/controllers/publics_controller.rb deleted file mode 100644 index 5d7d0e0ed..000000000 --- a/app/controllers/publics_controller.rb +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -class PublicsController < ApplicationController - include Diaspora::Parser - - skip_before_action :set_header_data - skip_before_action :set_grammatical_gender - before_action :authenticate_user!, :only => [:index] - - respond_to :html - respond_to :xml, :only => :post - - layout false - - def hub - render :text => params['hub.challenge'], :status => 202, :layout => false - end -end diff --git a/config/routes.rb b/config/routes.rb index 33e5847a1..2daa85525 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -18,6 +18,7 @@ Diaspora::Application.routes.draw do mount Sidekiq::Web => '/sidekiq', :as => 'sidekiq' end + # Federation mount DiasporaFederation::Engine => "/" get "/atom.xml" => redirect('http://blog.diasporafoundation.org/feed/atom') #too many stupid redirects :() @@ -182,15 +183,6 @@ Diaspora::Application.routes.draw do get '/u/:username' => 'people#show', :as => 'user_profile', :constraints => { :username => /[^\/]+/ } get '/u/:username/profile_photo' => 'users#user_photo', :constraints => { :username => /[^\/]+/ } - - # Federation - - controller :publics do - get "hub" => :hub - end - - - # External resources :services, :only => [:index, :destroy] diff --git a/spec/controllers/publics_controller_spec.rb b/spec/controllers/publics_controller_spec.rb deleted file mode 100644 index 3f3d089ba..000000000 --- a/spec/controllers/publics_controller_spec.rb +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -require 'spec_helper' - -describe PublicsController, :type => :controller do - describe '#hub' do - it 'succeeds' do - get :hub - expect(response).to be_success - end - end -end From 0e7bb6d75643e84a770f58a5eb17d83c2eddccb9 Mon Sep 17 00:00:00 2001 From: Benjamin Neff Date: Mon, 28 Dec 2015 01:39:21 +0100 Subject: [PATCH 6/8] define federation entity factories --- spec/factories.rb | 3 +++ spec/support/fixture_builder.rb | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/spec/factories.rb b/spec/factories.rb index 87110bcf0..0d95a9606 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -10,6 +10,9 @@ def r_str SecureRandom.hex(3) end +require "diaspora_federation/test" +DiasporaFederation::Test::Factories.federation_factories + FactoryGirl.define do factory :profile do sequence(:first_name) { |n| "Robert#{n}#{r_str}" } diff --git a/spec/support/fixture_builder.rb b/spec/support/fixture_builder.rb index 34f981a33..e7d90d83f 100644 --- a/spec/support/fixture_builder.rb +++ b/spec/support/fixture_builder.rb @@ -34,11 +34,11 @@ FixtureBuilder.configure do |fbuilder| local_leia.contacts.create(:person => remote_raphael, :aspects => [leias_aspect]) local_luke.contacts.create(:person => remote_raphael, :aspects => [lukes_aspect]) - + # Set up a follower peter = FactoryGirl.create(:user_with_aspect, :username => "peter") peters_aspect = peter.aspects.where(:name => "generic").first - + peter.contacts.create!(:person => alice.person, :aspects => [peters_aspect], :sharing => false, From 9f8e018422932ed32dcd936341b60271fb43da25 Mon Sep 17 00:00:00 2001 From: Benjamin Neff Date: Mon, 28 Dec 2015 01:51:41 +0100 Subject: [PATCH 7/8] add subscribe url to webfinger --- config/initializers/diaspora_federation.rb | 19 ++++++++++--------- spec/federation_callbacks_spec.rb | 1 + 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/config/initializers/diaspora_federation.rb b/config/initializers/diaspora_federation.rb index 58285b292..4d63aebd2 100644 --- a/config/initializers/diaspora_federation.rb +++ b/config/initializers/diaspora_federation.rb @@ -10,15 +10,16 @@ DiasporaFederation.configure do |config| person = Person.find_local_by_diaspora_handle(handle) if person DiasporaFederation::Discovery::WebFinger.new( - acct_uri: "acct:#{person.diaspora_handle}", - alias_url: AppConfig.url_to("/people/#{person.guid}"), - hcard_url: AppConfig.url_to(DiasporaFederation::Engine.routes.url_helpers.hcard_path(person.guid)), - seed_url: AppConfig.pod_uri, - profile_url: person.profile_url, - atom_url: person.atom_url, - salmon_url: person.receive_url, - guid: person.guid, - public_key: person.serialized_public_key + acct_uri: "acct:#{person.diaspora_handle}", + alias_url: AppConfig.url_to("/people/#{person.guid}"), + hcard_url: AppConfig.url_to(DiasporaFederation::Engine.routes.url_helpers.hcard_path(person.guid)), + seed_url: AppConfig.pod_uri, + profile_url: person.profile_url, + atom_url: person.atom_url, + salmon_url: person.receive_url, + subscribe_url: AppConfig.url_to("/people?q={uri}"), + guid: person.guid, + public_key: person.serialized_public_key ) end end diff --git a/spec/federation_callbacks_spec.rb b/spec/federation_callbacks_spec.rb index 80d2ba6de..a775d5ecc 100644 --- a/spec/federation_callbacks_spec.rb +++ b/spec/federation_callbacks_spec.rb @@ -13,6 +13,7 @@ describe "diaspora federation callbacks" do expect(wf.profile_url).to eq(person.profile_url) expect(wf.atom_url).to eq(person.atom_url) expect(wf.salmon_url).to eq(person.receive_url) + expect(wf.subscribe_url).to eq(AppConfig.url_to("/people?q={uri}")) expect(wf.guid).to eq(person.guid) expect(wf.public_key).to eq(person.serialized_public_key) end From 5392c6e6a905552c8b0831dd7983f7511ca5c622 Mon Sep 17 00:00:00 2001 From: Benjamin Neff Date: Mon, 28 Dec 2015 19:46:45 +0100 Subject: [PATCH 8/8] refactoring for federation tests --- .../federation/federation_helper.rb | 26 ++++ .../federation_messages_generation.rb | 132 ---------------- .../federation/receive_federation_messages.rb | 146 ------------------ .../receive_federation_messages_spec.rb | 130 ++++++++++++++++ .../federation/shared_receive_relayable.rb | 116 ++++++++++---- .../federation/shared_receive_retraction.rb | 55 ++++--- 6 files changed, 278 insertions(+), 327 deletions(-) create mode 100644 spec/integration/federation/federation_helper.rb delete mode 100644 spec/integration/federation/federation_messages_generation.rb delete mode 100644 spec/integration/federation/receive_federation_messages.rb create mode 100644 spec/integration/federation/receive_federation_messages_spec.rb diff --git a/spec/integration/federation/federation_helper.rb b/spec/integration/federation/federation_helper.rb new file mode 100644 index 000000000..5d536098d --- /dev/null +++ b/spec/integration/federation/federation_helper.rb @@ -0,0 +1,26 @@ +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 +end + +def remote_user_on_pod_c + @remote_on_c ||= 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") + end +end + +def generate_xml(entity, remote_user, user) + 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 diff --git a/spec/integration/federation/federation_messages_generation.rb b/spec/integration/federation/federation_messages_generation.rb deleted file mode 100644 index 59bcc315e..000000000 --- a/spec/integration/federation/federation_messages_generation.rb +++ /dev/null @@ -1,132 +0,0 @@ -def generate_xml(entity, remote_user, user) - 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 - -def generate_status_message - @entity = FactoryGirl.build( - :status_message_entity, - diaspora_id: @remote_user.diaspora_handle, - public: false - ) - - generate_xml(@entity, @remote_user, @user) -end - -def generate_forged_status_message - substitute_wrong_key(@remote_user, 1) - generate_status_message -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) - .once - .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 - ) - .once - .and_return(sender.encryption_key) -end - -def generate_retraction(entity_name, target_object, sender=@remote_user) - @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, @user) -end - -def generate_forged_retraction(entity_name, target_object, sender=@remote_user) - 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_local_parent(entity_name) - @entity = FactoryGirl.build( - entity_name, - parent_guid: @local_message.guid, - diaspora_id: @remote_user.person.diaspora_handle - ) - - mock_private_key_for_user(@remote_user) - - expect(DiasporaFederation.callbacks).to receive(:trigger) - .with(:fetch_author_private_key_by_entity_guid, "Post", kind_of(String)) - .and_return(nil) - generate_xml(@entity, @remote_user, @user) -end - -def generate_relayable_remote_parent(entity_name) - @entity = FactoryGirl.build( - entity_name, - parent_guid: @remote_message.guid, - diaspora_id: @remote_user2.person.diaspora_handle - ) - - mock_private_key_for_user(@remote_user2) - - expect(DiasporaFederation.callbacks).to receive(:trigger) - .with( - :fetch_author_private_key_by_entity_guid, - "Post", - @remote_message.guid - ) - .once - .and_return(@remote_user.encryption_key) - generate_xml(@entity, @remote_user, @user) -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, 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_user2, 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, 2) - generate_relayable_remote_parent(entity_name) -end diff --git a/spec/integration/federation/receive_federation_messages.rb b/spec/integration/federation/receive_federation_messages.rb deleted file mode 100644 index 4436c109d..000000000 --- a/spec/integration/federation/receive_federation_messages.rb +++ /dev/null @@ -1,146 +0,0 @@ -require "spec_helper" -require "diaspora_federation/test" -require "integration/federation/federation_messages_generation" -require "integration/federation/shared_receive_relayable" -require "integration/federation/shared_receive_retraction" - -describe Workers::ReceiveEncryptedSalmon do - before do - @user = alice - allow(User).to receive(:find) { |id| - @user if id == @user.id - } - - @remote_user = FactoryGirl.build(:user) # user on pod B - @remote_user2 = FactoryGirl.build(:user) # user on pod C - - allow_any_instance_of(DiasporaFederation::Discovery::Discovery) - .to receive(:webfinger) {|instance| - [@remote_user, @remote_user2].find {|user| user.diaspora_handle == instance.diaspora_id }.person.webfinger - } - allow_any_instance_of(DiasporaFederation::Discovery::Discovery) - .to receive(:hcard) {|instance| - [@remote_user, @remote_user2].find {|user| user.diaspora_handle == instance.diaspora_id }.person.hcard - } - - @remote_person = Person.find_or_fetch_by_identifier(@remote_user.diaspora_handle) - @remote_person2 = Person.find_or_fetch_by_identifier(@remote_user2.diaspora_handle) - end - - it "treats sharing request recive correctly" do - entity = FactoryGirl.build(:request_entity, recipient_id: @user.diaspora_handle) - - expect(Diaspora::Fetcher::Public).to receive(:queue_for).exactly(1).times - - Workers::ReceiveEncryptedSalmon.new.perform(@user.id, generate_xml(entity, @remote_user, @user)) - - expect(@user.contacts.count).to eq(2) - new_contact = @user.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.diaspora_handle) - end - - it "doesn't save the status message if there is no sharing" do - Workers::ReceiveEncryptedSalmon.new.perform(@user.id, generate_status_message) - - expect(StatusMessage.exists?(guid: @entity.guid)).to be(false) - end - - describe "with messages which require sharing" do - before do - @remote_person = Person.find_or_fetch_by_identifier(@remote_user.diaspora_handle) - contact = @user.contacts.find_or_initialize_by(person_id: @remote_person.id) - contact.sharing = true - contact.save - end - - it "treats status message receive correctly" do - Workers::ReceiveEncryptedSalmon.new.perform(@user.id, generate_status_message) - - expect(StatusMessage.exists?(guid: @entity.guid)).to be(true) - end - - it "doesn't accept status message with wrong signature" do - Workers::ReceiveEncryptedSalmon.new.perform(@user.id, generate_forged_status_message) - - expect(StatusMessage.exists?(guid: @entity.guid)).to be(false) - end - - describe "retractions for non-relayable objects" do - %w( - retraction - signed_retraction - ).each do |retraction_entity_name| - context "with #{retraction_entity_name}" do - %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_person) } - let(:entity_name) { "#{retraction_entity_name}_entity".to_sym } - end - end - end - end - end - end - - describe "with messages which require a status to operate on" do - before do - @local_message = FactoryGirl.create(:status_message, author: @user.person) - @remote_message = FactoryGirl.create(:status_message, author: @remote_person) - 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 - end - end - - describe "retractions for relayable objects" do - %w( - retraction - signed_retraction - relayable_retraction - ).each do |retraction_entity_name| - context "with #{retraction_entity_name}" do - 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_person, post: @local_message) } - let(:sender) { @remote_user } - end - - it_behaves_like "it retracts relayable object" do - # case for to-downsteam federation - let(:target_object) { FactoryGirl.create(:comment, author: @remote_person2, post: @remote_message) } - let(:entity_name) { "#{retraction_entity_name}_entity".to_sym } - let(:sender) { @remote_user } - 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_person, target: @local_message) } - let(:sender) { @remote_user } - end - - it_behaves_like "it retracts relayable object" do - # case for to-downsteam federation - let(:target_object) { FactoryGirl.create(:like, author: @remote_person2, target: @remote_message) } - let(:entity_name) { "#{retraction_entity_name}_entity".to_sym } - let(:sender) { @remote_user } - end - end - end - end - end - end - end -end diff --git a/spec/integration/federation/receive_federation_messages_spec.rb b/spec/integration/federation/receive_federation_messages_spec.rb new file mode 100644 index 000000000..fdb479dc5 --- /dev/null +++ b/spec/integration/federation/receive_federation_messages_spec.rb @@ -0,0 +1,130 @@ +require "spec_helper" +require "integration/federation/federation_helper" +require "integration/federation/shared_receive_relayable" +require "integration/federation/shared_receive_retraction" + +describe Workers::ReceiveEncryptedSalmon do + it "treats sharing request receive correctly" do + entity = FactoryGirl.build(:request_entity, recipient_id: alice.diaspora_handle) + + expect(Diaspora::Fetcher::Public).to receive(:queue_for) + Workers::ReceiveEncryptedSalmon.new.perform(alice.id, generate_xml(entity, remote_user_on_pod_c, alice)) + + new_contact = alice.contacts.find {|c| c.person.diaspora_handle == remote_user_on_pod_c.diaspora_handle } + expect(new_contact).not_to be_nil + expect(new_contact.sharing).to eq(true) + end + + it "doesn't save the status message if there is no sharing" do + entity = FactoryGirl.build(:status_message_entity, diaspora_id: remote_user_on_pod_b.diaspora_handle, public: false) + Workers::ReceiveEncryptedSalmon.new.perform(alice.id, generate_xml(entity, remote_user_on_pod_b, alice)) + + expect(StatusMessage.exists?(guid: entity.guid)).to be(false) + end + + describe "with messages which require sharing" do + before do + contact = alice.contacts.find_or_initialize_by(person_id: remote_user_on_pod_b.person.id) + contact.sharing = true + contact.save + end + + it "treats status message receive correctly" do + entity = FactoryGirl.build(:status_message_entity, + diaspora_id: remote_user_on_pod_b.diaspora_handle, public: false) + Workers::ReceiveEncryptedSalmon.new.perform(alice.id, generate_xml(entity, remote_user_on_pod_b, alice)) + + expect(StatusMessage.exists?(guid: entity.guid)).to be(true) + end + + it "doesn't accept status message with wrong signature" do + expect(remote_user_on_pod_b).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024)) + + entity = FactoryGirl.build(:status_message_entity, + diaspora_id: remote_user_on_pod_b.diaspora_handle, public: false) + Workers::ReceiveEncryptedSalmon.new.perform(alice.id, generate_xml(entity, remote_user_on_pod_b, alice)) + + expect(StatusMessage.exists?(guid: entity.guid)).to be(false) + end + + describe "retractions for non-relayable objects" do + %w( + retraction + signed_retraction + ).each do |retraction_entity_name| + context "with #{retraction_entity_name}" do + %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 + end + end + end + end + end + + describe "with messages which require a status to operate on" do + let(:local_message) { FactoryGirl.create(:status_message, author: alice.person) } + let(:remote_message) { FactoryGirl.create(:status_message, author: remote_user_on_pod_b.person) } + + %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 + end + end + + describe "retractions for relayable objects" do + let(:sender) { remote_user_on_pod_b } + + %w( + retraction + signed_retraction + relayable_retraction + ).each do |retraction_entity_name| + context "with #{retraction_entity_name}" do + context "with comment" do + it_behaves_like "it retracts 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_message) + } + end + + it_behaves_like "it retracts object" do + # case for to-downsteam federation + let(:entity_name) { "#{retraction_entity_name}_entity".to_sym } + let(:target_object) { + FactoryGirl.create(:comment, author: remote_user_on_pod_c.person, post: remote_message) + } + end + end + + context "with like" do + it_behaves_like "it retracts 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_message) + } + end + + it_behaves_like "it retracts object" do + # case for to-downsteam federation + let(:entity_name) { "#{retraction_entity_name}_entity".to_sym } + let(:target_object) { + FactoryGirl.create(:like, author: remote_user_on_pod_c.person, target: remote_message) + } + end + end + end + end + end + end + end +end diff --git a/spec/integration/federation/shared_receive_relayable.rb b/spec/integration/federation/shared_receive_relayable.rb index 2d25cce46..519a2793b 100644 --- a/spec/integration/federation/shared_receive_relayable.rb +++ b/spec/integration/federation/shared_receive_relayable.rb @@ -1,39 +1,93 @@ shared_examples_for "it deals correctly with a relayable" do - it "treats upstream receive correctly" do - Workers::ReceiveEncryptedSalmon.new.perform(@user.id, 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_person.diaspora_handle) + context "local" do + let(:entity) { + FactoryGirl.build( + entity_name, + parent_guid: local_message.guid, + diaspora_id: remote_user_on_pod_b.diaspora_handle + ) + } + + def mock_private_keys + allow(DiasporaFederation.callbacks).to receive(:trigger) + .with(:fetch_private_key_by_diaspora_id, + remote_user_on_pod_b.diaspora_handle) + .and_return(remote_user_on_pod_b.encryption_key) + allow(DiasporaFederation.callbacks).to receive(:trigger) + .with(:fetch_author_private_key_by_entity_guid, "Post", kind_of(String)) + .and_return(nil) + end + + it "treats upstream receive correctly" do + mock_private_keys + + Workers::ReceiveEncryptedSalmon.new.perform(alice.id, generate_xml(entity, remote_user_on_pod_b, alice)) + 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) + 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 + allow(remote_user_on_pod_b).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024)) + mock_private_keys + + Workers::ReceiveEncryptedSalmon.new.perform(alice.id, generate_xml(entity, remote_user_on_pod_b, alice)) + expect(klass.exists?(guid: entity.guid)).to be(false) + end end - it "rejects an upstream entity with a malformed author signature" do - Workers::ReceiveEncryptedSalmon.new.perform( - @user.id, - generate_relayable_local_parent_wrong_author_key(entity_name) - ) - expect(klass.exists?(guid: @entity.guid)).to be(false) - end + context "remote parent" do + let(:entity) { + FactoryGirl.build( + entity_name, + parent_guid: remote_message.guid, + diaspora_id: remote_user_on_pod_c.diaspora_handle + ) + } - it "treats downstream receive correctly" do - Workers::ReceiveEncryptedSalmon.new.perform(@user.id, 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_person2.diaspora_handle) - end + def mock_private_keys + allow(DiasporaFederation.callbacks).to receive(:trigger) + .with(:fetch_private_key_by_diaspora_id, + remote_user_on_pod_c.diaspora_handle) + .and_return(remote_user_on_pod_c.encryption_key) - it "rejects a downstream entity with a malformed author signature" do - Workers::ReceiveEncryptedSalmon.new.perform( - @user.id, - generate_relayable_remote_parent_wrong_author_key(entity_name) - ) - expect(klass.exists?(guid: @entity.guid)).to be(false) - end + allow(DiasporaFederation.callbacks).to receive(:trigger) + .with( + :fetch_author_private_key_by_entity_guid, + "Post", + remote_message.guid + ) + .and_return(remote_user_on_pod_b.encryption_key) + end - it "declines downstream receive when sender signed with a wrong key" do - Workers::ReceiveEncryptedSalmon.new.perform( - @user.id, - generate_relayable_remote_parent_wrong_parent_key(entity_name) - ) - expect(klass.exists?(guid: @entity.guid)).to be(false) + it "treats downstream receive correctly" do + mock_private_keys + + Workers::ReceiveEncryptedSalmon.new.perform(alice.id, generate_xml(entity, remote_user_on_pod_b, alice)) + 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 + allow(remote_user_on_pod_c).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024)) + mock_private_keys + + Workers::ReceiveEncryptedSalmon.new.perform(alice.id, generate_xml(entity, remote_user_on_pod_b, alice)) + expect(klass.exists?(guid: entity.guid)).to be(false) + 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 + allow(remote_user_on_pod_b).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024)) + mock_private_keys + + Workers::ReceiveEncryptedSalmon.new.perform(alice.id, generate_xml(entity, remote_user_on_pod_b, alice)) + expect(klass.exists?(guid: entity.guid)).to be(false) + end end end diff --git a/spec/integration/federation/shared_receive_retraction.rb b/spec/integration/federation/shared_receive_retraction.rb index af02defab..4264bc1ad 100644 --- a/spec/integration/federation/shared_receive_retraction.rb +++ b/spec/integration/federation/shared_receive_retraction.rb @@ -1,43 +1,62 @@ -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 - Workers::ReceiveEncryptedSalmon.new.perform(@user.id, generate_retraction(entity_name, target_object)) - - expect(target_klass.exists?(guid: target_object.guid)).to be(false) +def mock_private_keys_for_retraction(entity_name, entity, sender) + if %i(signed_retraction_entity relayable_retraction_entity).include?(entity_name) + allow(DiasporaFederation.callbacks).to receive(:trigger) + .with(:fetch_private_key_by_diaspora_id, sender.diaspora_handle) + .and_return(sender.encryption_key) end + if entity_name == :relayable_retraction_entity + 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 +end - it "doesn't retract object when retraction has wrong signatures" do - target_klass = target_object.class.to_s.constantize - Workers::ReceiveEncryptedSalmon.new.perform(@user.id, generate_forged_retraction(entity_name, target_object)) +def generate_retraction(entity_name, target_object, sender) + entity = FactoryGirl.build( + entity_name, + diaspora_id: sender.diaspora_handle, + target_guid: target_object.guid, + target_type: target_object.class.to_s + ) - expect(target_klass.exists?(guid: target_object.guid)).to be(true) + mock_private_keys_for_retraction(entity_name, entity, sender) + generate_xml(entity, sender, alice) +end + +shared_examples_for "it retracts non-relayable object" do + it_behaves_like "it retracts object" do + let(:sender) { remote_user_on_pod_b } end it "doesn't retract object when sender is different from target object" do target_klass = target_object.class.to_s.constantize Workers::ReceiveEncryptedSalmon.new.perform( - @user.id, - generate_retraction(entity_name, target_object, @remote_user2) + alice.id, + generate_retraction(entity_name, target_object, remote_user_on_pod_c) ) expect(target_klass.exists?(guid: target_object.guid)).to be(true) end end -shared_examples_for "it retracts relayable object" do +shared_examples_for "it retracts object" do it "retracts object by a correct message" do target_klass = target_object.class.to_s.constantize - Workers::ReceiveEncryptedSalmon.new.perform(@user.id, generate_retraction(entity_name, target_object, sender)) + Workers::ReceiveEncryptedSalmon.new.perform(alice.id, generate_retraction(entity_name, target_object, sender)) expect(target_klass.exists?(guid: target_object.guid)).to be(false) end it "doesn't retract object when retraction has wrong signatures" do target_klass = target_object.class.to_s.constantize - Workers::ReceiveEncryptedSalmon.new.perform( - @user.id, - generate_forged_retraction(entity_name, target_object, sender) - ) + + allow(sender).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024)) + + Workers::ReceiveEncryptedSalmon.new.perform(alice.id, generate_retraction(entity_name, target_object, sender)) expect(target_klass.exists?(guid: target_object.guid)).to be(true) end