basic receive cleanup

This commit is contained in:
maxwell 2011-01-10 13:29:00 -08:00
parent 6bb132b25e
commit daab8e80ce
9 changed files with 248 additions and 63 deletions

View file

@ -122,7 +122,7 @@ class Person
(person.nil? || person.remote?) ? nil : person (person.nil? || person.remote?) ? nil : person
end end
def self.build_from_webfinger(profile, hcard) def self.create_from_webfinger(profile, hcard)
return nil if profile.nil? || !profile.valid_diaspora_profile? return nil if profile.nil? || !profile.valid_diaspora_profile?
new_person = Person.new new_person = Person.new
new_person.exported_key = profile.public_key new_person.exported_key = profile.public_key

View file

@ -64,6 +64,20 @@ class Post
user.people_in_aspects(user.aspects_with_post(self.id)) user.people_in_aspects(user.aspects_with_post(self.id))
end end
def receive(postzord)
xml_author = object.diaspora_handle
if (postzord.salmon_author.diaspora_handle != xml_author)
Rails.logger.info("event=receive status=abort reason='author in xml does not match retrieved person' payload_type=#{object.class} recipient=#{self.diaspora_handle} sender=#{salmon_author.diaspora_handle}")
return nil
end
if postzord.user.contact_for(postzord.salmon_author)
self.person = postzord.salmon_author
#do post receive
end
end
protected protected
def destroy_comments def destroy_comments
comments.each{|c| c.destroy} comments.each{|c| c.destroy}

View file

@ -24,15 +24,23 @@ module Diaspora
object = Diaspora::Parser.from_xml(xml) object = Diaspora::Parser.from_xml(xml)
Rails.logger.info("event=receive status=start recipient=#{self.diaspora_handle} payload_type=#{object.class} sender=#{salmon_author.diaspora_handle}") Rails.logger.info("event=receive status=start recipient=#{self.diaspora_handle} payload_type=#{object.class} sender=#{salmon_author.diaspora_handle}")
#special casey
if object.is_a?(Request) if object.is_a?(Request)
salmon_author.save salmon_author.save
object.sender_handle = salmon_author.diaspora_handle object.sender_handle = salmon_author.diaspora_handle
end end
if object.is_a?(Comment) if object.is_a?(Comment)
xml_author = (owns?(object.post))? object.diaspora_handle : object.post.person.diaspora_handle xml_author = (owns?(object.post))? object.diaspora_handle : object.post.person.diaspora_handle
person = Webfinger.new(object.diaspora_handle).fetch
else else
xml_author = object.diaspora_handle xml_author = object.diaspora_handle
person = salmon_author
end
#begin similar
unless object.is_a?(Request) || self.contact_for(salmon_author)
Rails.logger.info("event=receive status=abort reason='sender not connected to recipient' recipient=#{self.diaspora_handle} sender=#{salmon_author.diaspora_handle} payload_type=#{object.class}")
return
end end
if (salmon_author.diaspora_handle != xml_author) if (salmon_author.diaspora_handle != xml_author)
@ -40,27 +48,11 @@ module Diaspora
return return
end end
e = Webfinger.new(object.diaspora_handle)
begin
person = e.fetch
rescue Exception => e
Rails.logger.info("event=receive status=abort reason='#{e.message}' payload_type=#{object.class} recipient=#{self.diaspora_handle} sender=#{salmon_author.diaspora_handle}")
return
end
if person if person
object.person = person if object.respond_to? :person=
unless object.is_a?(Request) || self.contact_for(salmon_author)
Rails.logger.info("event=receive status=abort reason='sender not connected to recipient' recipient=#{self.diaspora_handle} sender=#{salmon_author.diaspora_handle} payload_type=#{object.class}")
return
else
receive_object(object, person)
Rails.logger.info("event=receive status=complete recipient=#{self.diaspora_handle} sender=#{salmon_author.diaspora_handle} payload_type#{object.class}") Rails.logger.info("event=receive status=complete recipient=#{self.diaspora_handle} sender=#{salmon_author.diaspora_handle} payload_type#{object.class}")
return object object.person = person if object.respond_to? :person=
end receive_object(object, person)
end end
end end
@ -111,9 +103,7 @@ module Diaspora
end end
def receive_comment comment def receive_comment comment
commenter = comment.person commenter = comment.person
unless comment.post.person == self.person || comment.verify_post_creator_signature unless comment.post.person == self.person || comment.verify_post_creator_signature
Rails.logger.info("event=receive status=abort reason='comment signature not valid' recipient=#{self.diaspora_handle} sender=#{comment.post.person.diaspora_handle} payload_type=#{comment.class} post_id=#{comment.post_id}") Rails.logger.info("event=receive status=abort reason='comment signature not valid' recipient=#{self.diaspora_handle} sender=#{comment.post.person.diaspora_handle} payload_type=#{comment.class} post_id=#{comment.post_id}")
return return

View file

@ -19,5 +19,9 @@ module Diaspora
def subscribers(user) def subscribers(user)
raise 'you must override subscribers in order to enable federation on this model' raise 'you must override subscribers in order to enable federation on this model'
end end
def receive(user, salmon_author)
raise 'you must override receive in order to enable federation on this model'
end
end end
end end

29
lib/postzord/receiver.rb Normal file
View file

@ -0,0 +1,29 @@
# Copyright (c) 2010, Diaspora Inc. This file is
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
#
require File.join(Rails.root, 'lib/webfinger')
require File.join(Rails.root, 'lib/diaspora/parser')
module Postzord
class Receiver
def initialize(user, salmon_xml)
@user = user
@salmon = Salmon::SalmonSlap.parse(salmon_xml, @user)
@salmon_author = Webfinger.new(@salmon.author_email).fetch
end
def perform
if @salmon_author && @salmon.verified_for_key?(@salmon_author.public_key)
@object = Diaspora::Parser.from_xml(@salmon.parsed_data)
else
Rails.logger.info("event=receive status=abort recipient=#{@user.diaspora_handle} sender=#{@salmon.author_email} reason='not_verified for key'")
nil
end
end
protected
end
end

View file

@ -13,6 +13,7 @@ class Webfinger
end end
def fetch def fetch
begin
person = Person.by_account_identifier(@account) person = Person.by_account_identifier(@account)
if person if person
Rails.logger.info("event=webfinger status=success route=local target=#{@account}") Rails.logger.info("event=webfinger status=success route=local target=#{@account}")
@ -29,7 +30,10 @@ class Webfinger
Rails.logger.info("event=webfinger status=failure route=remote target=#{@account}") Rails.logger.info("event=webfinger status=failure route=remote target=#{@account}")
raise WebfingerFailedError.new(@account) raise WebfingerFailedError.new(@account)
end end
rescue
Rails.logger.info("event=receive status=abort recipient=#{self.diaspora_handle} sender=#{salmon.author_email} reason='#{e.message}'")
nil
end
end end
private private
@ -77,7 +81,7 @@ class Webfinger
end end
card = HCard.build hcard.body card = HCard.build hcard.body
p = Person.build_from_webfinger(wf_profile, card) p = Person.create_from_webfinger(wf_profile, card)
end end
end end

View file

@ -33,30 +33,6 @@ describe Diaspora::Parser do
proc { user.receive xml, user2.person }.should change(StatusMessage, :count).by(-1) proc { user.receive xml, user2.person }.should change(StatusMessage, :count).by(-1)
end end
context "connecting" do
let(:good_request) { FakeHttpRequest.new(:success)}
it "should create a new person upon getting a person request" do
remote_user = Factory.create(:user)
new_person = remote_user.person
request = Request.new(:to =>user.person, :from => new_person)
xml = remote_user.salmon(request).xml_for(user.person)
request.delete
request.from.delete
remote_user.delete
new_person.delete
Person.should_receive(:by_account_identifier).twice.and_return(new_person)
lambda {
user.receive_salmon xml
}.should change(Person, :count).by(1)
end
end
it "should activate the Person if I initiated a request to that url" do it "should activate the Person if I initiated a request to that url" do
user.send_contact_request_to(user2.person, aspect) user.send_contact_request_to(user2.person, aspect)
request = Request.to(user2).from(user).first request = Request.to(user2).from(user).first

View file

@ -0,0 +1,69 @@
# Copyright (c) 2010, Diaspora Inc. This file is
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
require 'spec_helper'
require File.join(Rails.root, 'lib/postzord')
require File.join(Rails.root, 'lib/postzord/receiver')
describe Postzord::Receiver do
describe '.initialize' do
it 'has @salmon_xml and an @user' do
xml = "yeah"
user = 'faa'
salmon_mock = mock()
web_mock = mock()
web_mock.should_receive(:fetch).and_return true
salmon_mock.should_receive(:author_email).and_return(true)
Salmon::SalmonSlap.should_receive(:parse).with(xml, user).and_return(salmon_mock)
Webfinger.should_receive(:new).and_return(web_mock)
zord = Postzord::Receiver.new(user, xml)
zord.instance_variable_get(:@user).should_not be_nil
zord.instance_variable_get(:@salmon).should_not be_nil
zord.instance_variable_get(:@salmon_author).should_not be_nil
end
end
describe '#perform' do
before do
@user = make_user
@user2 = make_user
@person2 = @user2.person
a = @user2.aspects.create(:name => "hey")
@original_post = @user2.build_post(:status_message, :message => "hey", :aspect_ids => [a.id])
salmon_xml = @user2.salmon(@original_post).xml_for(@user.person)
@zord = Postzord::Receiver.new(@user, salmon_xml)
@salmon = @zord.instance_variable_get(:@salmon)
end
context 'returns nil' do
it 'if the salmon author does not exist' do
@zord.instance_variable_set(:@salmon_author, nil)
@zord.perform.should be_nil
end
it 'if the author does not match the signature' do
@zord.instance_variable_set(:@salmon_author, Factory(:person))
@zord.perform.should be_nil
end
end
context 'returns the sent object' do
it 'returns the received object on success' do
object = @zord.perform
object.should respond_to(:to_diaspora_xml)
end
end
it 'parses the salmon object' do
Diaspora::Parser.should_receive(:from_xml).with(@salmon.parsed_data)
@zord.perform
end
end
end

View file

@ -0,0 +1,99 @@
# Copyright (c) 2010, Diaspora Inc. This file is
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
require 'spec_helper'
require File.join(Rails.root, 'lib/webfinger')
describe Webfinger do
let(:user1) { make_user }
let(:user2) { make_user }
let(:account) {"foo@tom.joindiaspora.com"}
let(:person){ Factory(:person, :diaspora_handle => account)}
let(:finger){Webfinger.new(account)}
let(:good_request) { FakeHttpRequest.new(:success)}
let(:diaspora_xrd) {File.open(File.join(Rails.root, 'spec/fixtures/host_xrd')).read}
let(:diaspora_finger) {File.open(File.join(Rails.root, 'spec/fixtures/finger_xrd')).read}
let(:hcard_xml) {File.open(File.join(Rails.root, 'spec/fixtures/hcard_response')).read}
let(:non_diaspora_xrd) {File.open(File.join(Rails.root, 'spec/fixtures/nonseed_finger_xrd')).read}
let(:non_diaspora_hcard) {File.open(File.join(Rails.root, 'spec/fixtures/evan_hcard')).read}
context 'setup' do
let(:action){ Proc.new{|person| person.inspect }}
describe '#intialize' do
it 'sets account ' do
n = Webfinger.new("mbs348@gmail.com")
n.instance_variable_get(:@account).should_not be nil
end
it 'should set ssl as the default' do
foo = Webfinger.new(account)
foo.instance_variable_get(:@ssl).should be true
end
end
context 'webfinger query chain processing' do
describe '#webfinger_profile_url' do
it 'should parse out the webfinger template' do
finger.send(:webfinger_profile_url, diaspora_xrd).should == "http://tom.joindiaspora.com/webfinger/?q=#{account}"
end
it 'should return nil if not an xrd' do
finger.send(:webfinger_profile_url, '<html></html>').should be nil
end
it 'should return the template for xrd' do
finger.send(:webfinger_profile_url, diaspora_xrd).should == 'http://tom.joindiaspora.com/webfinger/?q=foo@tom.joindiaspora.com'
end
end
describe '#xrd_url' do
it 'should return canonical host-meta url for http' do
finger.instance_variable_set(:@ssl, false)
finger.send(:xrd_url).should == "http://tom.joindiaspora.com/.well-known/host-meta"
end
it 'can return the https version' do
finger.send(:xrd_url).should == "https://tom.joindiaspora.com/.well-known/host-meta"
end
end
end
context 'webfingering local people' do
it 'should return a person from the database if it matches its handle' do
person.save
finger.fetch.id.should == person.id
end
end
it 'should fetch a diaspora webfinger and make a person for them' do
diaspora_xrd.stub!(:body).and_return(diaspora_xrd)
hcard_xml.stub!(:body).and_return(hcard_xml)
diaspora_finger.stub!(:body).and_return(diaspora_finger)
RestClient.stub!(:get).and_return(diaspora_xrd, diaspora_finger, hcard_xml)
#new_person = Factory.build(:person, :diaspora_handle => "tom@tom.joindiaspora.com")
# http://tom.joindiaspora.com/.well-known/host-meta
f = Webfinger.new("tom@tom.joindiaspora.com").fetch
f.should be_valid
end
it 'should retry with http if https fails' do
f = Webfinger.new("tom@tom.joindiaspora.com")
diaspora_xrd.stub!(:body).and_return(diaspora_xrd)
RestClient.should_receive(:get).twice.and_return(nil, diaspora_xrd)
f.should_receive(:xrd_url).twice
f.send(:get_xrd)
f.instance_variable_get(:@ssl).should == false
end
end
end