webfingering is now syncrounous
This commit is contained in:
parent
9aa093a0a3
commit
be00a2f1b3
5 changed files with 76 additions and 176 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue