Receiving entities support
This commit is contained in:
parent
6615e67d80
commit
5aac8c2423
11 changed files with 196 additions and 6 deletions
|
|
@ -1,4 +1,5 @@
|
|||
require_dependency "diaspora_federation/application_controller"
|
||||
require "diaspora_federation/receiver"
|
||||
|
||||
module DiasporaFederation
|
||||
# this controller processes receiving messages
|
||||
|
|
@ -11,6 +12,7 @@ module DiasporaFederation
|
|||
def public
|
||||
logger.info "received a public message"
|
||||
logger.debug CGI.unescape(params[:xml])
|
||||
Receiver::Public.new(CGI.unescape(params[:xml])).receive!
|
||||
render nothing: true, status: :ok
|
||||
end
|
||||
|
||||
|
|
@ -20,7 +22,12 @@ module DiasporaFederation
|
|||
def private
|
||||
logger.info "received a private message for #{params[:guid]}"
|
||||
logger.debug CGI.unescape(params[:xml])
|
||||
render nothing: true, status: :ok
|
||||
begin
|
||||
Receiver::Private.new(params[:guid], CGI.unescape(params[:xml])).receive!
|
||||
render nothing: true, status: :ok
|
||||
rescue RecipientNotFound
|
||||
render nothing: true, status: 404
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ require "diaspora_federation/entities"
|
|||
|
||||
require "diaspora_federation/discovery"
|
||||
require "diaspora_federation/salmon"
|
||||
require "diaspora_federation/receiver"
|
||||
|
||||
# diaspora* federation library
|
||||
module DiasporaFederation
|
||||
|
|
@ -22,11 +23,13 @@ module DiasporaFederation
|
|||
fetch_person_for_hcard
|
||||
save_person_after_webfinger
|
||||
fetch_private_key_by_diaspora_id
|
||||
fetch_private_key_by_user_guid
|
||||
fetch_author_private_key_by_entity_guid
|
||||
fetch_public_key_by_diaspora_id
|
||||
fetch_author_public_key_by_entity_guid
|
||||
entity_author_is_local?
|
||||
fetch_entity_author_id_by_guid
|
||||
entity_persist
|
||||
)
|
||||
|
||||
class << self
|
||||
|
|
|
|||
24
lib/diaspora_federation/receiver.rb
Normal file
24
lib/diaspora_federation/receiver.rb
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
module DiasporaFederation
|
||||
# SenderNotFound is raised when failed to fetch a public key of the sender of the received message
|
||||
class SenderNotFound < Exception
|
||||
end
|
||||
|
||||
# Common base for Private and Public receivers
|
||||
# @see Receiver::Public
|
||||
# @see Receiver::Private
|
||||
class Receiver
|
||||
def initialize(salmon_xml)
|
||||
@salmon_xml = salmon_xml
|
||||
end
|
||||
|
||||
def receive!
|
||||
sender_id = slap.author_id
|
||||
pkey = DiasporaFederation.callbacks.trigger(:fetch_public_key_by_diaspora_id, sender_id)
|
||||
raise SenderNotFound if pkey.nil?
|
||||
DiasporaFederation.callbacks.trigger(:entity_persist, slap.entity(pkey), @recipient_guid, sender_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require "diaspora_federation/receiver/private"
|
||||
require "diaspora_federation/receiver/public"
|
||||
24
lib/diaspora_federation/receiver/private.rb
Normal file
24
lib/diaspora_federation/receiver/private.rb
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
module DiasporaFederation
|
||||
# RecipientNotFound is raised when failed to fetch a private key of the recipient of the received message
|
||||
class RecipientNotFound < Exception
|
||||
end
|
||||
|
||||
class Receiver
|
||||
# Receiver::Private is used to receive private messages, which are addressed to a specific user, encrypted with his
|
||||
# public key and packed using Salmon::EncryptedSlap
|
||||
class Private < Receiver
|
||||
def initialize(recipient_guid, salmon_xml)
|
||||
super(salmon_xml)
|
||||
@recipient_guid = recipient_guid
|
||||
@recipient_private_key = DiasporaFederation.callbacks.trigger(:fetch_private_key_by_user_guid, recipient_guid)
|
||||
raise RecipientNotFound if @recipient_private_key.nil?
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def slap
|
||||
@salmon ||= Salmon::EncryptedSlap.from_xml(@salmon_xml, @recipient_private_key)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
13
lib/diaspora_federation/receiver/public.rb
Normal file
13
lib/diaspora_federation/receiver/public.rb
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
module DiasporaFederation
|
||||
class Receiver
|
||||
# Receiver::Public is used to receive public messages, which are not addressed to a specific user, unencrypted
|
||||
# and packed using Salmon::Slap
|
||||
class Public < Receiver
|
||||
protected
|
||||
|
||||
def slap
|
||||
@salmon ||= Salmon::Slap.from_xml(@salmon_xml)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
require "json"
|
||||
|
||||
module DiasporaFederation
|
||||
module Salmon
|
||||
# +EncryptedSlap+ provides class methods for generating and parsing encrypted
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
require "diaspora_federation"
|
||||
require "factory_girl"
|
||||
|
||||
FactoryGirl.define do
|
||||
|
|
|
|||
|
|
@ -3,27 +3,44 @@ module DiasporaFederation
|
|||
routes { DiasporaFederation::Engine.routes }
|
||||
|
||||
describe "POST #public" do
|
||||
it "succeeds" do
|
||||
post :public, xml: "<diaspora/>"
|
||||
expect(response).to be_success
|
||||
it "raises on an empty object" do
|
||||
expect { post :public, xml: "<diaspora/>" }.to raise_error(Salmon::MissingAuthor)
|
||||
end
|
||||
|
||||
it "returns a 422 if no xml is passed" do
|
||||
post :public
|
||||
expect(response.code).to eq("422")
|
||||
end
|
||||
|
||||
it "returns a 200 if receive! reports no errors" do
|
||||
expect_any_instance_of(Receiver::Public).to receive(:receive!)
|
||||
|
||||
post :public, xml: "<diaspora/>"
|
||||
expect(response.code).to eq("200")
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST #private" do
|
||||
it "succeeds" do
|
||||
it "return 404 for because of an unknown guid" do
|
||||
post :private, guid: "any-guid", xml: "<diaspora/>"
|
||||
expect(response).to be_success
|
||||
expect(response.code).to eq("404")
|
||||
end
|
||||
|
||||
it "returns a 422 if no xml is passed" do
|
||||
post :private, guid: "any-guid"
|
||||
expect(response.code).to eq("422")
|
||||
end
|
||||
|
||||
it "returns a 200 if receive! reports no errors" do
|
||||
expect(DiasporaFederation.callbacks).to receive(:trigger)
|
||||
.with(:fetch_private_key_by_user_guid, "any-guid")
|
||||
.once
|
||||
.and_return(true)
|
||||
expect_any_instance_of(Receiver::Private).to receive(:receive!)
|
||||
|
||||
post :private, guid: "any-guid", xml: "<diaspora/>"
|
||||
expect(response.code).to eq("200")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
57
spec/lib/diaspora_federation/receiver/private_spec.rb
Normal file
57
spec/lib/diaspora_federation/receiver/private_spec.rb
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
module DiasporaFederation
|
||||
describe Receiver::Private 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(:recipient_guid) { FactoryGirl.generate(:guid) }
|
||||
let(:xml) {
|
||||
DiasporaFederation::Salmon::EncryptedSlap.generate_xml(
|
||||
sender_id,
|
||||
sender_key,
|
||||
FactoryGirl.build(:request_entity),
|
||||
recipient_key
|
||||
)
|
||||
}
|
||||
|
||||
it "calls entity_persist if everyting 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(:fetch_private_key_by_user_guid, recipient_guid)
|
||||
.and_return(recipient_key)
|
||||
|
||||
expect(DiasporaFederation.callbacks).to receive(:trigger)
|
||||
.with(:entity_persist, kind_of(Entity), recipient_guid, sender_id)
|
||||
|
||||
described_class.new(recipient_guid, xml).receive!
|
||||
end
|
||||
|
||||
it "raises when sender public key is not available" do
|
||||
expect(DiasporaFederation.callbacks).to receive(:trigger)
|
||||
.with(:fetch_public_key_by_diaspora_id, sender_id)
|
||||
.and_return(nil)
|
||||
expect(DiasporaFederation.callbacks).to receive(:trigger)
|
||||
.with(:fetch_private_key_by_user_guid, recipient_guid)
|
||||
.and_return(recipient_key)
|
||||
|
||||
expect { described_class.new(recipient_guid, xml).receive! }.to raise_error SenderNotFound
|
||||
end
|
||||
|
||||
it "raises when recipient private key is not available" do
|
||||
expect(DiasporaFederation.callbacks).to receive(:trigger)
|
||||
.with(:fetch_private_key_by_user_guid, recipient_guid)
|
||||
.and_return(nil)
|
||||
|
||||
expect { described_class.new(recipient_guid, xml).receive! }.to raise_error RecipientNotFound
|
||||
end
|
||||
|
||||
it "raises when bad xml was supplied" do
|
||||
expect(DiasporaFederation.callbacks).to receive(:trigger)
|
||||
.with(:fetch_private_key_by_user_guid, recipient_guid)
|
||||
.and_return(recipient_key)
|
||||
|
||||
expect { described_class.new(recipient_guid, "<XML/>").receive! }.to raise_error Salmon::MissingHeader
|
||||
end
|
||||
end
|
||||
end
|
||||
35
spec/lib/diaspora_federation/receiver/public_spec.rb
Normal file
35
spec/lib/diaspora_federation/receiver/public_spec.rb
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
module DiasporaFederation
|
||||
describe Receiver::Public 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)
|
||||
)
|
||||
}
|
||||
|
||||
it "calls entity_persist if everyting 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(:entity_persist, kind_of(Entity), nil, sender_id)
|
||||
|
||||
described_class.new(xml).receive!
|
||||
end
|
||||
|
||||
it "raises when sender public key is not available" do
|
||||
expect(DiasporaFederation.callbacks).to receive(:trigger)
|
||||
.with(:fetch_public_key_by_diaspora_id, sender_id)
|
||||
.and_return(nil)
|
||||
|
||||
expect { described_class.new(xml).receive! }.to raise_error SenderNotFound
|
||||
end
|
||||
|
||||
it "raises when bad xml was supplied" do
|
||||
expect { described_class.new("<XML/>").receive! }.to raise_error Salmon::MissingAuthor
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -86,5 +86,12 @@ DiasporaFederation.configure do |config|
|
|||
on :fetch_entity_author_id_by_guid do
|
||||
nil
|
||||
end
|
||||
|
||||
on :fetch_private_key_by_user_guid do
|
||||
nil
|
||||
end
|
||||
|
||||
on :entity_persist do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in a new issue