use person object with attributes to generate webfinger

This commit is contained in:
Benjamin Neff 2015-07-02 01:11:28 +02:00
parent 3354eb472b
commit 6e6171fc93
8 changed files with 94 additions and 128 deletions

View file

@ -155,3 +155,10 @@ Metrics/AbcSize:
Metrics/ModuleLength:
Max: 1500
Style/SingleLineMethods:
Exclude:
- "test/dummy/app/models/*"
Style/EmptyLineBetweenDefs:
Exclude:
- "test/dummy/app/models/*"

View file

@ -41,7 +41,7 @@ module DiasporaFederation
return render nothing: true, status: 404 if person.nil?
logger.info "webfinger profile request for: #{person.diaspora_handle}"
render body: WebFinger::WebFinger.from_person(person.webfinger_hash).to_xml, content_type: "application/xrd+xml"
render body: WebFinger::WebFinger.from_person(person).to_xml, content_type: "application/xrd+xml"
end
private

View file

@ -86,7 +86,15 @@ module DiasporaFederation
validate_class(@person_class, "person_class", %i(
find_local_by_diaspora_handle
find_local_by_guid
webfinger_hash
diaspora_handle
alias_url
hcard_url
seed_url
profile_url
atom_url
salmon_url
guid
public_key
hcard_profile_hash
))
logger.info "successfully configured the federation engine"

View file

@ -9,7 +9,6 @@ module DiasporaFederation
# Raised, if something is wrong with the webfinger data
#
# * if the +webfinger_url+ is missing or malformed in {HostMeta.from_base_url} or {HostMeta.from_xml}
# * if the +data+ given to {WebFinger.from_person} is an invalid type or doesn't contain all required entries
# * 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.

View file

@ -9,19 +9,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 account data
# wf = WebFinger.from_person({
# acct_uri: "acct: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",
# pubkey: "-----BEGIN PUBLIC KEY-----\nABCDEF==\n-----END PUBLIC KEY-----"
# })
# xml_string = wf.to_xml
# @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"
# public_key: "-----BEGIN PUBLIC KEY-----\nABCDEF==\n-----END PUBLIC KEY-----"
#
# @example Creating a WebFinger instance from an xml document
# wf = WebFinger.from_xml(xml_string)
@ -89,7 +89,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
# +hcard_url+ link relation
REL_HCARD = "http://microformats.org/profile/hcard"
@ -131,26 +131,26 @@ module DiasporaFederation
doc.to_xml
end
# Create a WebFinger instance from the given person data Hash.
# @param [Hash] data account data
# Create a WebFinger instance from the given person.
# @param [Person] person the person object
# @return [WebFinger] WebFinger instance
# @raise [InvalidData] if the given data Hash is invalid or incomplete
def self.from_person(data)
raise InvalidData, "person data incomplete" unless account_data_complete?(data)
# @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 = data[:acct_uri]
@alias_url = data[:alias_url]
@hcard_url = data[:hcard_url]
@seed_url = data[:seed_url]
@profile_url = data[:profile_url]
@atom_url = data[:atom_url]
@salmon_url = data[:salmon_url]
@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 = data[:guid]
@pubkey = data[:pubkey]
@guid = person.guid
@public_key = person.public_key
#############################
}
wf
@ -163,7 +163,7 @@ module DiasporaFederation
def self.from_xml(webfinger_xml)
data = parse_xml_and_validate(webfinger_xml)
hcard_url, seed_url, guid, profile_url, atom_url, salmon_url, pubkey = parse_links(data)
hcard_url, seed_url, guid, profile_url, atom_url, salmon_url, public_key = parse_links(data)
wf = allocate
wf.instance_eval {
@ -177,7 +177,7 @@ module DiasporaFederation
# TODO: remove me! ##########
@guid = guid
@pubkey = Base64.strict_decode64(pubkey)
@public_key = Base64.strict_decode64(public_key)
##############################
}
wf
@ -185,18 +185,6 @@ module DiasporaFederation
private
# 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(
acct_uri alias_url hcard_url seed_url
guid profile_url atom_url salmon_url pubkey
).all? {|k| data.key? k }
end
private_class_method :account_data_complete?
# Parses the XML string to a Hash and does some rudimentary checking on
# the data Hash.
# @param [String] webfinger_xml WebFinger XML string
@ -236,7 +224,7 @@ module DiasporaFederation
# TODO: remove me! ##############
doc.links << {rel: REL_PUBKEY,
type: "RSA",
href: Base64.strict_encode64(@pubkey)}
href: Base64.strict_encode64(@public_key)}
##################################
end

View file

@ -59,7 +59,7 @@ module DiasporaFederation
end
it "calls WebFinger::WebFinger.from_person" do
expect(WebFinger::WebFinger).to receive(:from_person).with(alice.webfinger_hash).and_call_original
expect(WebFinger::WebFinger).to receive(:from_person).with(alice).and_call_original
get :legacy_webfinger, "q" => "acct:alice@localhost:3000"
end
end

View file

@ -1,29 +1,22 @@
module DiasporaFederation
describe WebFinger::WebFinger do
let(:acct) { "acct:user@pod.example.tld" }
let(:alias_url) { "http://pod.example.tld/" }
let(:hcard_url) { "https://pod.example.tld/hcard/users/abcdef0123456789" }
let(:seed_url) { "https://pod.geraspora.de/" }
let(:guid) { "abcdef0123456789" }
let(:profile_url) { "https://pod.example.tld/u/user" }
let(:atom_url) { "https://pod.example.tld/public/user.atom" }
let(:salmon_url) { "https://pod.example.tld/receive/users/abcdef0123456789" }
let(:pubkey) { "-----BEGIN PUBLIC KEY-----\nABCDEF==\n-----END PUBLIC KEY-----" }
let(:pubkey_base64) { Base64.strict_encode64(pubkey) }
let(:person) { FactoryGirl.create(:person) }
let(:acct) { "acct:#{person.diaspora_handle}" }
let(:public_key_base64) { Base64.strict_encode64(person.public_key) }
let(:xml) {
<<-XML
<?xml version="1.0" encoding="UTF-8"?>
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
<Subject>#{acct}</Subject>
<Alias>#{alias_url}</Alias>
<Link rel="http://microformats.org/profile/hcard" type="text/html" href="#{hcard_url}"/>
<Link rel="http://joindiaspora.com/seed_location" type="text/html" href="#{seed_url}"/>
<Link rel="http://joindiaspora.com/guid" type="text/html" href="#{guid}"/>
<Link rel="http://webfinger.net/rel/profile-page" type="text/html" href="#{profile_url}"/>
<Link rel="http://schemas.google.com/g/2010#updates-from" type="application/atom+xml" href="#{atom_url}"/>
<Link rel="salmon" href="#{salmon_url}"/>
<Link rel="diaspora-public-key" type="RSA" href="#{pubkey_base64}"/>
<Alias>#{person.alias_url}</Alias>
<Link rel="http://microformats.org/profile/hcard" type="text/html" href="#{person.hcard_url}"/>
<Link rel="http://joindiaspora.com/seed_location" type="text/html" href="#{person.seed_url}"/>
<Link rel="http://joindiaspora.com/guid" type="text/html" href="#{person.guid}"/>
<Link rel="http://webfinger.net/rel/profile-page" type="text/html" href="#{person.profile_url}"/>
<Link rel="http://schemas.google.com/g/2010#updates-from" type="application/atom+xml" href="#{person.atom_url}"/>
<Link rel="salmon" href="#{person.salmon_url}"/>
<Link rel="diaspora-public-key" type="RSA" href="#{public_key_base64}"/>
</XRD>
XML
}
@ -34,36 +27,12 @@ XML
context "generation" do
it "creates a nice XML document" do
wf = WebFinger::WebFinger.from_person(
acct_uri: acct,
alias_url: alias_url,
hcard_url: hcard_url,
seed_url: seed_url,
profile_url: profile_url,
atom_url: atom_url,
salmon_url: salmon_url,
guid: guid,
pubkey: pubkey
)
wf = WebFinger::WebFinger.from_person(person)
expect(wf.to_xml).to eq(xml)
end
it "fails if some params are missing" do
expect {
WebFinger::WebFinger.from_person(
acct_uri: acct,
alias_url: alias_url,
hcard_url: hcard_url
)
}.to raise_error(WebFinger::InvalidData)
end
it "fails if empty was given" do
expect { WebFinger::WebFinger.from_person({}) }.to raise_error WebFinger::InvalidData
end
it "fails if nil was given" do
expect { WebFinger::WebFinger.from_person(nil) }.to raise_error WebFinger::InvalidData
expect { WebFinger::WebFinger.from_person(nil) }.to raise_error ArgumentError
end
end
@ -71,15 +40,15 @@ XML
it "reads its own output" do
wf = WebFinger::WebFinger.from_xml(xml)
expect(wf.acct_uri).to eq(acct)
expect(wf.alias_url).to eq(alias_url)
expect(wf.hcard_url).to eq(hcard_url)
expect(wf.seed_url).to eq(seed_url)
expect(wf.profile_url).to eq(profile_url)
expect(wf.atom_url).to eq(atom_url)
expect(wf.salmon_url).to eq(salmon_url)
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.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)
expect(wf.guid).to eq(guid)
expect(wf.pubkey).to eq(pubkey)
expect(wf.guid).to eq(person.guid)
expect(wf.public_key).to eq(person.public_key)
end
it "reads old-style XML" do
@ -87,30 +56,30 @@ XML
<?xml version="1.0" encoding="UTF-8"?>
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
<Subject>#{acct}</Subject>
<Alias>#{alias_url}</Alias>
<Link rel="http://microformats.org/profile/hcard" type="text/html" href="#{hcard_url}"/>
<Link rel="http://joindiaspora.com/seed_location" type = "text/html" href="#{seed_url}"/>
<Link rel="http://joindiaspora.com/guid" type = "text/html" href="#{guid}"/>
<Alias>#{person.alias_url}</Alias>
<Link rel="http://microformats.org/profile/hcard" type="text/html" href="#{person.hcard_url}"/>
<Link rel="http://joindiaspora.com/seed_location" type = "text/html" href="#{person.seed_url}"/>
<Link rel="http://joindiaspora.com/guid" type = "text/html" href="#{person.guid}"/>
<Link rel="http://webfinger.net/rel/profile-page" type="text/html" href="#{profile_url}"/>
<Link rel="http://schemas.google.com/g/2010#updates-from" type="application/atom+xml" href="#{atom_url}"/>
<Link rel="salmon" href="#{salmon_url}"/>
<Link rel="http://webfinger.net/rel/profile-page" type="text/html" href="#{person.profile_url}"/>
<Link rel="http://schemas.google.com/g/2010#updates-from" type="application/atom+xml" href="#{person.atom_url}"/>
<Link rel="salmon" href="#{person.salmon_url}"/>
<Link rel="diaspora-public-key" type = "RSA" href="#{pubkey_base64}"/>
<Link rel="diaspora-public-key" type = "RSA" href="#{public_key_base64}"/>
</XRD>
XML
wf = WebFinger::WebFinger.from_xml(historic_xml)
expect(wf.acct_uri).to eq(acct)
expect(wf.alias_url).to eq(alias_url)
expect(wf.hcard_url).to eq(hcard_url)
expect(wf.seed_url).to eq(seed_url)
expect(wf.profile_url).to eq(profile_url)
expect(wf.atom_url).to eq(atom_url)
expect(wf.salmon_url).to eq(salmon_url)
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.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)
expect(wf.guid).to eq(guid)
expect(wf.pubkey).to eq(pubkey)
expect(wf.guid).to eq(person.guid)
expect(wf.public_key).to eq(person.public_key)
end
it "fails if the document is empty" do

View file

@ -1,19 +1,14 @@
class Person < ActiveRecord::Base
include ::Diaspora::Guid
def webfinger_hash
{
acct_uri: "acct:#{diaspora_handle}",
alias_url: "#{url}people/#{guid}",
hcard_url: "#{url}hcard/users/#{guid}",
seed_url: url,
profile_url: "#{url}u/#{diaspora_handle.split('@')[0]}",
atom_url: "#{url}public/#{diaspora_handle.split('@')[0]}.atom",
salmon_url: "#{url}receive/users/#{guid}",
guid: guid,
pubkey: serialized_public_key
}
end
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 salmon_url; "#{url}receive/users/#{guid}" end
alias_attribute :seed_url, :url
alias_attribute :public_key, :serialized_public_key
def hcard_profile_hash
{