diff --git a/app/controllers/diaspora_federation/webfinger_controller.rb b/app/controllers/diaspora_federation/webfinger_controller.rb index 461344d..82609fd 100644 --- a/app/controllers/diaspora_federation/webfinger_controller.rb +++ b/app/controllers/diaspora_federation/webfinger_controller.rb @@ -33,12 +33,12 @@ module DiasporaFederation # # GET /webfinger?q= def legacy_webfinger - person = find_person(params[:q]) if params[:q] + person_wf = find_person_webfinger(params[:q]) if params[:q] - return render nothing: true, status: 404 if person.nil? + return render nothing: true, status: 404 if person_wf.nil? - logger.info "webfinger profile request for: #{person.diaspora_handle}" - render body: WebFinger::WebFinger.from_person(person).to_xml, content_type: "application/xrd+xml" + logger.info "webfinger profile request for: #{person_wf.acct_uri}" + render body: person_wf.to_xml, content_type: "application/xrd+xml" end private @@ -49,8 +49,8 @@ module DiasporaFederation @host_meta_xml ||= WebFinger::HostMeta.from_base_url(DiasporaFederation.server_uri.to_s).to_xml end - def find_person(query) - DiasporaFederation.person_class.find_local_by_diaspora_handle(query.strip.downcase.gsub("acct:", "")) + def find_person_webfinger(query) + DiasporaFederation.callbacks.trigger(:person_webfinger_fetch, query.strip.downcase.gsub("acct:", "")) end end end diff --git a/lib/diaspora_federation/web_finger/web_finger.rb b/lib/diaspora_federation/web_finger/web_finger.rb index ad7eed3..7264bba 100644 --- a/lib/diaspora_federation/web_finger/web_finger.rb +++ b/lib/diaspora_federation/web_finger/web_finger.rb @@ -8,19 +8,19 @@ module DiasporaFederation # In the meantime an actual RFC draft has been in development, which should # serve as a base for all future changes of this implementation. # - # @example Creating a WebFinger document from a person object - # xml_string = WebFinger.from_person(person).to_xml - # - # The person object should have the following attributes (with examples) - # diaspora_handle: "user@server.example" - # alias_url: "https://server.example/people/0123456789abcdef" - # hcard_url: "https://server.example/hcard/users/0123456789abcdef" - # seed_url: "https://server.example/" - # profile_url: "https://server.example/u/user" - # atom_url: "https://server.example/public/user.atom" - # salmon_url: "https://server.example/receive/users/0123456789abcdef" - # guid: "0123456789abcdef" - # serialized_public_key: "-----BEGIN PUBLIC KEY-----\nABCDEF==\n-----END PUBLIC KEY-----" + # @example Creating a WebFinger document from a person hash + # wf = WebFinger.new( + # acct_uri: "acct:user@server.example", + # alias_url: "https://server.example/people/0123456789abcdef", + # hcard_url: "https://server.example/hcard/users/user", + # seed_url: "https://server.example/", + # profile_url: "https://server.example/u/user", + # atom_url: "https://server.example/public/user.atom", + # salmon_url: "https://server.example/receive/users/0123456789abcdef", + # guid: "0123456789abcdef", + # public_key: "-----BEGIN PUBLIC KEY-----\nABCDEF==\n-----END PUBLIC KEY-----" + # ) + # xml_string = wf.to_xml # # @example Creating a WebFinger instance from an xml document # wf = WebFinger.from_xml(xml_string) @@ -33,62 +33,72 @@ module DiasporaFederation # @see http://code.google.com/p/webfinger/wiki/CommonLinkRelations # @see http://www.iana.org/assignments/link-relations/link-relations.xhtml # official list of IANA link relations - class WebFinger - private_class_method :new + class WebFinger < Entity + # @!attribute [r] acct_uri + # The Subject element should contain the webfinger address that was asked + # for. If it does not, then this webfinger profile MUST be ignored. + # @return [String] + property :acct_uri - # The Subject element should contain the webfinger address that was asked - # for. If it does not, then this webfinger profile MUST be ignored. - # @return [String] - attr_reader :acct_uri + # @!attribute [r] alias_url + # @return [String] link to the users profile + property :alias_url - # @return [String] link to the users profile - attr_reader :alias_url, :profile_url + # @!attribute [r] hcard_url + # @return [String] link to the +hCard+ + property :hcard_url - # @return [String] link to the +hCard+ - attr_reader :hcard_url + # @!attribute [r] seed_url + # @return [String] link to the pod + property :seed_url - # @return [String] link to the pod - attr_reader :seed_url + # @!attribute [r] profile_url + # @return [String] link to the users profile + property :profile_url - # This atom feed is an Activity Stream of the user's public posts. Diaspora - # pods SHOULD publish an Activity Stream of public posts, but there is - # currently no requirement to be able to read Activity Streams. - # @see http://activitystrea.ms/ Activity Streams specification + # @!attribute [r] atom_url + # This atom feed is an Activity Stream of the user's public posts. Diaspora + # pods SHOULD publish an Activity Stream of public posts, but there is + # currently no requirement to be able to read Activity Streams. + # @see http://activitystrea.ms/ Activity Streams specification # - # Note that this feed MAY also be made available through the PubSubHubbub - # mechanism by supplying a in the atom feed itself. - # @return [String] atom feed url - attr_reader :atom_url + # Note that this feed MAY also be made available through the PubSubHubbub + # mechanism by supplying a in the atom feed itself. + # @return [String] atom feed url + property :atom_url - # @return [String] salmon endpoint url - # @see http://salmon-protocol.googlecode.com/svn/trunk/draft-panzer-salmon-00.html#SMLR - # Panzer draft for Salmon, paragraph 3.3 - attr_reader :salmon_url + # @!attribute [r] salmon_url + # @return [String] salmon endpoint url + # @see http://salmon-protocol.googlecode.com/svn/trunk/draft-panzer-salmon-00.html#SMLR + # Panzer draft for Salmon, paragraph 3.3 + property :salmon_url - # @deprecated Either convert these to +Property+ elements or move to the - # +hCard+, which actually has fields for an +UID+ defined in the +vCard+ - # specification (will affect older Diaspora* installations). + # @!attribute [r] guid + # @deprecated Either convert these to +Property+ elements or move to the + # +hCard+, which actually has fields for an +UID+ defined in the +vCard+ + # specification (will affect older Diaspora* installations). # - # @see HCard#guid + # @see HCard#guid # - # This is just the guid. When a user creates an account on a pod, the pod - # MUST assign them a guid - a random hexadecimal string of at least 8 - # hexadecimal digits. - # @return [String] guid - attr_reader :guid + # This is just the guid. When a user creates an account on a pod, the pod + # MUST assign them a guid - a random hexadecimal string of at least 8 + # hexadecimal digits. + # @return [String] guid + property :guid - # @deprecated Either convert these to +Property+ elements or move to the - # +hCard+, which actually has fields for an +KEY+ defined in the +vCard+ - # specification (will affect older Diaspora* installations). + # @!attribute [r] public_key + # @deprecated Either convert these to +Property+ elements or move to the + # +hCard+, which actually has fields for an +KEY+ defined in the +vCard+ + # specification (will affect older Diaspora* installations). # - # @see HCard#pubkey + # @see HCard#pubkey # - # When a user is created on the pod, the pod MUST generate a pgp keypair - # for them. This key is used for signing messages. The format is a - # DER-encoded PKCS#1 key beginning with the text - # "-----BEGIN PUBLIC KEY-----" and ending with "-----END PUBLIC KEY-----". - # @return [String] public key - attr_reader :public_key + # When a user is created on the pod, the pod MUST generate a pgp keypair + # for them. This key is used for signing messages. The format is a + # DER-encoded PKCS#1 key beginning with the text + # "-----BEGIN PUBLIC KEY-----" and ending with "-----END PUBLIC KEY-----". + # @return [String] public key + property :public_key # +hcard_url+ link relation REL_HCARD = "http://microformats.org/profile/hcard" @@ -130,31 +140,6 @@ module DiasporaFederation doc.to_xml end - # Create a WebFinger instance from the given person. - # @param [Person] person the person object - # @return [WebFinger] WebFinger instance - # @raise [ArgumentError] if the given person is nil - def self.from_person(person) - raise ArgumentError, "person is nil" if person.nil? - - wf = allocate - wf.instance_eval { - @acct_uri = "acct:#{person.diaspora_handle}" - @alias_url = person.alias_url - @hcard_url = person.hcard_url - @seed_url = person.seed_url - @profile_url = person.profile_url - @atom_url = person.atom_url - @salmon_url = person.salmon_url - - # TODO: remove me! ######### - @guid = person.guid - @public_key = person.serialized_public_key - ############################# - } - wf - end - # Create a WebFinger instance from the given XML string. # @param [String] webfinger_xml WebFinger XML string # @return [WebFinger] WebFinger instance diff --git a/spec/controllers/diaspora_federation/webfinger_controller_spec.rb b/spec/controllers/diaspora_federation/webfinger_controller_spec.rb index 75f49b4..62b42cb 100644 --- a/spec/controllers/diaspora_federation/webfinger_controller_spec.rb +++ b/spec/controllers/diaspora_federation/webfinger_controller_spec.rb @@ -58,8 +58,10 @@ module DiasporaFederation expect(response).to be_not_found end - it "calls WebFinger::WebFinger.from_person" do - expect(WebFinger::WebFinger).to receive(:from_person).with(alice).and_call_original + it "calls the person_webfinger_fetch callback" do + expect(DiasporaFederation.callbacks).to receive(:trigger) + .with(:person_webfinger_fetch, "alice@localhost:3000") + .and_call_original get :legacy_webfinger, "q" => "acct:alice@localhost:3000" end end diff --git a/spec/lib/diaspora_federation/web_finger/web_finger_spec.rb b/spec/lib/diaspora_federation/web_finger/web_finger_spec.rb index fa02ea8..a73750b 100644 --- a/spec/lib/diaspora_federation/web_finger/web_finger_spec.rb +++ b/spec/lib/diaspora_federation/web_finger/web_finger_spec.rb @@ -11,7 +11,7 @@ module DiasporaFederation #{acct} #{person.alias_url} - + @@ -22,17 +22,27 @@ XML } it "must not create blank instances" do - expect { WebFinger::WebFinger.new }.to raise_error NameError + expect { WebFinger::WebFinger.new({}) }.to raise_error ArgumentError end context "generation" do it "creates a nice XML document" do - wf = WebFinger::WebFinger.from_person(person) + wf = WebFinger::WebFinger.new( + acct_uri: "acct:#{person.diaspora_handle}", + alias_url: person.alias_url, + hcard_url: person.hcard_url, + seed_url: person.url, + profile_url: person.profile_url, + atom_url: person.atom_url, + salmon_url: person.salmon_url, + guid: person.guid, + public_key: person.serialized_public_key + ) expect(wf.to_xml).to eq(xml) end it "fails if nil was given" do - expect { WebFinger::WebFinger.from_person(nil) }.to raise_error ArgumentError + expect { WebFinger::WebFinger.new(nil) }.to raise_error ArgumentError, "expected a Hash" end end @@ -42,7 +52,7 @@ XML expect(wf.acct_uri).to eq(acct) expect(wf.alias_url).to eq(person.alias_url) expect(wf.hcard_url).to eq(person.hcard_url) - expect(wf.seed_url).to eq(person.seed_url) + expect(wf.seed_url).to eq(person.url) expect(wf.profile_url).to eq(person.profile_url) expect(wf.atom_url).to eq(person.atom_url) expect(wf.salmon_url).to eq(person.salmon_url) @@ -58,7 +68,7 @@ XML #{acct} #{person.alias_url} - + @@ -73,7 +83,7 @@ XML expect(wf.acct_uri).to eq(acct) expect(wf.alias_url).to eq(person.alias_url) expect(wf.hcard_url).to eq(person.hcard_url) - expect(wf.seed_url).to eq(person.seed_url) + expect(wf.seed_url).to eq(person.url) expect(wf.profile_url).to eq(person.profile_url) expect(wf.atom_url).to eq(person.atom_url) expect(wf.salmon_url).to eq(person.salmon_url) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 825cb21..b3e6ca4 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -28,7 +28,7 @@ require "entities" # some helper methods def alice - @alice ||= Person.find_local_by_diaspora_handle("alice@localhost:3000") + @alice ||= Person.find_by(diaspora_handle: "alice@localhost:3000") end # Force fixture rebuild diff --git a/test/dummy/app/models/person.rb b/test/dummy/app/models/person.rb index 17d9259..e9b7324 100644 --- a/test/dummy/app/models/person.rb +++ b/test/dummy/app/models/person.rb @@ -7,8 +7,6 @@ class Person < ActiveRecord::Base def atom_url; "#{url}public/#{diaspora_handle.split('@')[0]}.atom" end def salmon_url; "#{url}receive/users/#{guid}" end - alias_attribute :seed_url, :url - def nickname; diaspora_handle.split("@")[0] end def photo_large_url; "#{url}assets/user/default.png" end def photo_medium_url; "#{url}assets/user/default.png" end @@ -19,11 +17,6 @@ class Person < ActiveRecord::Base def first_name; "Dummy" end def last_name; "User" end - def self.find_local_by_diaspora_handle(identifier) - # no remote? and closed_account? check ... this class is only for testing - find_by_diaspora_handle(identifier) - end - def self.find_local_by_guid(guid) # no remote? and closed_account? check ... this class is only for testing find_by_guid(guid) diff --git a/test/dummy/config/initializers/diaspora_federation.rb b/test/dummy/config/initializers/diaspora_federation.rb index 198ad90..cd12e5d 100644 --- a/test/dummy/config/initializers/diaspora_federation.rb +++ b/test/dummy/config/initializers/diaspora_federation.rb @@ -1,3 +1,5 @@ +require "diaspora_federation/web_finger" + # configure the federation engine DiasporaFederation.configure do |config| # the pod url @@ -5,6 +7,20 @@ DiasporaFederation.configure do |config| config.define_callbacks do on :person_webfinger_fetch do |handle| + person = Person.find_by(diaspora_handle: handle) + if person + DiasporaFederation::WebFinger::WebFinger.new( + acct_uri: "acct:#{person.diaspora_handle}", + alias_url: person.alias_url, + hcard_url: person.hcard_url, + seed_url: person.url, + profile_url: person.profile_url, + atom_url: person.atom_url, + salmon_url: person.salmon_url, + guid: person.guid, + public_key: person.serialized_public_key + ) + end end on :person_hcard_fetch do |guid|