create public/private receiver

This commit is contained in:
Benjamin Neff 2016-03-21 01:01:55 +01:00
parent ca0a853134
commit 20675b941a
10 changed files with 171 additions and 40 deletions

View file

@ -13,7 +13,7 @@ module DiasporaFederation
magic_env_xml = Nokogiri::XML::Document.parse(response.body).root
magic_env = Salmon::MagicEnvelope.unenvelop(magic_env_xml)
DiasporaFederation.callbacks.trigger(:receive_entity, magic_env.payload)
Receiver::Public.new(magic_env).receive
rescue => e
raise NotFetchable, "Failed to fetch #{entity_type}:#{guid} from #{author}: #{e.class}: #{e.message}"
end

View file

@ -6,13 +6,13 @@ module DiasporaFederation
# @param [String] data message to receive
# @param [Boolean] legacy use old slap parser
def self.receive_public(data, legacy=false)
received_message = if legacy
Salmon::Slap.from_xml(data)
else
magic_env_xml = Nokogiri::XML::Document.parse(data).root
Salmon::MagicEnvelope.unenvelop(magic_env_xml)
end
receive(received_message)
magic_env = if legacy
Salmon::Slap.from_xml(data)
else
magic_env_xml = Nokogiri::XML::Document.parse(data).root
Salmon::MagicEnvelope.unenvelop(magic_env_xml)
end
Public.new(magic_env).receive
end
# receive a private message
@ -23,19 +23,19 @@ module DiasporaFederation
# @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)
received_message = if legacy
Salmon::EncryptedSlap.from_xml(data, recipient_private_key)
else
magic_env_xml = Salmon::EncryptedMagicEnvelope.decrypt(data, recipient_private_key)
Salmon::MagicEnvelope.unenvelop(magic_env_xml)
end
receive(received_message, recipient_id)
magic_env = if legacy
Salmon::EncryptedSlap.from_xml(data, recipient_private_key)
else
magic_env_xml = Salmon::EncryptedMagicEnvelope.decrypt(data, recipient_private_key)
Salmon::MagicEnvelope.unenvelop(magic_env_xml)
end
Private.new(magic_env, recipient_id).receive
end
def self.receive(received_message, recipient_id=nil)
DiasporaFederation.callbacks.trigger(:receive_entity, received_message.payload, recipient_id)
end
private_class_method :receive
end
end
end
require "diaspora_federation/federation/receiver/exceptions"
require "diaspora_federation/federation/receiver/abstract_receiver"
require "diaspora_federation/federation/receiver/public"
require "diaspora_federation/federation/receiver/private"

View file

@ -0,0 +1,35 @@
module DiasporaFederation
module Federation
module Receiver
# common functionality for receivers
class AbstractReceiver
# create a new receiver
# @param [MagicEnvelope] magic_envelope the received magic envelope
# @param [Object] recipient_id the identifier of the recipient of a private message
def initialize(magic_envelope, recipient_id=nil)
@entity = magic_envelope.payload
@sender = magic_envelope.sender
@recipient_id = recipient_id
end
# validate and receive the entity
def receive
validate
DiasporaFederation.callbacks.trigger(:receive_entity, entity, recipient_id)
end
private
attr_reader :entity, :sender, :recipient_id
def validate
raise InvalidSender unless sender_valid?
end
def sender_valid?
sender == entity.author # TODO: handle sender of relayables
end
end
end
end
end

View file

@ -0,0 +1,13 @@
module DiasporaFederation
module Federation
module Receiver
# Raised, if the sender of the {Salmon::MagicEnvelope} is not allowed to send the entity.
class InvalidSender < RuntimeError
end
# Raised, if receiving a private message without recipient.
class RecipientRequired < RuntimeError
end
end
end
end

View file

@ -0,0 +1,15 @@
module DiasporaFederation
module Federation
module Receiver
# receiver for private entities
class Private < AbstractReceiver
private
def validate
raise RecipientRequired if recipient_id.nil?
super
end
end
end
end
end

View file

@ -0,0 +1,9 @@
module DiasporaFederation
module Federation
module Receiver
# receiver for public entities
class Public < AbstractReceiver
end
end
end
end

View file

@ -14,14 +14,18 @@ module DiasporaFederation
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_public_key_by_diaspora_id, post.author
).and_return(alice.public_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:receive_entity, kind_of(Entities::StatusMessage)
) 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")
receiver = double
expect(Federation::Receiver::Public).to receive(:new).with(
kind_of(Salmon::MagicEnvelope)
) do |magic_env|
expect(magic_env.payload.guid).to eq(post.guid)
expect(magic_env.payload.author).to eq(post.author)
expect(magic_env.payload.raw_message).to eq(post.raw_message)
expect(magic_env.payload.public).to eq("true")
receiver
end
expect(receiver).to receive(:receive)
Federation::Fetcher.fetch_public(post.author, :post, post.guid)
end
@ -38,9 +42,12 @@ module DiasporaFederation
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_public_key_by_diaspora_id, post.author
).and_return(alice.public_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:receive_entity, kind_of(Entities::StatusMessage)
)
receiver = double
expect(Federation::Receiver::Public).to receive(:new).with(
kind_of(Salmon::MagicEnvelope)
).and_return(receiver)
expect(receiver).to receive(:receive)
Federation::Fetcher.fetch_public(post.author, :post, post.guid)
end

View file

@ -0,0 +1,30 @@
module DiasporaFederation
describe Federation::Receiver::Private do
let(:recipient) { 42 }
let(:entity) { FactoryGirl.build(:status_message_entity, public: false) }
let(:magic_env) { Salmon::MagicEnvelope.new(entity, entity.author) }
describe "#receive" do
it "receives a private post" do
expect(DiasporaFederation.callbacks).to receive(:trigger).with(:receive_entity, entity, recipient)
described_class.new(magic_env, recipient).receive
end
it "validates the sender" do
sender = FactoryGirl.generate(:diaspora_id)
bad_env = Salmon::MagicEnvelope.new(entity, sender)
expect {
described_class.new(bad_env, recipient).receive
}.to raise_error Federation::Receiver::InvalidSender
end
it "validates the recipient" do
expect {
described_class.new(magic_env).receive
}.to raise_error Federation::Receiver::RecipientRequired
end
end
end
end

View file

@ -0,0 +1,23 @@
module DiasporaFederation
describe Federation::Receiver::Public do
let(:entity) { FactoryGirl.build(:status_message_entity) }
let(:magic_env) { Salmon::MagicEnvelope.new(entity, entity.author) }
describe "#receive" do
it "receives a public post" do
expect(DiasporaFederation.callbacks).to receive(:trigger).with(:receive_entity, entity, nil)
described_class.new(magic_env).receive
end
it "validates the sender" do
sender = FactoryGirl.generate(:diaspora_id)
bad_env = Salmon::MagicEnvelope.new(entity, sender)
expect {
described_class.new(bad_env).receive
}.to raise_error Federation::Receiver::InvalidSender
end
end
end
end

View file

@ -1,6 +1,5 @@
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) }
@ -9,10 +8,10 @@ module DiasporaFederation
it "parses the entity with magic envelope receiver" do
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_public_key_by_diaspora_id, sender_id
:fetch_public_key_by_diaspora_id, post.author
).and_return(sender_key)
data = Salmon::MagicEnvelope.new(post, sender_id).envelop(sender_key).to_xml
data = Salmon::MagicEnvelope.new(post, post.author).envelop(sender_key).to_xml
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:receive_entity, kind_of(Entities::StatusMessage), nil
@ -28,10 +27,10 @@ module DiasporaFederation
it "parses the entity with legacy slap receiver" do
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_public_key_by_diaspora_id, sender_id
:fetch_public_key_by_diaspora_id, post.author
).and_return(sender_key)
data = DiasporaFederation::Salmon::Slap.generate_xml(sender_id, sender_key, post)
data = DiasporaFederation::Salmon::Slap.generate_xml(post.author, sender_key, post)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:receive_entity, kind_of(Entities::StatusMessage), nil
@ -51,10 +50,10 @@ module DiasporaFederation
it "parses the entity with magic envelope receiver" do
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_public_key_by_diaspora_id, sender_id
:fetch_public_key_by_diaspora_id, post.author
).and_return(sender_key)
magic_env = Salmon::MagicEnvelope.new(post, sender_id).envelop(sender_key)
magic_env = Salmon::MagicEnvelope.new(post, post.author).envelop(sender_key)
data = Salmon::EncryptedMagicEnvelope.encrypt(magic_env, recipient_key.public_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
@ -71,10 +70,10 @@ module DiasporaFederation
it "parses the entity with legacy slap receiver" do
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_public_key_by_diaspora_id, sender_id
:fetch_public_key_by_diaspora_id, post.author
).and_return(sender_key)
data = DiasporaFederation::Salmon::EncryptedSlap.prepare(sender_id, sender_key, post)
data = DiasporaFederation::Salmon::EncryptedSlap.prepare(post.author, sender_key, post)
.generate_xml(recipient_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
@ -90,7 +89,7 @@ module DiasporaFederation
end
it "raises when recipient private key is not available" do
magic_env = Salmon::MagicEnvelope.new(post, sender_id).envelop(sender_key)
magic_env = Salmon::MagicEnvelope.new(post, post.author).envelop(sender_key)
data = Salmon::EncryptedMagicEnvelope.encrypt(magic_env, recipient_key.public_key)
expect {