create receiver for new protocol and write tests
This commit is contained in:
parent
198e23ca65
commit
bd9cc67f5e
14 changed files with 255 additions and 37 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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("<XML/>", recipient_key).receive!
|
||||
described_class.new("<XML/>", recipient_key).parse
|
||||
}.to raise_error Salmon::MissingHeader
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -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("<XML/>").receive!
|
||||
described_class.new("<XML/>").parse
|
||||
}.to raise_error Salmon::MissingAuthor
|
||||
end
|
||||
end
|
||||
|
|
|
|||
102
spec/lib/diaspora_federation/federation/receiver_spec.rb
Normal file
102
spec/lib/diaspora_federation/federation/receiver_spec.rb
Normal file
|
|
@ -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
|
||||
|
|
@ -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|
|
||||
|
|
|
|||
Loading…
Reference in a new issue