diff --git a/lib/diaspora_federation.rb b/lib/diaspora_federation.rb
index 1563793..ea23223 100644
--- a/lib/diaspora_federation.rb
+++ b/lib/diaspora_federation.rb
@@ -29,7 +29,7 @@ module DiasporaFederation
fetch_entity_author_id_by_guid
queue_public_receive
queue_private_receive
- save_entity_after_receive
+ receive_entity
fetch_public_entity
fetch_person_url_to
update_pod
@@ -167,9 +167,11 @@ module DiasporaFederation
# @param [Boolean] legacy true if it is a legacy salmon slap, false if it is a encrypted magic envelope json
# @return [Boolean] true if successful, false if the user was not found
#
- # save_entity_after_receive
+ # receive_entity
# After the xml was parsed and processed the gem calls this callback to persist the entity
# @param [DiasporaFederation::Entity] entity the received entity after processing
+ # @param [Object] recipient_id identifier for the recipient of private messages or nil for public,
+ # see {Receiver.receive_private}
#
# fetch_public_entity
# fetch a public entity from the database
diff --git a/lib/diaspora_federation/federation/fetcher.rb b/lib/diaspora_federation/federation/fetcher.rb
index 4501edb..a985af2 100644
--- a/lib/diaspora_federation/federation/fetcher.rb
+++ b/lib/diaspora_federation/federation/fetcher.rb
@@ -13,7 +13,7 @@ module DiasporaFederation
magic_env = Nokogiri::XML::Document.parse(response.body).root
entity = Salmon::MagicEnvelope.unenvelop(magic_env)
- DiasporaFederation.callbacks.trigger(:save_entity_after_receive, entity)
+ DiasporaFederation.callbacks.trigger(:receive_entity, entity)
rescue => e
raise NotFetchable, "Failed to fetch #{entity_type}:#{guid} from #{author}: #{e.class}: #{e.message}"
end
diff --git a/lib/diaspora_federation/federation/receiver.rb b/lib/diaspora_federation/federation/receiver.rb
index d0975a6..d4fb3e6 100644
--- a/lib/diaspora_federation/federation/receiver.rb
+++ b/lib/diaspora_federation/federation/receiver.rb
@@ -1,6 +1,36 @@
module DiasporaFederation
module Federation
+ # this module is for parse and receive entities.
module Receiver
+ # receive a public message
+ # @param [String] data message to receive
+ # @param [Boolean] legacy use old slap parser
+ def self.receive_public(data, legacy=false)
+ receiver = legacy ? PublicSlapReceiver.new(data) : MagicEnvelopeReceiver.new(data)
+ receive(receiver)
+ end
+
+ # receive a private message
+ # @param [String] data message to receive
+ # @param [OpenSSL::PKey::RSA] recipient_private_key recipient private key to decrypt the message
+ # @param [Object] recipient_id the identifier to persist the entity for the correct user,
+ # see +receive_entity+ callback
+ # @param [Boolean] legacy use old slap parser
+ def self.receive_private(data, recipient_private_key, recipient_id, legacy=false)
+ raise ArgumentError, "no recipient key provided" unless recipient_private_key.instance_of?(OpenSSL::PKey::RSA)
+ receiver = if legacy
+ PrivateSlapReceiver.new(data, recipient_private_key)
+ else
+ EncryptedMagicEnvelopeReceiver.new(data, recipient_private_key)
+ end
+ receive(receiver, recipient_id)
+ end
+
+ def self.receive(receiver, recipient_id=nil)
+ entity = receiver.parse
+ DiasporaFederation.callbacks.trigger(:receive_entity, entity, recipient_id)
+ end
+ private_class_method :receive
end
end
end
@@ -8,3 +38,5 @@ end
require "diaspora_federation/federation/receiver/slap_receiver"
require "diaspora_federation/federation/receiver/private_slap_receiver"
require "diaspora_federation/federation/receiver/public_slap_receiver"
+require "diaspora_federation/federation/receiver/magic_envelope_receiver"
+require "diaspora_federation/federation/receiver/encrypted_magic_envelope_receiver"
diff --git a/lib/diaspora_federation/federation/receiver/encrypted_magic_envelope_receiver.rb b/lib/diaspora_federation/federation/receiver/encrypted_magic_envelope_receiver.rb
new file mode 100644
index 0000000..7eb6142
--- /dev/null
+++ b/lib/diaspora_federation/federation/receiver/encrypted_magic_envelope_receiver.rb
@@ -0,0 +1,24 @@
+module DiasporaFederation
+ module Federation
+ module Receiver
+ # Receiver for an encrypted magic envelope
+ #
+ # @see Salmon::EncryptedMagicEnvelope
+ class EncryptedMagicEnvelopeReceiver < MagicEnvelopeReceiver
+ # create a new receiver for an encrypted magic envelope
+ # @param [String] data the encrypted json with magic envelope xml
+ # @param [OpenSSL::PKey::RSA] recipient_private_key recipient private key to decrypt the message
+ def initialize(data, recipient_private_key)
+ super(data)
+ @recipient_private_key = recipient_private_key
+ end
+
+ protected
+
+ def magic_env_xml
+ Salmon::EncryptedMagicEnvelope.decrypt(@data, @recipient_private_key)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/diaspora_federation/federation/receiver/magic_envelope_receiver.rb b/lib/diaspora_federation/federation/receiver/magic_envelope_receiver.rb
new file mode 100644
index 0000000..1a40762
--- /dev/null
+++ b/lib/diaspora_federation/federation/receiver/magic_envelope_receiver.rb
@@ -0,0 +1,28 @@
+module DiasporaFederation
+ module Federation
+ module Receiver
+ # Receiver for a magic envelope
+ #
+ # @see Salmon::MagicEnvelope
+ class MagicEnvelopeReceiver
+ # create a new receiver for a magic envelope
+ # @param [String] data the message magic envelope xml
+ def initialize(data)
+ @data = data
+ end
+
+ # parse the magic envelope and create the entity
+ # @return [Entity] the parsed entity
+ def parse
+ Salmon::MagicEnvelope.unenvelop(magic_env_xml)
+ end
+
+ protected
+
+ def magic_env_xml
+ Nokogiri::XML::Document.parse(@data).root
+ end
+ end
+ end
+ end
+end
diff --git a/lib/diaspora_federation/federation/receiver/private_slap_receiver.rb b/lib/diaspora_federation/federation/receiver/private_slap_receiver.rb
index 3f309ee..8c2246d 100644
--- a/lib/diaspora_federation/federation/receiver/private_slap_receiver.rb
+++ b/lib/diaspora_federation/federation/receiver/private_slap_receiver.rb
@@ -10,7 +10,6 @@ module DiasporaFederation
# @param [OpenSSL::PKey::RSA] recipient_private_key recipient private key to decrypt the message
def initialize(slap_xml, recipient_private_key)
super(slap_xml)
- raise ArgumentError, "no recipient key provided" unless recipient_private_key.instance_of?(OpenSSL::PKey::RSA)
@recipient_private_key = recipient_private_key
end
diff --git a/lib/diaspora_federation/federation/receiver/slap_receiver.rb b/lib/diaspora_federation/federation/receiver/slap_receiver.rb
index 0206a44..76cdb38 100644
--- a/lib/diaspora_federation/federation/receiver/slap_receiver.rb
+++ b/lib/diaspora_federation/federation/receiver/slap_receiver.rb
@@ -12,12 +12,12 @@ module DiasporaFederation
@slap_xml = slap_xml
end
- # Parse the salmon xml and send it to the +:save_entity_after_receive+ callback
- def receive!
+ # Parse the salmon xml
+ def parse
sender_id = slap.author_id
public_key = DiasporaFederation.callbacks.trigger(:fetch_public_key_by_diaspora_id, sender_id)
raise Salmon::SenderKeyNotFound if public_key.nil?
- DiasporaFederation.callbacks.trigger(:save_entity_after_receive, slap.entity(public_key))
+ slap.entity(public_key)
end
end
end
diff --git a/spec/lib/diaspora_federation/federation/fetcher_spec.rb b/spec/lib/diaspora_federation/federation/fetcher_spec.rb
index d9bfe6b..1070107 100644
--- a/spec/lib/diaspora_federation/federation/fetcher_spec.rb
+++ b/spec/lib/diaspora_federation/federation/fetcher_spec.rb
@@ -15,7 +15,7 @@ module DiasporaFederation
:fetch_public_key_by_diaspora_id, post.author
).and_return(alice.public_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
- :save_entity_after_receive, kind_of(Entities::StatusMessage)
+ :receive_entity, kind_of(Entities::StatusMessage)
) do |_, entity|
expect(entity.guid).to eq(post.guid)
expect(entity.author).to eq(post.author)
@@ -39,7 +39,7 @@ module DiasporaFederation
:fetch_public_key_by_diaspora_id, post.author
).and_return(alice.public_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
- :save_entity_after_receive, kind_of(Entities::StatusMessage)
+ :receive_entity, kind_of(Entities::StatusMessage)
)
Federation::Fetcher.fetch_public(post.author, :post, post.guid)
diff --git a/spec/lib/diaspora_federation/federation/receiver/encrypted_magic_envelope_receiver_spec.rb b/spec/lib/diaspora_federation/federation/receiver/encrypted_magic_envelope_receiver_spec.rb
new file mode 100644
index 0000000..01fc7fc
--- /dev/null
+++ b/spec/lib/diaspora_federation/federation/receiver/encrypted_magic_envelope_receiver_spec.rb
@@ -0,0 +1,21 @@
+module DiasporaFederation
+ describe Federation::Receiver::EncryptedMagicEnvelopeReceiver do
+ let(:sender_id) { FactoryGirl.generate(:diaspora_id) }
+ let(:sender_key) { OpenSSL::PKey::RSA.generate(1024) }
+ let(:recipient_key) { OpenSSL::PKey::RSA.generate(1024) }
+ let(:entity) { FactoryGirl.build(:status_message_entity, public: false) }
+ let(:magic_env) { Salmon::MagicEnvelope.new(entity).envelop(sender_key, sender_id) }
+ let(:data) { Salmon::EncryptedMagicEnvelope.encrypt(magic_env, recipient_key.public_key) }
+
+ it "parses the entity if everything is fine" do
+ expect(DiasporaFederation.callbacks).to receive(:trigger).with(
+ :fetch_public_key_by_diaspora_id, sender_id
+ ).and_return(sender_key)
+
+ parsed_entity = described_class.new(data, recipient_key).parse
+ expect(parsed_entity).to be_a(Entities::StatusMessage)
+ expect(parsed_entity.guid).to eq(entity.guid)
+ expect(parsed_entity.public).to eq("false")
+ end
+ end
+end
diff --git a/spec/lib/diaspora_federation/federation/receiver/magic_envelope_receiver_spec.rb b/spec/lib/diaspora_federation/federation/receiver/magic_envelope_receiver_spec.rb
new file mode 100644
index 0000000..bf98b1f
--- /dev/null
+++ b/spec/lib/diaspora_federation/federation/receiver/magic_envelope_receiver_spec.rb
@@ -0,0 +1,19 @@
+module DiasporaFederation
+ describe Federation::Receiver::MagicEnvelopeReceiver do
+ let(:sender_id) { FactoryGirl.generate(:diaspora_id) }
+ let(:sender_key) { OpenSSL::PKey::RSA.generate(1024) }
+ let(:entity) { FactoryGirl.build(:status_message_entity) }
+ let(:data) { Salmon::MagicEnvelope.new(entity).envelop(sender_key, sender_id).to_xml }
+
+ it "parses the entity if everything is fine" do
+ expect(DiasporaFederation.callbacks).to receive(:trigger).with(
+ :fetch_public_key_by_diaspora_id, sender_id
+ ).and_return(sender_key)
+
+ parsed_entity = described_class.new(data).parse
+ expect(parsed_entity).to be_a(Entities::StatusMessage)
+ expect(parsed_entity.guid).to eq(entity.guid)
+ expect(parsed_entity.public).to eq("true")
+ end
+ end
+end
diff --git a/spec/lib/diaspora_federation/federation/receiver/private_slap_receiver_spec.rb b/spec/lib/diaspora_federation/federation/receiver/private_slap_receiver_spec.rb
index 6273fbb..9435fe6 100644
--- a/spec/lib/diaspora_federation/federation/receiver/private_slap_receiver_spec.rb
+++ b/spec/lib/diaspora_federation/federation/receiver/private_slap_receiver_spec.rb
@@ -3,19 +3,20 @@ module DiasporaFederation
let(:sender_id) { FactoryGirl.generate(:diaspora_id) }
let(:sender_key) { OpenSSL::PKey::RSA.generate(1024) }
let(:recipient_key) { OpenSSL::PKey::RSA.generate(1024) }
+ let(:entity) { FactoryGirl.build(:status_message_entity, public: false) }
let(:xml) {
- DiasporaFederation::Salmon::EncryptedSlap.prepare(sender_id, sender_key, FactoryGirl.build(:request_entity))
- .generate_xml(recipient_key)
+ DiasporaFederation::Salmon::EncryptedSlap.prepare(sender_id, sender_key, entity).generate_xml(recipient_key)
}
- it "calls save_entity_after_receive if everything is fine" do
+ it "parses the entity if everything is fine" do
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_public_key_by_diaspora_id, sender_id
).and_return(sender_key)
- expect(DiasporaFederation.callbacks).to receive(:trigger).with(:save_entity_after_receive, kind_of(Entity))
-
- described_class.new(xml, recipient_key).receive!
+ parsed_entity = described_class.new(xml, recipient_key).parse
+ expect(parsed_entity).to be_a(Entities::StatusMessage)
+ expect(parsed_entity.guid).to eq(entity.guid)
+ expect(parsed_entity.public).to eq("false")
end
it "raises when sender public key is not available" do
@@ -24,19 +25,13 @@ module DiasporaFederation
).and_return(nil)
expect {
- described_class.new(xml, recipient_key).receive!
+ described_class.new(xml, recipient_key).parse
}.to raise_error Salmon::SenderKeyNotFound
end
- it "raises when recipient private key is not available" do
- expect {
- described_class.new(xml, nil).receive!
- }.to raise_error ArgumentError, "no recipient key provided"
- end
-
it "raises when bad xml was supplied" do
expect {
- described_class.new("", recipient_key).receive!
+ described_class.new("", recipient_key).parse
}.to raise_error Salmon::MissingHeader
end
end
diff --git a/spec/lib/diaspora_federation/federation/receiver/public_slap_receiver_spec.rb b/spec/lib/diaspora_federation/federation/receiver/public_slap_receiver_spec.rb
index 18b249a..e80a1e6 100644
--- a/spec/lib/diaspora_federation/federation/receiver/public_slap_receiver_spec.rb
+++ b/spec/lib/diaspora_federation/federation/receiver/public_slap_receiver_spec.rb
@@ -2,22 +2,18 @@ module DiasporaFederation
describe Federation::Receiver::PublicSlapReceiver do
let(:sender_id) { FactoryGirl.generate(:diaspora_id) }
let(:sender_key) { OpenSSL::PKey::RSA.generate(1024) }
- let(:xml) {
- DiasporaFederation::Salmon::Slap.generate_xml(
- sender_id,
- sender_key,
- FactoryGirl.build(:request_entity)
- )
- }
+ let(:entity) { FactoryGirl.build(:status_message_entity) }
+ let(:xml) { DiasporaFederation::Salmon::Slap.generate_xml(sender_id, sender_key, entity) }
- it "calls save_entity_after_receive if everything is fine" do
+ it "parses the entity if everything is fine" do
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_public_key_by_diaspora_id, sender_id
).and_return(sender_key)
- expect(DiasporaFederation.callbacks).to receive(:trigger).with(:save_entity_after_receive, kind_of(Entity))
-
- described_class.new(xml).receive!
+ parsed_entity = described_class.new(xml).parse
+ expect(parsed_entity).to be_a(Entities::StatusMessage)
+ expect(parsed_entity.guid).to eq(entity.guid)
+ expect(parsed_entity.public).to eq("true")
end
it "raises when sender public key is not available" do
@@ -26,13 +22,13 @@ module DiasporaFederation
).and_return(nil)
expect {
- described_class.new(xml).receive!
+ described_class.new(xml).parse
}.to raise_error Salmon::SenderKeyNotFound
end
it "raises when bad xml was supplied" do
expect {
- described_class.new("").receive!
+ described_class.new("").parse
}.to raise_error Salmon::MissingAuthor
end
end
diff --git a/spec/lib/diaspora_federation/federation/receiver_spec.rb b/spec/lib/diaspora_federation/federation/receiver_spec.rb
new file mode 100644
index 0000000..9a999fd
--- /dev/null
+++ b/spec/lib/diaspora_federation/federation/receiver_spec.rb
@@ -0,0 +1,102 @@
+module DiasporaFederation
+ describe Federation::Receiver do
+ let(:sender_id) { FactoryGirl.generate(:diaspora_id) }
+ let(:sender_key) { OpenSSL::PKey::RSA.generate(1024) }
+ let(:recipient_key) { OpenSSL::PKey::RSA.generate(1024) }
+
+ describe ".receive_public" do
+ let(:post) { FactoryGirl.build(:status_message_entity) }
+
+ it "parses the entity with magic envelope receiver" do
+ expect(DiasporaFederation.callbacks).to receive(:trigger).with(
+ :fetch_public_key_by_diaspora_id, sender_id
+ ).and_return(sender_key)
+
+ data = Salmon::MagicEnvelope.new(post).envelop(sender_key, sender_id).to_xml
+
+ expect(DiasporaFederation.callbacks).to receive(:trigger).with(
+ :receive_entity, kind_of(Entities::StatusMessage), nil
+ ) do |_, entity|
+ expect(entity.guid).to eq(post.guid)
+ expect(entity.author).to eq(post.author)
+ expect(entity.raw_message).to eq(post.raw_message)
+ expect(entity.public).to eq("true")
+ end
+
+ described_class.receive_public(data)
+ end
+
+ it "parses the entity with legacy slap receiver" do
+ expect(DiasporaFederation.callbacks).to receive(:trigger).with(
+ :fetch_public_key_by_diaspora_id, sender_id
+ ).and_return(sender_key)
+
+ data = DiasporaFederation::Salmon::Slap.generate_xml(sender_id, sender_key, post)
+
+ expect(DiasporaFederation.callbacks).to receive(:trigger).with(
+ :receive_entity, kind_of(Entities::StatusMessage), nil
+ ) do |_, entity|
+ expect(entity.guid).to eq(post.guid)
+ expect(entity.author).to eq(post.author)
+ expect(entity.raw_message).to eq(post.raw_message)
+ expect(entity.public).to eq("true")
+ end
+
+ described_class.receive_public(data, true)
+ end
+ end
+
+ describe ".receive_private" do
+ let(:post) { FactoryGirl.build(:status_message_entity, public: false) }
+
+ it "parses the entity with magic envelope receiver" do
+ expect(DiasporaFederation.callbacks).to receive(:trigger).with(
+ :fetch_public_key_by_diaspora_id, sender_id
+ ).and_return(sender_key)
+
+ magic_env = Salmon::MagicEnvelope.new(post).envelop(sender_key, sender_id)
+ data = Salmon::EncryptedMagicEnvelope.encrypt(magic_env, recipient_key.public_key)
+
+ expect(DiasporaFederation.callbacks).to receive(:trigger).with(
+ :receive_entity, kind_of(Entities::StatusMessage), 1234
+ ) do |_, entity|
+ expect(entity.guid).to eq(post.guid)
+ expect(entity.author).to eq(post.author)
+ expect(entity.raw_message).to eq(post.raw_message)
+ expect(entity.public).to eq("false")
+ end
+
+ described_class.receive_private(data, recipient_key, 1234)
+ end
+
+ it "parses the entity with legacy slap receiver" do
+ expect(DiasporaFederation.callbacks).to receive(:trigger).with(
+ :fetch_public_key_by_diaspora_id, sender_id
+ ).and_return(sender_key)
+
+ data = DiasporaFederation::Salmon::EncryptedSlap.prepare(sender_id, sender_key, post)
+ .generate_xml(recipient_key)
+
+ expect(DiasporaFederation.callbacks).to receive(:trigger).with(
+ :receive_entity, kind_of(Entities::StatusMessage), 1234
+ ) do |_, entity|
+ expect(entity.guid).to eq(post.guid)
+ expect(entity.author).to eq(post.author)
+ expect(entity.raw_message).to eq(post.raw_message)
+ expect(entity.public).to eq("false")
+ end
+
+ described_class.receive_private(data, recipient_key, 1234, true)
+ end
+
+ it "raises when recipient private key is not available" do
+ magic_env = Salmon::MagicEnvelope.new(post).envelop(sender_key, sender_id)
+ data = Salmon::EncryptedMagicEnvelope.encrypt(magic_env, recipient_key.public_key)
+
+ expect {
+ described_class.receive_private(data, nil, 1234)
+ }.to raise_error ArgumentError, "no recipient key provided"
+ end
+ end
+ end
+end
diff --git a/test/dummy/config/initializers/diaspora_federation.rb b/test/dummy/config/initializers/diaspora_federation.rb
index 963055c..47fcbbd 100644
--- a/test/dummy/config/initializers/diaspora_federation.rb
+++ b/test/dummy/config/initializers/diaspora_federation.rb
@@ -97,7 +97,7 @@ DiasporaFederation.configure do |config|
true
end
- on :save_entity_after_receive do
+ on :receive_entity do
end
on :fetch_public_entity do |entity_type, guid|