diff --git a/app/models/retraction.rb b/app/models/retraction.rb index 89d430dc8..3aa3cf875 100644 --- a/app/models/retraction.rb +++ b/app/models/retraction.rb @@ -30,7 +30,7 @@ class Retraction if self.type.constantize.find_by_id(post_id) unless Post.first(:diaspora_handle => person.diaspora_handle, :id => post_id) Rails.logger.info("event=retraction status=abort reason='no post found authored by retractor' sender=#{person.diaspora_handle} post_id=#{post_id}") - raise "#{person.inspect} is trying to retract a post that either doesn't exist or is not by them" + return end begin diff --git a/lib/diaspora/user/receiving.rb b/lib/diaspora/user/receiving.rb index 182ba473e..48081d7a3 100644 --- a/lib/diaspora/user/receiving.rb +++ b/lib/diaspora/user/receiving.rb @@ -6,23 +6,25 @@ module Diaspora def receive_salmon salmon_xml salmon = Salmon::SalmonSlap.parse salmon_xml, self webfinger = EMWebfinger.new(salmon.author_email) - - webfinger.on_person { |response| - if response.is_a? Person - salmon_author = response - if salmon.verified_for_key?(salmon_author.public_key) - self.receive(salmon.parsed_data, salmon_author) - end + begin + salmon_author = webfinger.fetch + rescue Exception => e + Rails.logger.info("event=receive status=abort recipient=#{self.diaspora_handle} sender=#{salmon.author_email} reason='#{e.message}'") + end + + if salmon_author + if salmon.verified_for_key?(salmon_author.public_key) + self.receive(salmon.parsed_data, salmon_author) else - Rails.logger.info("event=receive status=abort recipient=#{self.diaspora_handle} sender=#{salmon.author_email} reason='#{response}'") + Rails.logger.info("event=receive status=abort recipient=#{self.diaspora_handle} sender=#{salmon.author_email} reason='not_verified for key'") end - } + end end def receive xml, salmon_author 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}") - + if object.is_a?(Request) salmon_author.save object.sender_handle = salmon_author.diaspora_handle @@ -41,17 +43,23 @@ module Diaspora e = EMWebfinger.new(object.diaspora_handle) - e.on_person do |person| - if person.class == 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}") - return object - end + 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 + 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}") + return object end end end @@ -102,7 +110,7 @@ module Diaspora def receive_comment comment commenter = comment.person - + 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}") return @@ -136,10 +144,10 @@ module Diaspora def receive_post post #exsists locally, but you dont know about it #does not exsist locally, and you dont know about it - + #exsists_locally? - #you know about it, and it is mutable - #you know about it, and it is not mutable + #you know about it, and it is mutable + #you know about it, and it is not mutable # on_pod = exsists_on_pod?(post) if on_pod && on_pod.diaspora_handle == post.diaspora_handle diff --git a/lib/em-webfinger.rb b/lib/em-webfinger.rb index bc7904a07..14304a276 100644 --- a/lib/em-webfinger.rb +++ b/lib/em-webfinger.rb @@ -7,7 +7,6 @@ class EMWebfinger OPTS = {:timeout => TIMEOUT, :redirects => REDIRECTS} def initialize(account) @account = account.strip.gsub('acct:','').to_s - @callbacks = [] @ssl = true Rails.logger.info("event=EMWebfinger status=initialized target=#{account}") # Raise an error if identifier has a port number @@ -15,67 +14,53 @@ class EMWebfinger # Raise an error if identifier is not a valid email (generous regexp) #raise "Identifier is invalid" if !(@account=~ /^[a-zA-Z][\w\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$/) end + def fetch - if @callbacks.empty? - Rails.logger.info("event=EMWebfinger status=abort target=#{@account} callbacks=empty") - raise 'you need to set a callback before calling fetch' - end person = Person.by_account_identifier(@account) if person Rails.logger.info("event=EMWebfinger status=local target=#{@account}") - process_callbacks person + return person else Rails.logger.info("event=EMWebfinger status=remote target=#{@account}") + profile_url = get_xrd - - webfinger_profile = get_webfinger_profile(profile_url) if profile_url - - fingered_person = make_person_from_webfinger(webfinger_profile) if webfinger_profile - - process_callbacks(fingered_person) + webfinger_profile = get_webfinger_profile(profile_url) + fingered_person = make_person_from_webfinger(webfinger_profile) + fingered_person end end - def on_person(&block) - @callbacks << block - self.fetch - end - private - def get_xrd - begin - http = RestClient.get xrd_url, OPTS + begin + http = RestClient.get xrd_url, OPTS - profile_url = webfinger_profile_url(http.body) - if profile_url - return profile_url - else - raise "no profile URL" - end - rescue - if @ssl - @ssl = false - retry - else - process_callbacks I18n.t('webfinger.xrd_fetch_failed', :account => @account) - return - end - end + profile_url = webfinger_profile_url(http.body) + if profile_url + return profile_url + else + raise "no profile URL" + end + rescue Exception => e + if @ssl + @ssl = false + retry + else + raise e + raise I18n.t('webfinger.xrd_fetch_failed', :account => @account) + end + end end def get_webfinger_profile(profile_url) - begin http = RestClient.get(profile_url, OPTS) - return http.body - rescue Exception => e - puts e.message - process_callbacks I18n.t('webfinger.fetch_failed', :profile_url => profile_url) - return - end + rescue + raise I18n.t('webfinger.fetch_failed', :profile_url => profile_url) + end + return http.body end def make_person_from_webfinger(webfinger_profile) @@ -86,9 +71,8 @@ class EMWebfinger begin hcard = RestClient.get(wf_profile.hcard, OPTS) rescue - process_callbacks I18n.t('webfinger.hcard_fetch_failed', :account => @account) - return - end + return I18n.t('webfinger.hcard_fetch_failed', :account => @account) + end card = HCard.build hcard.body p = Person.build_from_webfinger(wf_profile, card) @@ -96,19 +80,6 @@ class EMWebfinger end - def process_callbacks(person) - Rails.logger.info("event=EMWebfinger status=callbacks_started target=#{@account} response='#{person.is_a?(String) ? person : person.id}'") - @callbacks.each { |c| - begin - c.call(person) - rescue Exception => e - Rails.logger.info("event=EMWebfinger status=error_on_callback error='#{e.inspect}'") - end - } - Rails.logger.info("event=EMWebfinger status=complete target=#{@account}") - end - - ##helpers private @@ -122,7 +93,7 @@ class EMWebfinger domain = @account.split('@')[1] "http#{'s' if @ssl}://#{domain}/.well-known/host-meta" end - + def swizzle(template) template.gsub '{uri}', @account end diff --git a/spec/lib/em-webfinger_spec.rb b/spec/lib/em-webfinger_spec.rb index 6b5c16b9c..c8c8c4710 100644 --- a/spec/lib/em-webfinger_spec.rb +++ b/spec/lib/em-webfinger_spec.rb @@ -42,35 +42,6 @@ describe EMWebfinger do end end - - describe '#on_person' do - it 'should set a callback' do - n = EMWebfinger.new("mbs@gmail.com") - n.stub(:fetch).and_return(true) - - n.on_person{|person| 1+1} - n.instance_variable_get(:@callbacks).count.should be 1 - end - - it 'should not blow up if the returned xrd is nil' do - http = FakeHttpRequest.new(:success) - fake_account = 'foo@example.com' - http.callbacks = [''] - EventMachine::HttpRequest.should_receive(:new).and_return(http) - n = EMWebfinger.new("foo@example.com") - - n.on_person{|person| - person.should == "webfinger does not seem to be enabled for #{fake_account}'s host" - } - end - end - - describe '#fetch' do - it 'should require a callback' do - proc{finger.fetch }.should raise_error "you need to set a callback before calling fetch" - end - end - context 'webfinger query chain processing' do describe '#webfinger_profile_url' do it 'should parse out the webfinger template' do @@ -101,81 +72,31 @@ describe EMWebfinger do context 'webfingering local people' do it 'should return a person from the database if it matches its handle' do person.save - EM.run do - finger.on_person { |p| - p.should == person - EM.stop - } + finger.fetch.id.should == person.id end end it 'should fetch a diaspora webfinger and make a person for them' do - good_request.callbacks = [diaspora_xrd, diaspora_finger, hcard_xml] - + 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 = EMWebfinger.new("tom@tom.joindiaspora.com") + f = EMWebfinger.new("tom@tom.joindiaspora.com").fetch + f.should be_valid - EventMachine::HttpRequest.should_receive(:new).exactly(3).times.and_return(good_request) - - EM.run { - f.on_person{ |p| - p.valid?.should be true - EM.stop - } - } end it 'should retry with http if https fails' do - good_request.callbacks = [nil, 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 = EMWebfinger.new("tom@tom.joindiaspora.com") - EventMachine::HttpRequest.should_receive(:new).exactly(4).times.and_return(good_request) - + diaspora_xrd.stub!(:body).and_return(diaspora_xrd) + RestClient.should_receive(:get).twice.and_return(nil, diaspora_xrd) f.should_receive(:xrd_url).twice - - EM.run { - f.on_person{ |p| - EM.stop - } - } + f.send(:get_xrd) + f.instance_variable_get(:@ssl).should == false end - it 'must try https first' do - single_request = FakeHttpRequest.new(:success) - single_request.callbacks = [diaspora_xrd] - good_request.callbacks = [diaspora_finger, hcard_xml] - EventMachine::HttpRequest.should_receive(:new).with("https://tom.joindiaspora.com/.well-known/host-meta").and_return(single_request) - EventMachine::HttpRequest.should_receive(:new).exactly(2).and_return(good_request) - - f = EMWebfinger.new("tom@tom.joindiaspora.com") - - EM.run { - f.on_person{ |p| - EM.stop - } - } - end - - it 'should retry with http if https fails with an http error code' do - bad_request = FakeHttpRequest.new(:failure) - - good_request.callbacks = [diaspora_xrd, diaspora_finger, hcard_xml] - - EventMachine::HttpRequest.should_receive(:new).with("https://tom.joindiaspora.com/.well-known/host-meta").and_return(bad_request) - EventMachine::HttpRequest.should_receive(:new).exactly(3).and_return(good_request) - - f = EMWebfinger.new("tom@tom.joindiaspora.com") - - EM.run { - f.on_person{ |p| - EM.stop - } - } - end end end -end diff --git a/spec/models/user/receive_spec.rb b/spec/models/user/receive_spec.rb index a2ff94d5f..45eb64a24 100644 --- a/spec/models/user/receive_spec.rb +++ b/spec/models/user/receive_spec.rb @@ -61,7 +61,7 @@ describe User do describe '#receive_salmon' do it 'should handle the case where the webfinger fails' do - Person.should_receive(:by_account_identifier).and_return("not a person") + EMWebfinger.stub!(:fetch).and_return(nil) proc{ user2.post :status_message, :message => "store this!", :to => aspect2.id