create public/private receiver
This commit is contained in:
parent
ca0a853134
commit
20675b941a
10 changed files with 171 additions and 40 deletions
|
|
@ -13,7 +13,7 @@ module DiasporaFederation
|
||||||
|
|
||||||
magic_env_xml = Nokogiri::XML::Document.parse(response.body).root
|
magic_env_xml = Nokogiri::XML::Document.parse(response.body).root
|
||||||
magic_env = Salmon::MagicEnvelope.unenvelop(magic_env_xml)
|
magic_env = Salmon::MagicEnvelope.unenvelop(magic_env_xml)
|
||||||
DiasporaFederation.callbacks.trigger(:receive_entity, magic_env.payload)
|
Receiver::Public.new(magic_env).receive
|
||||||
rescue => e
|
rescue => e
|
||||||
raise NotFetchable, "Failed to fetch #{entity_type}:#{guid} from #{author}: #{e.class}: #{e.message}"
|
raise NotFetchable, "Failed to fetch #{entity_type}:#{guid} from #{author}: #{e.class}: #{e.message}"
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,13 @@ module DiasporaFederation
|
||||||
# @param [String] data message to receive
|
# @param [String] data message to receive
|
||||||
# @param [Boolean] legacy use old slap parser
|
# @param [Boolean] legacy use old slap parser
|
||||||
def self.receive_public(data, legacy=false)
|
def self.receive_public(data, legacy=false)
|
||||||
received_message = if legacy
|
magic_env = if legacy
|
||||||
Salmon::Slap.from_xml(data)
|
Salmon::Slap.from_xml(data)
|
||||||
else
|
else
|
||||||
magic_env_xml = Nokogiri::XML::Document.parse(data).root
|
magic_env_xml = Nokogiri::XML::Document.parse(data).root
|
||||||
Salmon::MagicEnvelope.unenvelop(magic_env_xml)
|
Salmon::MagicEnvelope.unenvelop(magic_env_xml)
|
||||||
end
|
end
|
||||||
receive(received_message)
|
Public.new(magic_env).receive
|
||||||
end
|
end
|
||||||
|
|
||||||
# receive a private message
|
# receive a private message
|
||||||
|
|
@ -23,19 +23,19 @@ module DiasporaFederation
|
||||||
# @param [Boolean] legacy use old slap parser
|
# @param [Boolean] legacy use old slap parser
|
||||||
def self.receive_private(data, recipient_private_key, recipient_id, legacy=false)
|
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)
|
raise ArgumentError, "no recipient key provided" unless recipient_private_key.instance_of?(OpenSSL::PKey::RSA)
|
||||||
received_message = if legacy
|
magic_env = if legacy
|
||||||
Salmon::EncryptedSlap.from_xml(data, recipient_private_key)
|
Salmon::EncryptedSlap.from_xml(data, recipient_private_key)
|
||||||
else
|
else
|
||||||
magic_env_xml = Salmon::EncryptedMagicEnvelope.decrypt(data, recipient_private_key)
|
magic_env_xml = Salmon::EncryptedMagicEnvelope.decrypt(data, recipient_private_key)
|
||||||
Salmon::MagicEnvelope.unenvelop(magic_env_xml)
|
Salmon::MagicEnvelope.unenvelop(magic_env_xml)
|
||||||
end
|
end
|
||||||
receive(received_message, recipient_id)
|
Private.new(magic_env, recipient_id).receive
|
||||||
end
|
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
|
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"
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
13
lib/diaspora_federation/federation/receiver/exceptions.rb
Normal file
13
lib/diaspora_federation/federation/receiver/exceptions.rb
Normal 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
|
||||||
15
lib/diaspora_federation/federation/receiver/private.rb
Normal file
15
lib/diaspora_federation/federation/receiver/private.rb
Normal 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
|
||||||
9
lib/diaspora_federation/federation/receiver/public.rb
Normal file
9
lib/diaspora_federation/federation/receiver/public.rb
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
module DiasporaFederation
|
||||||
|
module Federation
|
||||||
|
module Receiver
|
||||||
|
# receiver for public entities
|
||||||
|
class Public < AbstractReceiver
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -14,14 +14,18 @@ module DiasporaFederation
|
||||||
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
|
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
|
||||||
:fetch_public_key_by_diaspora_id, post.author
|
:fetch_public_key_by_diaspora_id, post.author
|
||||||
).and_return(alice.public_key)
|
).and_return(alice.public_key)
|
||||||
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
|
|
||||||
:receive_entity, kind_of(Entities::StatusMessage)
|
receiver = double
|
||||||
) do |_, entity|
|
expect(Federation::Receiver::Public).to receive(:new).with(
|
||||||
expect(entity.guid).to eq(post.guid)
|
kind_of(Salmon::MagicEnvelope)
|
||||||
expect(entity.author).to eq(post.author)
|
) do |magic_env|
|
||||||
expect(entity.raw_message).to eq(post.raw_message)
|
expect(magic_env.payload.guid).to eq(post.guid)
|
||||||
expect(entity.public).to eq("true")
|
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
|
end
|
||||||
|
expect(receiver).to receive(:receive)
|
||||||
|
|
||||||
Federation::Fetcher.fetch_public(post.author, :post, post.guid)
|
Federation::Fetcher.fetch_public(post.author, :post, post.guid)
|
||||||
end
|
end
|
||||||
|
|
@ -38,9 +42,12 @@ module DiasporaFederation
|
||||||
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
|
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
|
||||||
:fetch_public_key_by_diaspora_id, post.author
|
:fetch_public_key_by_diaspora_id, post.author
|
||||||
).and_return(alice.public_key)
|
).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)
|
Federation::Fetcher.fetch_public(post.author, :post, post.guid)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
module DiasporaFederation
|
module DiasporaFederation
|
||||||
describe Federation::Receiver do
|
describe Federation::Receiver do
|
||||||
let(:sender_id) { FactoryGirl.generate(:diaspora_id) }
|
|
||||||
let(:sender_key) { OpenSSL::PKey::RSA.generate(1024) }
|
let(:sender_key) { OpenSSL::PKey::RSA.generate(1024) }
|
||||||
let(:recipient_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
|
it "parses the entity with magic envelope receiver" do
|
||||||
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
|
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)
|
).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(
|
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
|
||||||
:receive_entity, kind_of(Entities::StatusMessage), nil
|
:receive_entity, kind_of(Entities::StatusMessage), nil
|
||||||
|
|
@ -28,10 +27,10 @@ module DiasporaFederation
|
||||||
|
|
||||||
it "parses the entity with legacy slap receiver" do
|
it "parses the entity with legacy slap receiver" do
|
||||||
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
|
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)
|
).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(
|
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
|
||||||
:receive_entity, kind_of(Entities::StatusMessage), nil
|
:receive_entity, kind_of(Entities::StatusMessage), nil
|
||||||
|
|
@ -51,10 +50,10 @@ module DiasporaFederation
|
||||||
|
|
||||||
it "parses the entity with magic envelope receiver" do
|
it "parses the entity with magic envelope receiver" do
|
||||||
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
|
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)
|
).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)
|
data = Salmon::EncryptedMagicEnvelope.encrypt(magic_env, recipient_key.public_key)
|
||||||
|
|
||||||
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
|
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
|
||||||
|
|
@ -71,10 +70,10 @@ module DiasporaFederation
|
||||||
|
|
||||||
it "parses the entity with legacy slap receiver" do
|
it "parses the entity with legacy slap receiver" do
|
||||||
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
|
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)
|
).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)
|
.generate_xml(recipient_key)
|
||||||
|
|
||||||
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
|
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
|
||||||
|
|
@ -90,7 +89,7 @@ module DiasporaFederation
|
||||||
end
|
end
|
||||||
|
|
||||||
it "raises when recipient private key is not available" do
|
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)
|
data = Salmon::EncryptedMagicEnvelope.encrypt(magic_env, recipient_key.public_key)
|
||||||
|
|
||||||
expect {
|
expect {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue