diaspora/lib/postzord/receiver/private.rb
Steven Hancock a8de3a5a3f Rails.root and File.join cleanup
- `Rails.root` is a `Pathname`, so let's use `Rails.root.join`
- Clean up most of the remaining `File.join`s
2012-06-11 03:13:20 -07:00

123 lines
4.1 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.
require Rails.root.join('lib', 'webfinger')
require Rails.root.join('lib', 'diaspora', 'parser')
class Postzord::Receiver::Private < Postzord::Receiver
def initialize(user, opts={})
@user = user
@user_person = @user.person
@salmon_xml = opts[:salmon_xml]
@sender = opts[:person] || Webfinger.new(self.salmon.author_id).fetch
@author = @sender
@object = opts[:object]
end
def receive!
begin
if @sender && self.salmon.verified_for_key?(@sender.public_key)
parse_and_receive(salmon.parsed_data)
else
FEDERATION_LOGGER.info("event=receive status=abort recipient=#{@user.diaspora_handle} sender=#{@salmon.author_id} reason='not_verified for key'")
false
end
rescue => e
#this sucks
FEDERATION_LOGGER.info("Failure to receive #{@object.inspect} for sender:#{@sender.id} for user:#{@user.id}: #{e.message}")
raise e
end
end
def parse_and_receive(xml)
@object ||= Diaspora::Parser.from_xml(xml)
return if @object.nil?
FEDERATION_LOGGER.info("user:#{@user.id} starting private receive from person:#{@sender.guid}")
if self.validate_object
set_author!
receive_object
FEDERATION_LOGGER.info("object received #{@object.class}")
else
FEDERATION_LOGGER.info("failed to receive object from #{@object.author}: #{@object.inspect}")
raise "not a valid object:#{@object.inspect}"
end
end
# @return [Object]
def receive_object
obj = @object.receive(@user, @author)
Notification.notify(@user, obj, @author) if obj.respond_to?(:notification_type)
FEDERATION_LOGGER.info("user:#{@user.id} successfully received private post from person#{@sender.guid} #{@object.inspect}")
obj
end
protected
def salmon
@salmon ||= Salmon::EncryptedSlap.from_xml(@salmon_xml, @user)
end
def xml_author
if @object.respond_to?(:relayable?)
#if A and B are friends, and A sends B a comment from C, we delegate the validation to the owner of the post being commented on
xml_author = @user.owns?(@object.parent) ? @object.diaspora_handle : @object.parent.author.diaspora_handle
@author = Webfinger.new(@object.diaspora_handle).fetch if @object.author
else
xml_author = @object.diaspora_handle
end
xml_author
end
def validate_object
raise "Contact required unless request" if contact_required_unless_request
raise "Relayable object, but no parent object found" if relayable_without_parent?
assign_sender_handle_if_request
raise "Author does not match XML author" if author_does_not_match_xml_author?
@object
end
def set_author!
return unless @author
@object.author = @author if @object.respond_to? :author=
@object.person = @author if @object.respond_to? :person=
end
private
#validations
def relayable_without_parent?
if @object.respond_to?(:relayable?) && @object.parent.nil?
FEDERATION_LOGGER.info("event=receive status=abort reason='received a comment but no corresponding post' recipient=#{@user_person.diaspora_handle} sender=#{@sender.diaspora_handle} payload_type=#{@object.class})")
return true
end
end
def author_does_not_match_xml_author?
if (@author.diaspora_handle != xml_author)
FEDERATION_LOGGER.info("event=receive status=abort reason='author in xml does not match retrieved person' payload_type=#{@object.class} recipient=#{@user_person.diaspora_handle} sender=#{@sender.diaspora_handle}")
return true
end
end
def contact_required_unless_request
unless @object.is_a?(Request) || @user.contact_for(@sender)
FEDERATION_LOGGER.info("event=receive status=abort reason='sender not connected to recipient' recipient=#{@user_person.diaspora_handle} sender=#{@sender.diaspora_handle}")
return true
end
end
def assign_sender_handle_if_request
#special casey
if @object.is_a?(Request)
@object.sender_handle = @sender.diaspora_handle
end
end
end