Allow parent entity types different than "Post"

Entities::Message requires "Conversation" at the place, for instance.
This commit is contained in:
cmrd Senya 2015-12-15 02:03:58 +03:00
parent 358e844772
commit a0545c37de
11 changed files with 75 additions and 19 deletions

View file

@ -33,6 +33,10 @@ module DiasporaFederation
# @see Conversation#guid
# @return [String] conversation guid
property :conversation_guid
def self.get_target_entity_type(*)
"Conversation"
end
end
end
end

View file

@ -23,6 +23,10 @@ module DiasporaFederation
# @see PollAnswer#guid
# @return [String] poll answer guid
property :poll_answer_guid
def self.get_target_entity_type(*)
"Poll"
end
end
end
end

View file

@ -31,6 +31,10 @@ module DiasporaFederation
property :parent_guid
property :parent_author_signature, default: nil
property :author_signature, default: nil
def self.get_target_entity_type(data)
data[:target_type] || "Post"
end
end
end
@ -40,7 +44,7 @@ module DiasporaFederation
def to_xml
entity_xml.tap do |xml|
hash = to_h
Relayable.update_signatures!(hash)
Relayable.update_signatures!(hash, self.class)
xml.at_xpath("author_signature").content = hash[:author_signature]
xml.at_xpath("parent_author_signature").content = hash[:parent_author_signature]
@ -54,21 +58,29 @@ module DiasporaFederation
# verifies the signatures (+author_signature+ and +parent_author_signature+ if needed)
# @param [Hash] data hash with data to verify
# @raise [SignatureVerificationFailed] if the signature is not valid or no public key is found
def self.verify_signatures(data)
def self.verify_signatures(data, klass)
pkey = DiasporaFederation.callbacks.trigger(:fetch_public_key_by_diaspora_id, data[:diaspora_id])
raise SignatureVerificationFailed, "failed to fetch public key for #{data[:diaspora_id]}" if pkey.nil?
raise SignatureVerificationFailed, "wrong author_signature" unless Signing.verify_signature(
data, data[:author_signature], pkey
)
author_is_local = DiasporaFederation.callbacks.trigger(:entity_author_is_local?, "Post", data[:parent_guid])
verify_parent_signature(data) unless author_is_local
author_is_local = DiasporaFederation.callbacks.trigger(
:entity_author_is_local?,
klass.get_target_entity_type(data),
data[:parent_guid]
)
verify_parent_signature(data, klass) unless author_is_local
end
# this happens only on downstream federation
# @param [Hash] data hash with data to verify
def self.verify_parent_signature(data)
pkey = DiasporaFederation.callbacks.trigger(:fetch_author_public_key_by_entity_guid, "Post", data[:parent_guid])
def self.verify_parent_signature(data, klass)
pkey = DiasporaFederation.callbacks.trigger(
:fetch_author_public_key_by_entity_guid,
klass.get_target_entity_type(data),
data[:parent_guid]
)
raise SignatureVerificationFailed,
"failed to fetch public key for author of #{data[:parent_guid]}" if pkey.nil?
raise SignatureVerificationFailed, "wrong parent_author_signature" unless Signing.verify_signature(
@ -81,7 +93,7 @@ module DiasporaFederation
# if the signatures are not in the hash yet and if the keys are available.
#
# @param [Hash] data hash given for a signing
def self.update_signatures!(data)
def self.update_signatures!(data, klass)
if data[:author_signature].nil?
pkey = DiasporaFederation.callbacks.trigger(:fetch_private_key_by_diaspora_id, data[:diaspora_id])
data[:author_signature] = Signing.sign_with_key(data, pkey) unless pkey.nil?
@ -90,7 +102,7 @@ module DiasporaFederation
if data[:parent_author_signature].nil?
pkey = DiasporaFederation.callbacks.trigger(
:fetch_author_private_key_by_entity_guid,
"Post",
klass.get_target_entity_type(data),
data[:parent_guid]
)
data[:parent_author_signature] = Signing.sign_with_key(data, pkey) unless pkey.nil?

View file

@ -99,7 +99,9 @@ module DiasporaFederation
end
}]
Entities::Relayable.verify_signatures(data) if klass.included_modules.include?(Entities::Relayable)
if klass.included_modules.include?(Entities::Relayable)
Entities::Relayable.verify_signatures(data, klass)
end
klass.new(data)
end

View file

@ -23,7 +23,7 @@ module DiasporaFederation
def self.relayable_attributes_with_signatures(factory_name)
klass = FactoryGirl.factory_by_name(factory_name).build_class
sort_hash(FactoryGirl.attributes_for(factory_name), klass).tap do |data|
DiasporaFederation::Entities::Relayable.update_signatures!(data)
DiasporaFederation::Entities::Relayable.update_signatures!(data, klass)
end
end

View file

@ -20,5 +20,11 @@ XML
it_behaves_like "an XML Entity"
it_behaves_like "a relayable Entity"
describe ".get_target_entity_type" do
it "returns \"Post\" as target type" do
expect(described_class.get_target_entity_type(data)).to eq("Post")
end
end
end
end

View file

@ -21,5 +21,11 @@ XML
it_behaves_like "an XML Entity"
it_behaves_like "a relayable Entity"
describe ".get_target_entity_type" do
it "returns data[:target_type] as target type" do
expect(described_class.get_target_entity_type(data)).to eq(data[:target_type])
end
end
end
end

View file

@ -22,5 +22,11 @@ XML
it_behaves_like "an XML Entity"
it_behaves_like "a relayable Entity"
describe ".get_target_entity_type" do
it "returns \"Conversation\" as target type" do
expect(described_class.get_target_entity_type(data)).to eq("Conversation")
end
end
end
end

View file

@ -20,5 +20,11 @@ XML
it_behaves_like "an XML Entity"
it_behaves_like "a relayable Entity"
describe ".get_target_entity_type" do
it "returns data[:target_type] as target type" do
expect(described_class.get_target_entity_type(data)).to eq(data[:target_type])
end
end
end
end

View file

@ -20,5 +20,11 @@ XML
it_behaves_like "an XML Entity"
it_behaves_like "a relayable Entity"
describe ".get_target_entity_type" do
it "returns \"Poll\" as target type" do
expect(described_class.get_target_entity_type(data)).to eq("Poll")
end
end
end
end

View file

@ -10,6 +10,10 @@ module DiasporaFederation
}
}
class SomeRelayable < Entity
include Entities::Relayable
end
describe ".verify_signatures" do
it "doesn't raise anything if correct data were passed" do
hash[:author_signature] = Signing.sign_with_key(hash, author_pkey)
@ -28,14 +32,14 @@ module DiasporaFederation
expect(DiasporaFederation.callbacks).to receive(:trigger)
.with(:entity_author_is_local?, "Post", hash[:parent_guid])
.and_return(false)
expect { Entities::Relayable.verify_signatures(hash) }.not_to raise_error
expect { Entities::Relayable.verify_signatures(hash, SomeRelayable) }.not_to raise_error
end
it "raises when no public key for author was fetched" do
expect(DiasporaFederation.callbacks).to receive(:trigger).with(:fetch_public_key_by_diaspora_id, anything)
.and_return(nil)
expect { Entities::Relayable.verify_signatures(hash) }.to raise_error(
expect { Entities::Relayable.verify_signatures(hash, SomeRelayable) }.to raise_error(
Entities::Relayable::SignatureVerificationFailed
)
end
@ -46,7 +50,7 @@ module DiasporaFederation
expect(DiasporaFederation.callbacks).to receive(:trigger)
.with(:fetch_public_key_by_diaspora_id, hash[:diaspora_id])
.and_return(author_pkey.public_key)
expect { Entities::Relayable.verify_signatures(hash) }.to raise_error(
expect { Entities::Relayable.verify_signatures(hash, SomeRelayable) }.to raise_error(
Entities::Relayable::SignatureVerificationFailed
)
end
@ -67,7 +71,7 @@ module DiasporaFederation
expect(DiasporaFederation.callbacks).to receive(:trigger)
.with(:entity_author_is_local?, "Post", hash[:parent_guid])
.and_return(false)
expect { Entities::Relayable.verify_signatures(hash) }.to raise_error(
expect { Entities::Relayable.verify_signatures(hash, SomeRelayable) }.to raise_error(
Entities::Relayable::SignatureVerificationFailed
)
end
@ -89,7 +93,7 @@ module DiasporaFederation
expect(DiasporaFederation.callbacks).to receive(:trigger)
.with(:entity_author_is_local?, "Post", hash[:parent_guid])
.and_return(false)
expect { Entities::Relayable.verify_signatures(hash) }.to raise_error(
expect { Entities::Relayable.verify_signatures(hash, SomeRelayable) }.to raise_error(
Entities::Relayable::SignatureVerificationFailed
)
end
@ -104,7 +108,7 @@ module DiasporaFederation
expect(DiasporaFederation.callbacks).to receive(:trigger)
.with(:entity_author_is_local?, "Post", hash[:parent_guid])
.and_return(true)
expect { Entities::Relayable.verify_signatures(hash) }.not_to raise_error
expect { Entities::Relayable.verify_signatures(hash, SomeRelayable) }.not_to raise_error
end
end
@ -121,7 +125,7 @@ module DiasporaFederation
)
.and_return(parent_pkey)
Entities::Relayable.update_signatures!(hash)
Entities::Relayable.update_signatures!(hash, SomeRelayable)
expect(Signing.verify_signature(hash, hash[:author_signature], author_pkey)).to be_truthy
expect(Signing.verify_signature(hash, hash[:parent_author_signature], parent_pkey)).to be_truthy
end
@ -130,7 +134,7 @@ module DiasporaFederation
signatures = {author_signature: "aa", parent_author_signature: "bb"}
hash.merge!(signatures)
Entities::Relayable.update_signatures!(hash)
Entities::Relayable.update_signatures!(hash, SomeRelayable)
expect(hash[:author_signature]).to eq(signatures[:author_signature])
expect(hash[:parent_author_signature]).to eq(signatures[:parent_author_signature])
end
@ -147,7 +151,7 @@ module DiasporaFederation
)
.and_return(nil)
Entities::Relayable.update_signatures!(hash)
Entities::Relayable.update_signatures!(hash, SomeRelayable)
expect(hash[:author_signature]).to eq(nil)
expect(hash[:parent_author_signature]).to eq(nil)
end