diff --git a/app/controllers/diaspora_federation/h_card_controller.rb b/app/controllers/diaspora_federation/h_card_controller.rb index 71a9479..70e8821 100644 --- a/app/controllers/diaspora_federation/h_card_controller.rb +++ b/app/controllers/diaspora_federation/h_card_controller.rb @@ -7,12 +7,12 @@ module DiasporaFederation # # GET /hcard/users/:guid def hcard - person = DiasporaFederation.person_class.find_local_by_guid(params[:guid]) + person_hcard = DiasporaFederation.callbacks.trigger(:person_hcard_fetch, params[:guid]) - return render nothing: true, status: 404 if person.nil? + return render nothing: true, status: 404 if person_hcard.nil? - logger.info "hcard profile request for: #{person.diaspora_handle}" - render html: WebFinger::HCard.from_person(person).to_html.html_safe + logger.info "hcard profile request for: #{person_hcard.nickname}:#{person_hcard.guid}" + render html: person_hcard.to_html.html_safe end end end diff --git a/lib/diaspora_federation/web_finger/h_card.rb b/lib/diaspora_federation/web_finger/h_card.rb index 61257ad..8655c75 100644 --- a/lib/diaspora_federation/web_finger/h_card.rb +++ b/lib/diaspora_federation/web_finger/h_card.rb @@ -13,21 +13,21 @@ module DiasporaFederation # correctly nested according to the hCard standard and class names are # partially wrong. Also, apart from that, it's just ugly. # - # @example Creating a hCard document from a person object - # html_string = HCard.from_person(person).to_html - # - # The person object should have the following attributes (with examples) - # guid: "0123456789abcdef", - # nickname: "user", - # full_name: "User Name", - # seed_url: "https://server.example/", - # photo_large_url: "https://server.example/uploads/l.jpg", - # photo_medium_url: "https://server.example/uploads/m.jpg", - # photo_small_url: "https://server.example/uploads/s.jpg", - # serialized_public_key: "-----BEGIN PUBLIC KEY-----\nABCDEF==\n-----END PUBLIC KEY-----", - # searchable: true, - # first_name: "User", - # last_name: "Name" + # @example Creating a hCard document from a person hash + # hc = HCard.new( + # guid: "0123456789abcdef", + # nickname: "user", + # full_name: "User Name", + # seed_url: "https://server.example/", + # photo_large_url: "https://server.example/uploads/l.jpg", + # photo_medium_url: "https://server.example/uploads/m.jpg", + # photo_small_url: "https://server.example/uploads/s.jpg", + # serialized_public_key: "-----BEGIN PUBLIC KEY-----\nABCDEF==\n-----END PUBLIC KEY-----", + # searchable: true, + # first_name: "User", + # last_name: "Name" + # ) + # html_string = hc.to_html # # @example Create a HCard instance from an hCard document # hc = HCard.from_html(html_string) @@ -39,65 +39,74 @@ module DiasporaFederation # @see http://microformats.org/wiki/h-card "h-card" (draft) # @see http://www.ietf.org/rfc/rfc2426.txt "vCard MIME Directory Profile" (obsolete) # @see http://www.ietf.org/rfc/rfc6350.txt "vCard Format Specification" - class HCard - private_class_method :new + class HCard < Entity + # @!attribute [r] 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 - # 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 + # @!attribute [r] nickname + # the first part of the diaspora handle + # @return [String] nickname + property :nickname - # the first part of the diaspora handle - # @return [String] nickname - attr_reader :nickname + # @!attribute [r] full_name + # @return [String] display name of the user + property :full_name - # @return [String] display name of the user - attr_reader :full_name - - # @deprecated should be changed to the profile url. The pod url is in - # the WebFinger (see {WebFinger#seed_url}, will affect older Diaspora* - # installations). + # @!attribute [r] url + # @deprecated should be changed to the profile url. The pod url is in + # the WebFinger (see {WebFinger#seed_url}, will affect older Diaspora* + # installations). # - # @return [String] link to the pod - attr_reader :url + # @return [String] link to the pod + property :url - # 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 + # @!attribute [r] 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 - # @return [String] url to the big avatar (300x300) - attr_reader :photo_large_url - # @return [String] url to the medium avatar (100x100) - attr_reader :photo_medium_url - # @return [String] url to the small avatar (50x50) - attr_reader :photo_small_url + # @!attribute [r] photo_large_url + # @return [String] url to the big avatar (300x300) + property :photo_large_url + # @!attribute [r] photo_medium_url + # @return [String] url to the medium avatar (100x100) + property :photo_medium_url + # @!attribute [r] photo_small_url + # @return [String] url to the small avatar (50x50) + property :photo_small_url - # @deprecated We decided to only use one name field, these should be removed - # in later iterations (will affect older Diaspora* installations). + # @!attribute [r] first_name + # @deprecated We decided to only use one name field, these should be removed + # in later iterations (will affect older Diaspora* installations). # - # @see #full_name - # @return [String] first name - attr_reader :first_name + # @see #full_name + # @return [String] first name + property :first_name - # @deprecated We decided to only use one name field, these should be removed - # in later iterations (will affect older Diaspora* installations). + # @!attribute [r] last_name + # @deprecated We decided to only use one name field, these should be removed + # in later iterations (will affect older Diaspora* installations). # - # @see #full_name - # @return [String] last name - attr_reader :last_name + # @see #full_name + # @return [String] last name + property :last_name - # @deprecated As this is a simple property, consider move to WebFinger instead - # of HCard. vCard has no comparable field for this information, but - # Webfinger may declare arbitrary properties (will affect older Diaspora* - # installations). + # @!attribute [r] searchable + # @deprecated As this is a simple property, consider move to WebFinger instead + # of HCard. vCard has no comparable field for this information, but + # Webfinger may declare arbitrary properties (will affect older Diaspora* + # installations). # - # flag if a user is searchable by name - # @return [Boolean] searchable flag - attr_reader :searchable + # flag if a user is searchable by name + # @return [Boolean] searchable flag + property :searchable # CSS selectors for finding all the hCard fields SELECTORS = { @@ -144,33 +153,6 @@ module DiasporaFederation builder.doc.to_xhtml(indent: 2, indent_text: " ") end - # Creates a new HCard instance from the given person - # @param [Person] person the person object - # @return [HCard] HCard instance - # @raise [InvalidData] if the account data Hash is invalid or incomplete - def self.from_person(person) - raise ArgumentError, "person is nil" if person.nil? - - hc = allocate - hc.instance_eval { - @guid = person.guid - @nickname = person.nickname - @full_name = person.full_name - @url = person.seed_url - @photo_large_url = person.photo_large_url - @photo_medium_url = person.photo_medium_url - @photo_small_url = person.photo_small_url - @public_key = person.serialized_public_key - @searchable = person.searchable - - # TODO: remove me! ################### - @first_name = person.first_name - @last_name = person.last_name - ####################################### - } - hc - end - # Creates a new HCard instance from the given HTML string. # @param html_string [String] HTML string # @return [HCard] HCard instance diff --git a/spec/controllers/diaspora_federation/h_card_controller_spec.rb b/spec/controllers/diaspora_federation/h_card_controller_spec.rb index 9172bce..0be9afb 100644 --- a/spec/controllers/diaspora_federation/h_card_controller_spec.rb +++ b/spec/controllers/diaspora_federation/h_card_controller_spec.rb @@ -24,8 +24,10 @@ module DiasporaFederation expect(response).to be_not_found end - it "calls WebFinger::HCard.from_profile" do - expect(WebFinger::HCard).to receive(:from_person).with(alice).and_call_original + it "calls the person_hcard_fetch callback" do + expect(DiasporaFederation.callbacks).to receive(:trigger) + .with(:person_hcard_fetch, alice.guid) + .and_call_original get :hcard, "guid" => alice.guid end end diff --git a/spec/lib/diaspora_federation/web_finger/h_card_spec.rb b/spec/lib/diaspora_federation/web_finger/h_card_spec.rb index 368052e..a091107 100644 --- a/spec/lib/diaspora_federation/web_finger/h_card_spec.rb +++ b/spec/lib/diaspora_federation/web_finger/h_card_spec.rb @@ -1,6 +1,9 @@ module DiasporaFederation describe WebFinger::HCard do let(:person) { FactoryGirl.create(:person) } + let(:photo_large_url) { "#{person.url}/upload/large.png" } + let(:photo_medium_url) { "#{person.url}/upload/medium.png" } + let(:photo_small_url) { "#{person.url}/upload/small.png" } let(:html) { <<-HTML @@ -61,25 +64,25 @@ module DiasporaFederation
Url
- #{person.seed_url} + #{person.url}
Photo
- +
Photo_medium
- +
Photo_small
- +
@@ -90,17 +93,29 @@ HTML } it "must not create blank instances" do - expect { WebFinger::HCard.new }.to raise_error NameError + expect { WebFinger::HCard.new({}) }.to raise_error ArgumentError end context "generation" do it "creates an instance from a data hash" do - hcard = WebFinger::HCard.from_person(person) + hcard = WebFinger::HCard.new( + guid: person.guid, + nickname: person.nickname, + full_name: person.full_name, + url: person.url, + photo_large_url: photo_large_url, + photo_medium_url: photo_medium_url, + photo_small_url: photo_small_url, + public_key: person.serialized_public_key, + searchable: person.searchable, + first_name: person.first_name, + last_name: person.last_name + ) expect(hcard.to_html).to eq(html) end it "fails if nil was given" do - expect { WebFinger::HCard.from_person(nil) }.to raise_error ArgumentError + expect { WebFinger::HCard.new(nil) }.to raise_error ArgumentError, "expected a Hash" end end @@ -110,10 +125,10 @@ HTML expect(hcard.guid).to eq(person.guid) expect(hcard.nickname).to eq(person.nickname) expect(hcard.full_name).to eq(person.full_name) - expect(hcard.url).to eq(person.seed_url) - expect(hcard.photo_large_url).to eq(person.photo_large_url) - expect(hcard.photo_medium_url).to eq(person.photo_medium_url) - expect(hcard.photo_small_url).to eq(person.photo_small_url) + expect(hcard.url).to eq(person.url) + expect(hcard.photo_large_url).to eq(photo_large_url) + expect(hcard.photo_medium_url).to eq(photo_medium_url) + expect(hcard.photo_small_url).to eq(photo_small_url) expect(hcard.public_key).to eq(person.serialized_public_key) expect(hcard.searchable).to eq(person.searchable) @@ -142,7 +157,7 @@ HTML
Nickname
-#{person.full_name} +#{person.full_name}
@@ -166,25 +181,25 @@ HTML
URL
-#{person.seed_url} +#{person.url}
Photo
- +
Photo
- +
Photo
- +
@@ -199,10 +214,10 @@ HTML HTML hcard = WebFinger::HCard.from_html(historic_html) - expect(hcard.url).to eq(person.seed_url) - expect(hcard.photo_large_url).to eq(person.photo_large_url) - expect(hcard.photo_medium_url).to eq(person.photo_medium_url) - expect(hcard.photo_small_url).to eq(person.photo_small_url) + expect(hcard.url).to eq(person.url) + expect(hcard.photo_large_url).to eq(photo_large_url) + expect(hcard.photo_medium_url).to eq(photo_medium_url) + expect(hcard.photo_small_url).to eq(photo_small_url) expect(hcard.searchable).to eq(person.searchable) expect(hcard.first_name).to eq(person.first_name) diff --git a/test/dummy/app/models/person.rb b/test/dummy/app/models/person.rb index e9b7324..a46a163 100644 --- a/test/dummy/app/models/person.rb +++ b/test/dummy/app/models/person.rb @@ -3,22 +3,16 @@ class Person < ActiveRecord::Base def alias_url; "#{url}people/#{guid}" end def hcard_url; "#{url}hcard/users/#{guid}" end - def profile_url; "#{url}u/#{diaspora_handle.split('@')[0]}" end - def atom_url; "#{url}public/#{diaspora_handle.split('@')[0]}.atom" end + def profile_url; "#{url}u/#{nickname}" end + def atom_url; "#{url}public/#{nickname}.atom" end def salmon_url; "#{url}receive/users/#{guid}" end 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 - def photo_small_url; "#{url}assets/user/default.png" end + + def photo_default_url; "#{url}assets/user/default.png" end def searchable; true end def full_name; "Dummy User" end def first_name; "Dummy" end def last_name; "User" end - - def self.find_local_by_guid(guid) - # no remote? and closed_account? check ... this class is only for testing - find_by_guid(guid) - end end diff --git a/test/dummy/config/initializers/diaspora_federation.rb b/test/dummy/config/initializers/diaspora_federation.rb index cd12e5d..a41a7c5 100644 --- a/test/dummy/config/initializers/diaspora_federation.rb +++ b/test/dummy/config/initializers/diaspora_federation.rb @@ -24,6 +24,22 @@ DiasporaFederation.configure do |config| end on :person_hcard_fetch do |guid| + person = Person.find_by(guid: guid) + if person + DiasporaFederation::WebFinger::HCard.new( + guid: person.guid, + nickname: person.nickname, + full_name: person.full_name, + url: person.url, + photo_large_url: person.photo_default_url, + photo_medium_url: person.photo_default_url, + photo_small_url: person.photo_default_url, + public_key: person.serialized_public_key, + searchable: person.searchable, + first_name: person.first_name, + last_name: person.last_name + ) + end end end end