use person object with attributes to generate hcard
This commit is contained in:
parent
6e6171fc93
commit
99d5ffdc04
7 changed files with 96 additions and 158 deletions
|
|
@ -14,7 +14,7 @@ module DiasporaFederation
|
|||
return render nothing: true, status: 404 if person.nil?
|
||||
|
||||
logger.info "hcard profile request for: #{person.diaspora_handle}"
|
||||
render html: WebFinger::HCard.from_profile(person.hcard_profile_hash).to_html.html_safe
|
||||
render html: WebFinger::HCard.from_person(person).to_html.html_safe
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -84,18 +84,11 @@ module DiasporaFederation
|
|||
def validate_config
|
||||
configuration_error "missing server_uri" unless @server_uri.respond_to? :host
|
||||
validate_class(@person_class, "person_class", %i(
|
||||
find_local_by_diaspora_handle
|
||||
find_local_by_guid
|
||||
diaspora_handle
|
||||
alias_url
|
||||
hcard_url
|
||||
seed_url
|
||||
profile_url
|
||||
atom_url
|
||||
salmon_url
|
||||
guid
|
||||
public_key
|
||||
hcard_profile_hash
|
||||
find_local_by_diaspora_handle find_local_by_guid
|
||||
diaspora_handle nickname guid public_key searchable
|
||||
alias_url hcard_url seed_url profile_url atom_url salmon_url
|
||||
photo_large_url photo_medium_url photo_small_url
|
||||
full_name first_name last_name
|
||||
))
|
||||
logger.info "successfully configured the federation engine"
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ module DiasporaFederation
|
|||
#
|
||||
# * if the +webfinger_url+ is missing or malformed in {HostMeta.from_base_url} or {HostMeta.from_xml}
|
||||
# * if the parsed XML from {WebFinger.from_xml} is incomplete
|
||||
# * if the params passed to {HCard.from_profile} or {HCard.from_html}
|
||||
# are in some way malformed, invalid or incomplete.
|
||||
# * if the html passed to {HCard.from_html} in some way is malformed, invalid or incomplete.
|
||||
class InvalidData < RuntimeError
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -14,21 +14,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 account data
|
||||
# hc = HCard.from_profile({
|
||||
# guid: "0123456789abcdef",
|
||||
# nickname: "user",
|
||||
# full_name: "User Name",
|
||||
# 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",
|
||||
# pubkey: "-----BEGIN PUBLIC KEY-----\nABCDEF==\n-----END PUBLIC KEY-----",
|
||||
# searchable: true,
|
||||
# first_name: "User",
|
||||
# last_name: "Name"
|
||||
# })
|
||||
# html_string = hc.to_html
|
||||
# @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",
|
||||
# public_key: "-----BEGIN PUBLIC KEY-----\nABCDEF==\n-----END PUBLIC KEY-----",
|
||||
# searchable: true,
|
||||
# first_name: "User",
|
||||
# last_name: "Name"
|
||||
#
|
||||
# @example Create a HCard instance from an hCard document
|
||||
# hc = HCard.from_html(html_string)
|
||||
|
|
@ -68,7 +68,7 @@ module DiasporaFederation
|
|||
# DER-encoded PKCS#1 key beginning with the text
|
||||
# "-----BEGIN PUBLIC KEY-----" and ending with "-----END PUBLIC KEY-----".
|
||||
# @return [String] public key
|
||||
attr_reader :pubkey
|
||||
attr_reader :public_key
|
||||
|
||||
# @return [String] url to the big avatar (300x300)
|
||||
attr_reader :photo_large_url
|
||||
|
|
@ -128,7 +128,7 @@ module DiasporaFederation
|
|||
add_simple_property(content, :searchable, "searchable", @searchable)
|
||||
|
||||
add_property(content, :key) do |html|
|
||||
html.pre(@pubkey.to_s, class: "key")
|
||||
html.pre(@public_key.to_s, class: "key")
|
||||
end
|
||||
|
||||
# TODO: remove me! ###################
|
||||
|
|
@ -145,28 +145,28 @@ module DiasporaFederation
|
|||
builder.doc.to_xhtml(indent: 2, indent_text: " ")
|
||||
end
|
||||
|
||||
# Creates a new HCard instance from the given Hash containing profile data
|
||||
# @param [Hash] data account data
|
||||
# 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_profile(data)
|
||||
raise InvalidData unless account_data_complete?(data)
|
||||
def self.from_person(person)
|
||||
raise ArgumentError, "person is nil" if person.nil?
|
||||
|
||||
hc = allocate
|
||||
hc.instance_eval {
|
||||
@guid = data[:guid]
|
||||
@nickname = data[:nickname]
|
||||
@full_name = data[:full_name]
|
||||
@url = data[:url]
|
||||
@photo_large_url = data[:photo_large_url]
|
||||
@photo_medium_url = data[:photo_medium_url]
|
||||
@photo_small_url = data[:photo_small_url]
|
||||
@pubkey = data[:pubkey]
|
||||
@searchable = data[:searchable]
|
||||
@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.public_key
|
||||
@searchable = person.searchable
|
||||
|
||||
# TODO: remove me! ###################
|
||||
@first_name = data[:first_name]
|
||||
@last_name = data[:last_name]
|
||||
@first_name = person.first_name
|
||||
@last_name = person.last_name
|
||||
#######################################
|
||||
}
|
||||
hc
|
||||
|
|
@ -188,7 +188,7 @@ module DiasporaFederation
|
|||
@photo_large_url = photo_from_doc(doc, :photo)
|
||||
@photo_medium_url = photo_from_doc(doc, :photo_medium)
|
||||
@photo_small_url = photo_from_doc(doc, :photo_small)
|
||||
@pubkey = content_from_doc(doc, :key) unless element_from_doc(doc, :key).nil?
|
||||
@public_key = content_from_doc(doc, :key) unless element_from_doc(doc, :key).nil?
|
||||
@searchable = content_from_doc(doc, :searchable) == "true"
|
||||
|
||||
# TODO: change me! ###################
|
||||
|
|
@ -271,19 +271,6 @@ module DiasporaFederation
|
|||
end
|
||||
end
|
||||
|
||||
# Checks the given account data Hash for correct type and completeness.
|
||||
# @param [Hash] data account data
|
||||
# @return [Boolean] validation result
|
||||
def self.account_data_complete?(data)
|
||||
data.instance_of?(Hash) &&
|
||||
%i(
|
||||
guid nickname full_name url
|
||||
photo_large_url photo_medium_url photo_small_url
|
||||
pubkey searchable first_name last_name
|
||||
).all? {|k| data.key? k }
|
||||
end
|
||||
private_class_method :account_data_complete?
|
||||
|
||||
# Make sure some of the most important elements are present in the parsed
|
||||
# HTML document.
|
||||
# @param [LibXML::XML::Document] doc HTML document
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ module DiasporaFederation
|
|||
end
|
||||
|
||||
it "calls WebFinger::HCard.from_profile" do
|
||||
expect(WebFinger::HCard).to receive(:from_profile).with(alice.hcard_profile_hash).and_call_original
|
||||
expect(WebFinger::HCard).to receive(:from_person).with(alice).and_call_original
|
||||
get :hcard, "guid" => alice.guid
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,16 +1,6 @@
|
|||
module DiasporaFederation
|
||||
describe WebFinger::HCard do
|
||||
let(:guid) { "abcdef0123456789" }
|
||||
let(:nickname) { "user" }
|
||||
let(:first_name) { "Test" }
|
||||
let(:last_name) { "Testington" }
|
||||
let(:name) { "#{first_name} #{last_name}" }
|
||||
let(:url) { "https://pod.example.tld/users/me" }
|
||||
let(:photo_url) { "https://pod.example.tld/uploads/f.jpg" }
|
||||
let(:photo_url_m) { "https://pod.example.tld/uploads/m.jpg" }
|
||||
let(:photo_url_s) { "https://pod.example.tld/uploads/s.jpg" }
|
||||
let(:key) { "-----BEGIN PUBLIC KEY-----\nABCDEF==\n-----END PUBLIC KEY-----" }
|
||||
let(:searchable) { true }
|
||||
let(:person) { FactoryGirl.create(:person) }
|
||||
|
||||
let(:html) {
|
||||
<<-HTML
|
||||
|
|
@ -19,77 +9,77 @@ module DiasporaFederation
|
|||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta charset="UTF-8" />
|
||||
<title>#{name}</title>
|
||||
<title>#{person.full_name}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="content">
|
||||
<h1>#{name}</h1>
|
||||
<h1>#{person.full_name}</h1>
|
||||
<div id="content_inner" class="entity_profile vcard author">
|
||||
<h2>User profile</h2>
|
||||
<dl class="entity_uid">
|
||||
<dt>Uid</dt>
|
||||
<dd>
|
||||
<span class="uid">#{guid}</span>
|
||||
<span class="uid">#{person.guid}</span>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="entity_nickname">
|
||||
<dt>Nickname</dt>
|
||||
<dd>
|
||||
<span class="nickname">#{nickname}</span>
|
||||
<span class="nickname">#{person.nickname}</span>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="entity_full_name">
|
||||
<dt>Full_name</dt>
|
||||
<dd>
|
||||
<span class="fn">#{name}</span>
|
||||
<span class="fn">#{person.full_name}</span>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="entity_searchable">
|
||||
<dt>Searchable</dt>
|
||||
<dd>
|
||||
<span class="searchable">#{searchable}</span>
|
||||
<span class="searchable">#{person.searchable}</span>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="entity_key">
|
||||
<dt>Key</dt>
|
||||
<dd>
|
||||
<pre class="key">#{key}</pre>
|
||||
<pre class="key">#{person.public_key}</pre>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="entity_first_name">
|
||||
<dt>First_name</dt>
|
||||
<dd>
|
||||
<span class="given_name">#{first_name}</span>
|
||||
<span class="given_name">#{person.first_name}</span>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="entity_family_name">
|
||||
<dt>Family_name</dt>
|
||||
<dd>
|
||||
<span class="family_name">#{last_name}</span>
|
||||
<span class="family_name">#{person.last_name}</span>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="entity_url">
|
||||
<dt>Url</dt>
|
||||
<dd>
|
||||
<a id="pod_location" class="url" rel="me" href="#{url}">#{url}</a>
|
||||
<a id="pod_location" class="url" rel="me" href="#{person.seed_url}">#{person.seed_url}</a>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="entity_photo">
|
||||
<dt>Photo</dt>
|
||||
<dd>
|
||||
<img class="photo avatar" width="300" height="300" src="#{photo_url}" />
|
||||
<img class="photo avatar" width="300" height="300" src="#{person.photo_large_url}" />
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="entity_photo_medium">
|
||||
<dt>Photo_medium</dt>
|
||||
<dd>
|
||||
<img class="photo avatar" width="100" height="100" src="#{photo_url_m}" />
|
||||
<img class="photo avatar" width="100" height="100" src="#{person.photo_medium_url}" />
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="entity_photo_small">
|
||||
<dt>Photo_small</dt>
|
||||
<dd>
|
||||
<img class="photo avatar" width="50" height="50" src="#{photo_url_s}" />
|
||||
<img class="photo avatar" width="50" height="50" src="#{person.photo_small_url}" />
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
|
@ -105,60 +95,35 @@ HTML
|
|||
|
||||
context "generation" do
|
||||
it "creates an instance from a data hash" do
|
||||
hcard = WebFinger::HCard.from_profile(
|
||||
guid: guid,
|
||||
nickname: nickname,
|
||||
full_name: name,
|
||||
url: url,
|
||||
photo_large_url: photo_url,
|
||||
photo_medium_url: photo_url_m,
|
||||
photo_small_url: photo_url_s,
|
||||
pubkey: key,
|
||||
searchable: searchable,
|
||||
first_name: first_name,
|
||||
last_name: last_name
|
||||
)
|
||||
hcard = WebFinger::HCard.from_person(person)
|
||||
expect(hcard.to_html).to eq(html)
|
||||
end
|
||||
|
||||
it "fails if some params are missing" do
|
||||
expect {
|
||||
WebFinger::HCard.from_profile(
|
||||
guid: guid,
|
||||
nickname: nickname
|
||||
)
|
||||
}.to raise_error WebFinger::InvalidData
|
||||
end
|
||||
|
||||
it "fails if nothing was given" do
|
||||
expect { WebFinger::HCard.from_profile({}) }.to raise_error WebFinger::InvalidData
|
||||
end
|
||||
|
||||
it "fails if nil was given" do
|
||||
expect { WebFinger::HCard.from_profile(nil) }.to raise_error WebFinger::InvalidData
|
||||
expect { WebFinger::HCard.from_person(nil) }.to raise_error ArgumentError
|
||||
end
|
||||
end
|
||||
|
||||
context "parsing" do
|
||||
it "reads its own output" do
|
||||
hcard = WebFinger::HCard.from_html(html)
|
||||
expect(hcard.guid).to eq(guid)
|
||||
expect(hcard.nickname).to eq(nickname)
|
||||
expect(hcard.full_name).to eq(name)
|
||||
expect(hcard.url).to eq(url)
|
||||
expect(hcard.photo_large_url).to eq(photo_url)
|
||||
expect(hcard.photo_medium_url).to eq(photo_url_m)
|
||||
expect(hcard.photo_small_url).to eq(photo_url_s)
|
||||
expect(hcard.pubkey).to eq(key)
|
||||
expect(hcard.searchable).to eq(searchable)
|
||||
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.public_key).to eq(person.public_key)
|
||||
expect(hcard.searchable).to eq(person.searchable)
|
||||
|
||||
expect(hcard.first_name).to eq(first_name)
|
||||
expect(hcard.last_name).to eq(last_name)
|
||||
expect(hcard.first_name).to eq(person.first_name)
|
||||
expect(hcard.last_name).to eq(person.last_name)
|
||||
end
|
||||
|
||||
it "searchable is false, if it is empty in html" do
|
||||
changed_html = html.sub(
|
||||
"class=\"searchable\">#{searchable}<",
|
||||
"class=\"searchable\">#{person.searchable}<",
|
||||
"class=\"searchable\"><"
|
||||
)
|
||||
|
||||
|
|
@ -170,62 +135,62 @@ HTML
|
|||
it "reads old-style HTML" do
|
||||
historic_html = <<-HTML
|
||||
<div id="content">
|
||||
<h1>#{name}</h1>
|
||||
<h1>#{person.full_name}</h1>
|
||||
<div id="content_inner">
|
||||
<div class="entity_profile vcard author" id="i">
|
||||
<h2>User profile</h2>
|
||||
<dl class="entity_nickname">
|
||||
<dt>Nickname</dt>
|
||||
<dd>
|
||||
<a class="nickname url uid" href="#{url}" rel="me">#{name}</a>
|
||||
<a class="nickname url uid" href="#{person.seed_url}" rel="me">#{person.full_name}</a>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="entity_given_name">
|
||||
<dt>First name</dt>
|
||||
<dd>
|
||||
<span class="given_name">#{first_name}</span>
|
||||
<span class="given_name">#{person.first_name}</span>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="entity_family_name">
|
||||
<dt>Family name</dt>
|
||||
<dd>
|
||||
<span class="family_name">#{last_name}</span>
|
||||
<span class="family_name">#{person.last_name}</span>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="entity_fn">
|
||||
<dt>Full name</dt>
|
||||
<dd>
|
||||
<span class="fn">#{name}</span>
|
||||
<span class="fn">#{person.full_name}</span>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="entity_url">
|
||||
<dt>URL</dt>
|
||||
<dd>
|
||||
<a class="url" href="#{url}" id="pod_location" rel="me">#{url}</a>
|
||||
<a class="url" href="#{person.seed_url}" id="pod_location" rel="me">#{person.seed_url}</a>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="entity_photo">
|
||||
<dt>Photo</dt>
|
||||
<dd>
|
||||
<img class="photo avatar" height="300px" src="#{photo_url}" width="300px">
|
||||
<img class="photo avatar" height="300px" src="#{person.photo_large_url}" width="300px">
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="entity_photo_medium">
|
||||
<dt>Photo</dt>
|
||||
<dd>
|
||||
<img class="photo avatar" height="100px" src="#{photo_url_m}" width="100px">
|
||||
<img class="photo avatar" height="100px" src="#{person.photo_medium_url}" width="100px">
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="entity_photo_small">
|
||||
<dt>Photo</dt>
|
||||
<dd>
|
||||
<img class="photo avatar" height="50px" src="#{photo_url_s}" width="50px">
|
||||
<img class="photo avatar" height="50px" src="#{person.photo_small_url}" width="50px">
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="entity_searchable">
|
||||
<dt>Searchable</dt>
|
||||
<dd>
|
||||
<span class="searchable">#{searchable}</span>
|
||||
<span class="searchable">#{person.searchable}</span>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
|
@ -234,20 +199,20 @@ HTML
|
|||
HTML
|
||||
|
||||
hcard = WebFinger::HCard.from_html(historic_html)
|
||||
expect(hcard.url).to eq(url)
|
||||
expect(hcard.photo_large_url).to eq(photo_url)
|
||||
expect(hcard.photo_medium_url).to eq(photo_url_m)
|
||||
expect(hcard.photo_small_url).to eq(photo_url_s)
|
||||
expect(hcard.searchable).to eq(searchable)
|
||||
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.searchable).to eq(person.searchable)
|
||||
|
||||
expect(hcard.first_name).to eq(first_name)
|
||||
expect(hcard.last_name).to eq(last_name)
|
||||
expect(hcard.first_name).to eq(person.first_name)
|
||||
expect(hcard.last_name).to eq(person.last_name)
|
||||
end
|
||||
|
||||
it "fails if the document is incomplete" do
|
||||
invalid_html = <<-HTML
|
||||
<div id="content">
|
||||
<span class="fn">#{name}</span>
|
||||
<span class="fn">#{person.full_name}</span>
|
||||
</div>
|
||||
HTML
|
||||
expect { WebFinger::HCard.from_html(invalid_html) }.to raise_error WebFinger::InvalidData
|
||||
|
|
|
|||
|
|
@ -10,21 +10,15 @@ class Person < ActiveRecord::Base
|
|||
alias_attribute :seed_url, :url
|
||||
alias_attribute :public_key, :serialized_public_key
|
||||
|
||||
def hcard_profile_hash
|
||||
{
|
||||
guid: guid,
|
||||
nickname: diaspora_handle.split("@")[0],
|
||||
full_name: "Dummy User",
|
||||
url: url,
|
||||
photo_large_url: "#{url}assets/user/default.png",
|
||||
photo_medium_url: "#{url}assets/user/default.png",
|
||||
photo_small_url: "#{url}assets/user/default.png",
|
||||
pubkey: serialized_public_key,
|
||||
searchable: true,
|
||||
first_name: "Dummy",
|
||||
last_name: "User"
|
||||
}
|
||||
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 searchable; true end
|
||||
def full_name; "Dummy User" end
|
||||
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
|
||||
|
|
|
|||
Loading…
Reference in a new issue