create entity fetcher for public entities
This commit is contained in:
parent
4a7fd52844
commit
d83b6f14f5
5 changed files with 108 additions and 4 deletions
|
|
@ -4,5 +4,6 @@ module DiasporaFederation
|
|||
end
|
||||
end
|
||||
|
||||
require "diaspora_federation/federation/fetcher"
|
||||
require "diaspora_federation/federation/receiver"
|
||||
require "diaspora_federation/federation/sender"
|
||||
|
|
|
|||
26
lib/diaspora_federation/federation/fetcher.rb
Normal file
26
lib/diaspora_federation/federation/fetcher.rb
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
module DiasporaFederation
|
||||
module Federation
|
||||
# this module is for fetching entities from other pods
|
||||
module Fetcher
|
||||
# fetches a public entity from a remote pod
|
||||
# @param [String] author the diaspora ID of the author of the entity
|
||||
# @param [Symbol, String] entity_type snake_case version of the entity class
|
||||
# @param [String] guid guid of the entity to fetch
|
||||
def self.fetch_public(author, entity_type, guid)
|
||||
url = DiasporaFederation.callbacks.trigger(:fetch_person_url_to, author, "/fetch/#{entity_type}/#{guid}")
|
||||
response = DiasporaFederation::Fetcher.get(url)
|
||||
raise "Failed to fetch #{url}: #{response.status}" unless response.success?
|
||||
|
||||
magic_env = Nokogiri::XML::Document.parse(response.body).root
|
||||
entity = Salmon::MagicEnvelope.unenvelop(magic_env)
|
||||
DiasporaFederation.callbacks.trigger(:save_entity_after_receive, entity)
|
||||
rescue => e
|
||||
raise NotFetchable, "Failed to fetch #{entity_type}:#{guid} from #{author}: #{e.class}: #{e.message}"
|
||||
end
|
||||
|
||||
# Raised, if the entity is not fetchable
|
||||
class NotFetchable < RuntimeError
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
76
spec/lib/diaspora_federation/federation/fetcher_spec.rb
Normal file
76
spec/lib/diaspora_federation/federation/fetcher_spec.rb
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
module DiasporaFederation
|
||||
describe Federation::Fetcher do
|
||||
let(:post) { FactoryGirl.build(:status_message_entity, public: true) }
|
||||
let(:post_magic_env) { Salmon::MagicEnvelope.new(post).envelop(alice.private_key, post.author).to_xml }
|
||||
|
||||
describe ".fetch_public" do
|
||||
it "fetches a public post" do
|
||||
stub_request(:get, "https://example.org/fetch/post/#{post.guid}")
|
||||
.to_return(status: 200, body: post_magic_env)
|
||||
|
||||
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
|
||||
:fetch_person_url_to, post.author, "/fetch/post/#{post.guid}"
|
||||
).and_return("https://example.org/fetch/post/#{post.guid}")
|
||||
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(
|
||||
:save_entity_after_receive, 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")
|
||||
end
|
||||
|
||||
Federation::Fetcher.fetch_public(post.author, :post, post.guid)
|
||||
end
|
||||
|
||||
it "follows redirects" do
|
||||
stub_request(:get, "https://example.org/fetch/post/#{post.guid}")
|
||||
.to_return(status: 302, headers: {"Location" => "https://example.com/fetch/post/#{post.guid}"})
|
||||
stub_request(:get, "https://example.com/fetch/post/#{post.guid}")
|
||||
.to_return(status: 200, body: post_magic_env)
|
||||
|
||||
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
|
||||
:fetch_person_url_to, post.author, "/fetch/post/#{post.guid}"
|
||||
).and_return("https://example.org/fetch/post/#{post.guid}")
|
||||
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(
|
||||
:save_entity_after_receive, kind_of(Entities::StatusMessage)
|
||||
)
|
||||
|
||||
Federation::Fetcher.fetch_public(post.author, :post, post.guid)
|
||||
end
|
||||
|
||||
it "raises NotFetchable if post not found (private)" do
|
||||
stub_request(:get, "https://example.org/fetch/post/#{post.guid}")
|
||||
.to_return(status: 404)
|
||||
|
||||
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
|
||||
:fetch_person_url_to, post.author, "/fetch/post/#{post.guid}"
|
||||
).and_return("https://example.org/fetch/post/#{post.guid}")
|
||||
|
||||
expect {
|
||||
Federation::Fetcher.fetch_public(post.author, :post, post.guid)
|
||||
}.to raise_error Federation::Fetcher::NotFetchable
|
||||
end
|
||||
|
||||
it "raises NotFetchable if connection refused" do
|
||||
expect(DiasporaFederation::Fetcher).to receive(:get).with(
|
||||
"https://example.org/fetch/post/#{post.guid}"
|
||||
).and_raise(Faraday::ConnectionFailed, "Couldn't connect to server")
|
||||
|
||||
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
|
||||
:fetch_person_url_to, post.author, "/fetch/post/#{post.guid}"
|
||||
).and_return("https://example.org/fetch/post/#{post.guid}")
|
||||
|
||||
expect {
|
||||
Federation::Fetcher.fetch_public(post.author, :post, post.guid)
|
||||
}.to raise_error Federation::Fetcher::NotFetchable
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -85,10 +85,8 @@ shared_examples "a relayable Entity" do
|
|||
author_signature = xml.at_xpath("post/*[1]/author_signature").text
|
||||
parent_author_signature = xml.at_xpath("post/*[1]/parent_author_signature").text
|
||||
|
||||
alice_public_key = OpenSSL::PKey::RSA.new(alice.serialized_public_key)
|
||||
bob_public_key = OpenSSL::PKey::RSA.new(bob.serialized_public_key)
|
||||
expect(verify_signature(alice_public_key, author_signature, signed_string)).to be_truthy
|
||||
expect(verify_signature(bob_public_key, parent_author_signature, signed_string)).to be_truthy
|
||||
expect(verify_signature(alice.public_key, author_signature, signed_string)).to be_truthy
|
||||
expect(verify_signature(bob.public_key, parent_author_signature, signed_string)).to be_truthy
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
class Person < ActiveRecord::Base
|
||||
include ::Diaspora::Guid
|
||||
|
||||
def private_key; OpenSSL::PKey::RSA.new(serialized_private_key) end
|
||||
def public_key; OpenSSL::PKey::RSA.new(serialized_public_key) end
|
||||
|
||||
def alias_url; "#{url}people/#{guid}" end
|
||||
def hcard_url; "#{url}hcard/users/#{guid}" end
|
||||
def profile_url; "#{url}u/#{nickname}" end
|
||||
|
|
|
|||
Loading…
Reference in a new issue