* Extract post fetching logic from Reshare into its own module * raise proper error message when fetching fails * raise proper error message when parent is still missing We can't skip fetch failures or missing parents and still need to retry them in case we're sent the parent later on
100 lines
2.9 KiB
Ruby
100 lines
2.9 KiB
Ruby
# Copyright (c) 2010-2011, Diaspora Inc. This file is
|
|
# licensed under the Affero General Public License version 3 or later. See
|
|
# the COPYRIGHT file.
|
|
|
|
class Postzord::Receiver::Public < Postzord::Receiver
|
|
|
|
attr_accessor :salmon, :author
|
|
|
|
def initialize(xml)
|
|
@salmon = Salmon::Slap.from_xml(xml)
|
|
@author = Webfinger.new(@salmon.author_id).fetch
|
|
|
|
FEDERATION_LOGGER.info("Receiving public object from person:#{@author.id}")
|
|
end
|
|
|
|
# @return [Boolean]
|
|
def verified_signature?
|
|
@salmon.verified_for_key?(@author.public_key)
|
|
end
|
|
|
|
# @return [void]
|
|
def receive!
|
|
return false unless verified_signature?
|
|
# return false unless account_deletion_is_from_author
|
|
|
|
return false unless save_object
|
|
|
|
FEDERATION_LOGGER.info("received a #{@object.inspect}")
|
|
if @object.respond_to?(:relayable?)
|
|
receive_relayable
|
|
elsif @object.is_a?(AccountDeletion)
|
|
#nothing
|
|
elsif @object.is_a?(SignedRetraction) # feels like a hack
|
|
self.recipient_user_ids.each do |user_id|
|
|
user = User.where(id: user_id).first
|
|
@object.perform user if user
|
|
end
|
|
else
|
|
Workers::ReceiveLocalBatch.perform_async(@object.class.to_s, @object.id, self.recipient_user_ids)
|
|
true
|
|
end
|
|
end
|
|
|
|
# @return [Object]
|
|
def receive_relayable
|
|
if @object.parent_author.local?
|
|
# receive relayable object only for the owner of the parent object
|
|
@object.receive(@object.parent_author.owner, @author)
|
|
end
|
|
# notify everyone who can see the parent object
|
|
receiver = Postzord::Receiver::LocalBatch.new(@object, self.recipient_user_ids)
|
|
receiver.notify_users
|
|
@object
|
|
end
|
|
|
|
# @return [Object]
|
|
def save_object
|
|
@object = Diaspora::Parser::from_xml(@salmon.parsed_data)
|
|
raise "Object is not public" if object_can_be_public_and_it_is_not?
|
|
raise Diaspora::RelayableObjectWithoutParent if object_must_have_parent_and_does_not?
|
|
raise Diaspora::AuthorXMLAuthorMismatch if author_does_not_match_xml_author?
|
|
@object.save! if @object && @object.respond_to?(:save!)
|
|
@object
|
|
end
|
|
|
|
# @return [Array<Integer>] User ids
|
|
def recipient_user_ids
|
|
User.all_sharing_with_person(@author).pluck('users.id')
|
|
end
|
|
|
|
def xml_author
|
|
if @object.respond_to?(:relayable?)
|
|
#this is public, so it would only be owners sending us other people comments etc
|
|
@object.parent_author.local? ? @object.diaspora_handle : @object.parent_diaspora_handle
|
|
else
|
|
@object.diaspora_handle
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def account_deletion_is_from_author
|
|
return true unless @object.is_a?(AccountDeletion)
|
|
return false if @object.diaspora_handle != @author.diaspora_handle
|
|
return true
|
|
end
|
|
|
|
# @return [Boolean]
|
|
def object_can_be_public_and_it_is_not?
|
|
@object.respond_to?(:public) && !@object.public?
|
|
end
|
|
|
|
def object_must_have_parent_and_does_not?
|
|
if @object.respond_to?(:relayable?) # comment, like
|
|
@object.parent.nil?
|
|
else
|
|
false
|
|
end
|
|
end
|
|
end
|