Remove legacy Webfinger handling
This commit is contained in:
parent
3861eb9fef
commit
d5107f5678
12 changed files with 341 additions and 767 deletions
|
|
@ -5,20 +5,6 @@ require_dependency "diaspora_federation/application_controller"
|
|||
module DiasporaFederation
|
||||
# This controller handles all webfinger-specific requests.
|
||||
class WebfingerController < ApplicationController
|
||||
# Returns the host-meta xml
|
||||
#
|
||||
# example:
|
||||
# <?xml version="1.0" encoding="UTF-8"?>
|
||||
# <XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
|
||||
# <Link rel="lrdd" type="application/xrd+xml"
|
||||
# template="https://server.example/.well-known/webfinger.xml?resource={uri}"/>
|
||||
# </XRD>
|
||||
#
|
||||
# GET /.well-known/host-meta
|
||||
def host_meta
|
||||
render xml: WebfingerController.host_meta_xml, content_type: "application/xrd+xml"
|
||||
end
|
||||
|
||||
# Returns the webfinger as RFC 7033 JRD or XRD.
|
||||
#
|
||||
# JSON example:
|
||||
|
|
@ -59,20 +45,6 @@ module DiasporaFederation
|
|||
# ]
|
||||
# }
|
||||
#
|
||||
# XML example:
|
||||
# <?xml version="1.0" encoding="UTF-8"?>
|
||||
# <XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
|
||||
# <Subject>acct:alice@localhost:3000</Subject>
|
||||
# <Alias>http://localhost:3000/people/c8e87290f6a20132963908fbffceb188</Alias>
|
||||
# <Link rel="http://microformats.org/profile/hcard" type="text/html"
|
||||
# href="http://localhost:3000/hcard/users/c8e87290f6a20132963908fbffceb188"/>
|
||||
# <Link rel="http://joindiaspora.com/seed_location" type="text/html" href="http://localhost:3000/"/>
|
||||
# <Link rel="http://webfinger.net/rel/profile-page" type="text/html" href="http://localhost:3000/u/alice"/>
|
||||
# <Link rel="http://schemas.google.com/g/2010#updates-from" type="application/atom+xml"
|
||||
# href="http://localhost:3000/public/alice.atom"/>
|
||||
# <Link rel="salmon" href="http://localhost:3000/receive/users/c8e87290f6a20132963908fbffceb188"/>
|
||||
# </XRD>
|
||||
#
|
||||
# GET /.well-known/webfinger?resource=<uri>
|
||||
def webfinger
|
||||
person_wf = find_person_webfinger(params.require(:resource))
|
||||
|
|
@ -80,26 +52,13 @@ module DiasporaFederation
|
|||
if person_wf.nil?
|
||||
head :not_found
|
||||
else
|
||||
logger.info "webfinger profile request for: #{person_wf.acct_uri}"
|
||||
logger.info "Webfinger profile request for: #{person_wf.acct_uri}"
|
||||
|
||||
respond_to do |format|
|
||||
format.any(:jrd, :json, :html) do
|
||||
headers["Access-Control-Allow-Origin"] = "*"
|
||||
render json: JSON.pretty_generate(person_wf.to_json), content_type: "application/jrd+json"
|
||||
end
|
||||
format.any(:xrd, :xml) do
|
||||
render xml: person_wf.to_xml, content_type: "application/xrd+xml"
|
||||
end
|
||||
end
|
||||
headers["Access-Control-Allow-Origin"] = "*"
|
||||
render json: JSON.pretty_generate(person_wf.to_json), content_type: "application/jrd+json"
|
||||
end
|
||||
end
|
||||
|
||||
# Creates the host-meta xml with the configured server_uri and caches it
|
||||
# @return [String] XML string
|
||||
def self.host_meta_xml
|
||||
@host_meta_xml ||= Discovery::HostMeta.from_base_url(DiasporaFederation.server_uri.to_s).to_xml
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_person_webfinger(query)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ DiasporaFederation::Engine.routes.draw do
|
|||
end
|
||||
|
||||
controller :webfinger do
|
||||
get ".well-known/host-meta" => :host_meta, :as => "host_meta"
|
||||
get ".well-known/webfinger" => :webfinger, :as => "webfinger"
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ end
|
|||
|
||||
require "diaspora_federation/discovery/exceptions"
|
||||
require "diaspora_federation/discovery/xrd_document"
|
||||
require "diaspora_federation/discovery/host_meta"
|
||||
require "diaspora_federation/discovery/web_finger"
|
||||
require "diaspora_federation/discovery/h_card"
|
||||
require "diaspora_federation/discovery/discovery"
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ module DiasporaFederation
|
|||
validate_diaspora_id
|
||||
|
||||
DiasporaFederation.callbacks.trigger(:save_person_after_webfinger, person)
|
||||
logger.info "successfully webfingered #{diaspora_id}"
|
||||
logger.info "Successfully webfingered #{diaspora_id}"
|
||||
person
|
||||
rescue DiscoveryError
|
||||
raise # simply re-raise DiscoveryError
|
||||
|
|
@ -67,22 +67,11 @@ module DiasporaFederation
|
|||
"acct:#{diaspora_id}"
|
||||
end
|
||||
|
||||
def legacy_webfinger_url_from_host_meta
|
||||
# This tries the xrd url with https first, then falls back to http.
|
||||
host_meta = HostMeta.from_xml(get("https://#{domain}/.well-known/host-meta", http_fallback: true))
|
||||
host_meta.webfinger_template_url.gsub("{uri}", acct_parameter)
|
||||
end
|
||||
|
||||
def webfinger
|
||||
return @webfinger if @webfinger
|
||||
|
||||
webfinger_url = "https://#{domain}/.well-known/webfinger?resource=#{acct_parameter}"
|
||||
|
||||
# This tries the WebFinger URL with https first, then falls back to http if webfinger_http_fallback is enabled.
|
||||
@webfinger = WebFinger.from_json(get(webfinger_url, http_fallback: DiasporaFederation.webfinger_http_fallback))
|
||||
rescue => e # rubocop:disable Style/RescueStandardError
|
||||
logger.warn "WebFinger failed, retrying with legacy WebFinger for #{diaspora_id}: #{e.class}: #{e.message}"
|
||||
@webfinger = WebFinger.from_xml(get(legacy_webfinger_url_from_host_meta))
|
||||
@webfinger ||=
|
||||
WebFinger.from_json(get("https://#{domain}/.well-known/webfinger?resource=#{acct_parameter}",
|
||||
http_fallback: DiasporaFederation.webfinger_http_fallback))
|
||||
end
|
||||
|
||||
def hcard
|
||||
|
|
|
|||
|
|
@ -1,92 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module DiasporaFederation
|
||||
module Discovery
|
||||
# Generates and parses Host Meta documents.
|
||||
#
|
||||
# This is a minimal implementation of the standard, only to the degree of what
|
||||
# is used for the purposes of the diaspora* protocol. (e.g. WebFinger)
|
||||
#
|
||||
# @example Creating a Host Meta document
|
||||
# doc = HostMeta.from_base_url("https://pod.example.tld/")
|
||||
# doc.to_xml
|
||||
#
|
||||
# @example Parsing a Host Meta document
|
||||
# doc = HostMeta.from_xml(xml_string)
|
||||
# webfinger_tpl = doc.webfinger_template_url
|
||||
#
|
||||
# @see http://tools.ietf.org/html/rfc6415 RFC 6415: "Web Host Metadata"
|
||||
# @see XrdDocument
|
||||
class HostMeta
|
||||
private_class_method :new
|
||||
|
||||
# Creates a new host-meta instance
|
||||
# @param [String] webfinger_url the webfinger-url
|
||||
def initialize(webfinger_url)
|
||||
@webfinger_url = webfinger_url
|
||||
end
|
||||
|
||||
# URL fragment to append to the base URL
|
||||
WEBFINGER_SUFFIX = "/.well-known/webfinger.xml?resource={uri}"
|
||||
|
||||
# Returns the WebFinger URL that was used to build this instance (either from
|
||||
# xml or by giving a base URL).
|
||||
# @return [String] WebFinger template URL
|
||||
def webfinger_template_url
|
||||
@webfinger_url
|
||||
end
|
||||
|
||||
# Produces the XML string for the Host Meta instance with a +Link+ element
|
||||
# containing the +webfinger_url+.
|
||||
# @return [String] XML string
|
||||
def to_xml
|
||||
doc = XrdDocument.new
|
||||
doc.links << {rel: "lrdd",
|
||||
type: "application/xrd+xml",
|
||||
template: @webfinger_url}
|
||||
doc.to_xml
|
||||
end
|
||||
|
||||
# Builds a new HostMeta instance and constructs the WebFinger URL from the
|
||||
# given base URL by appending HostMeta::WEBFINGER_SUFFIX.
|
||||
# @param [String, URL] base_url the base-url for the webfinger-url
|
||||
# @return [HostMeta]
|
||||
# @raise [InvalidData] if the webfinger url is malformed
|
||||
def self.from_base_url(base_url)
|
||||
webfinger_url = "#{base_url.to_s.chomp('/')}#{WEBFINGER_SUFFIX}"
|
||||
raise InvalidData, "invalid webfinger url: #{webfinger_url}" unless webfinger_url_valid?(webfinger_url)
|
||||
|
||||
new(webfinger_url)
|
||||
end
|
||||
|
||||
# Reads the given Host Meta XML document string and populates the
|
||||
# +webfinger_url+.
|
||||
# @param [String] hostmeta_xml Host Meta XML string
|
||||
# @raise [InvalidData] if the xml or the webfinger url is malformed
|
||||
def self.from_xml(hostmeta_xml)
|
||||
data = XrdDocument.xml_data(hostmeta_xml)
|
||||
raise InvalidData, "received an invalid xml" unless data.key?(:links)
|
||||
|
||||
webfinger_url = webfinger_url_from_xrd(data)
|
||||
raise InvalidData, "invalid webfinger url: #{webfinger_url}" unless webfinger_url_valid?(webfinger_url)
|
||||
|
||||
new(webfinger_url)
|
||||
end
|
||||
|
||||
# Applies some basic sanity-checking to the given URL
|
||||
# @param [String] url validation subject
|
||||
# @return [Boolean] validation result
|
||||
private_class_method def self.webfinger_url_valid?(url)
|
||||
!url.nil? && url.instance_of?(String) && url =~ %r{\Ahttps?://.*/.*\{uri\}.*}i
|
||||
end
|
||||
|
||||
# Gets the webfinger url from an XRD data structure
|
||||
# @param [Hash] data extracted data
|
||||
# @return [String] webfinger url
|
||||
private_class_method def self.webfinger_url_from_xrd(data)
|
||||
link = data[:links].find {|l| l[:rel] == "lrdd" }
|
||||
return link[:template] unless link.nil?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -3,10 +3,7 @@
|
|||
module DiasporaFederation
|
||||
module Discovery
|
||||
# The WebFinger document used for diaspora* user discovery is based on an
|
||||
# {http://tools.ietf.org/html/draft-jones-appsawg-webfinger older draft of the specification}.
|
||||
#
|
||||
# In the meantime an actual RFC draft has been in development, which should
|
||||
# serve as a base for all future changes of this implementation.
|
||||
# {https://datatracker.ietf.org/doc/html/rfc7033 RFC 7033}.
|
||||
#
|
||||
# @example Creating a WebFinger document from a person hash
|
||||
# wf = WebFinger.new(
|
||||
|
|
@ -17,22 +14,20 @@ module DiasporaFederation
|
|||
# atom_url: "https://server.example/public/user.atom",
|
||||
# salmon_url: "https://server.example/receive/users/0123456789abcdef"
|
||||
# )
|
||||
# xml_string = wf.to_xml
|
||||
# json_string = wf.to_json
|
||||
#
|
||||
# @example Creating a WebFinger instance from an xml document
|
||||
# wf = WebFinger.from_xml(xml_string)
|
||||
# @example Creating a WebFinger instance from an JSON document
|
||||
# wf = WebFinger.from_json(json_string)
|
||||
# ...
|
||||
# hcard_url = wf.hcard_url
|
||||
# ...
|
||||
#
|
||||
# @see http://tools.ietf.org/html/draft-jones-appsawg-webfinger "WebFinger" -
|
||||
# current draft
|
||||
# @see http://www.iana.org/assignments/link-relations/link-relations.xhtml
|
||||
# official list of IANA link relations
|
||||
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.
|
||||
# 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, :string
|
||||
|
||||
|
|
@ -67,7 +62,7 @@ module DiasporaFederation
|
|||
property :salmon_url, :string, optional: true
|
||||
|
||||
# @!attribute [r] subscribe_url
|
||||
# This url is used to find another user on the home-pod of the user in the webfinger.
|
||||
# This url is used to find another user on the home-pod of the user in the WebFinger.
|
||||
property :subscribe_url, :string, optional: true
|
||||
|
||||
# +hcard_url+ link relation
|
||||
|
|
@ -106,29 +101,29 @@ module DiasporaFederation
|
|||
super(data)
|
||||
end
|
||||
|
||||
# Creates the XML string from the current WebFinger instance
|
||||
# @return [String] XML string
|
||||
# @!visibility private
|
||||
# Generating WebFinger to XML is not supported anymore, use {#to_json} instead.
|
||||
def to_xml
|
||||
to_xrd.to_xml
|
||||
raise "Generating WebFinger to XML is not supported anymore, use 'to_json' instead."
|
||||
end
|
||||
|
||||
# Creates the JSON string from the current WebFinger instance
|
||||
# @return [String] JSON string
|
||||
def to_json(*_args)
|
||||
to_xrd.to_json
|
||||
end
|
||||
|
||||
# Creates a WebFinger instance from the given XML string
|
||||
# @param [String] webfinger_xml WebFinger XML string
|
||||
# @return [WebFinger] WebFinger instance
|
||||
# @raise [InvalidData] if the given XML string is invalid or incomplete
|
||||
def self.from_xml(webfinger_xml)
|
||||
from_hash(parse_xml_and_validate(webfinger_xml))
|
||||
# @!visibility private
|
||||
# Parsing WebFinger as XML is not supported anymore, use {from_json} instead.
|
||||
def self.from_xml(_webfinger_xml)
|
||||
raise "Parsing WebFinger as XML is not supported anymore, use 'from_json' instead."
|
||||
end
|
||||
|
||||
# Creates a WebFinger instance from the given JSON string
|
||||
# @param [String] webfinger_json WebFinger JSON string
|
||||
# @return [WebFinger] WebFinger instance
|
||||
def self.from_json(webfinger_json)
|
||||
from_hash(XrdDocument.json_data(webfinger_json))
|
||||
from_hash(parse_json_and_validate(webfinger_json))
|
||||
end
|
||||
|
||||
# Creates a WebFinger instance from the given data
|
||||
|
|
@ -157,15 +152,15 @@ module DiasporaFederation
|
|||
|
||||
private
|
||||
|
||||
# Parses the XML string to a Hash and does some rudimentary checking on
|
||||
# Parses the JSON string to a Hash and does some rudimentary checking on
|
||||
# the data Hash.
|
||||
# @param [String] webfinger_xml WebFinger XML string
|
||||
# @return [Hash] data XML data
|
||||
# @raise [InvalidData] if the given XML string is invalid or incomplete
|
||||
private_class_method def self.parse_xml_and_validate(webfinger_xml)
|
||||
XrdDocument.xml_data(webfinger_xml).tap do |data|
|
||||
# @param [String] webfinger_json WebFinger JSON string
|
||||
# @return [Hash] data JSON data
|
||||
# @raise [InvalidData] if the given JSON string is invalid or incomplete
|
||||
private_class_method def self.parse_json_and_validate(webfinger_json)
|
||||
XrdDocument.json_data(webfinger_json).tap do |data|
|
||||
valid = data.key?(:subject) && data.key?(:links)
|
||||
raise InvalidData, "webfinger xml is incomplete" unless valid
|
||||
raise InvalidData, "Webfinger JSON is incomplete" unless valid
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,9 @@ module DiasporaFederation
|
|||
# This class implements basic handling of XRD documents as far as it is
|
||||
# necessary in the context of the protocols used with diaspora* federation.
|
||||
#
|
||||
# @note {http://tools.ietf.org/html/rfc6415 RFC 6415} recommends that servers
|
||||
# should also offer the JRD format in addition to the XRD representation.
|
||||
# Implementing +XrdDocument#to_json+ and +XrdDocument.json_data+ should
|
||||
# be almost trivial due to the simplicity of the format and the way the data
|
||||
# is stored internally already. See
|
||||
# {http://tools.ietf.org/html/rfc6415#appendix-A RFC 6415, Appendix A}
|
||||
# for a description of the JSON format.
|
||||
# It also implements handling of the JRD format, see
|
||||
# {https://datatracker.ietf.org/doc/html/rfc6415#appendix-A RFC 6415, Appendix A}
|
||||
# for a description of the JSON format.
|
||||
#
|
||||
# @example Creating a XrdDocument
|
||||
# doc = XrdDocument.new
|
||||
|
|
@ -210,7 +206,7 @@ module DiasporaFederation
|
|||
|
||||
# symbolize link keys from JSON hash, but only convert known keys
|
||||
private_class_method def self.symbolize_keys_for_links(links)
|
||||
links.map do |link|
|
||||
links&.map do |link|
|
||||
{}.tap do |hash|
|
||||
LINK_ATTRS.each do |attr|
|
||||
hash[attr] = link[attr.to_s] if link.key?(attr.to_s)
|
||||
|
|
|
|||
|
|
@ -4,39 +4,6 @@ module DiasporaFederation
|
|||
describe WebfingerController, type: :controller do
|
||||
routes { DiasporaFederation::Engine.routes }
|
||||
|
||||
describe "GET #host_meta" do
|
||||
before do
|
||||
DiasporaFederation.server_uri = URI("http://localhost:3000/")
|
||||
WebfingerController.instance_variable_set(:@host_meta_xml, nil) # clear cache
|
||||
end
|
||||
|
||||
it "succeeds" do
|
||||
get :host_meta
|
||||
expect(response).to be_successful
|
||||
end
|
||||
|
||||
it "contains the webfinger-template" do
|
||||
get :host_meta
|
||||
expect(response.body).to include "template=\"http://localhost:3000/.well-known/webfinger.xml?resource={uri}\""
|
||||
end
|
||||
|
||||
it "returns a application/xrd+xml" do
|
||||
get :host_meta
|
||||
expect(response.header["Content-Type"]).to include "application/xrd+xml"
|
||||
end
|
||||
|
||||
it "calls Discovery::HostMeta.from_base_url with the base url" do
|
||||
expect(Discovery::HostMeta).to receive(:from_base_url).with("http://localhost:3000/").and_call_original
|
||||
get :host_meta
|
||||
end
|
||||
|
||||
it "caches the xml" do
|
||||
expect(Discovery::HostMeta).to receive(:from_base_url).exactly(1).times.and_call_original
|
||||
get :host_meta
|
||||
get :host_meta
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET #webfinger" do
|
||||
it "uses the JRD format as default" do
|
||||
get :webfinger, params: {resource: alice.diaspora_id}
|
||||
|
|
@ -44,81 +11,46 @@ module DiasporaFederation
|
|||
expect(response.header["Content-Type"]).to include "application/jrd+json"
|
||||
end
|
||||
|
||||
context "json", exceptions: :catch do
|
||||
it "succeeds when the person exists" do
|
||||
get :webfinger, format: :json, params: {resource: alice.diaspora_id}
|
||||
expect(response).to be_successful
|
||||
end
|
||||
|
||||
it "succeeds with 'acct:' in the query when the person exists" do
|
||||
get :webfinger, format: :json, params: {resource: "acct:#{alice.diaspora_id}"}
|
||||
expect(response).to be_successful
|
||||
end
|
||||
|
||||
it "contains the diaspora* ID" do
|
||||
get :webfinger, format: :json, params: {resource: "acct:#{alice.diaspora_id}"}
|
||||
expect(response.body).to include "\"subject\": \"acct:alice@localhost:3000\""
|
||||
end
|
||||
|
||||
it "returns a application/jrd+json" do
|
||||
get :webfinger, format: :json, params: {resource: "acct:#{alice.diaspora_id}"}
|
||||
expect(response.header["Content-Type"]).to include "application/jrd+json"
|
||||
end
|
||||
|
||||
it "adds a Access-Control-Allow-Origin header" do
|
||||
get :webfinger, format: :json, params: {resource: "acct:#{alice.diaspora_id}"}
|
||||
expect(response.header["Access-Control-Allow-Origin"]).to eq("*")
|
||||
end
|
||||
|
||||
it "404s when the person does not exist" do
|
||||
get :webfinger, format: :json, params: {resource: "me@mydiaspora.pod.com"}
|
||||
expect(response).to be_not_found
|
||||
end
|
||||
|
||||
it "raises when the resource parameter is missing" do
|
||||
expect {
|
||||
get :webfinger, format: :json
|
||||
}.to raise_error ActionController::ParameterMissing, /param is missing or the value is empty: resource/
|
||||
end
|
||||
|
||||
it "calls the fetch_person_for_webfinger callback" do
|
||||
expect_callback(:fetch_person_for_webfinger, "alice@localhost:3000").and_call_original
|
||||
|
||||
get :webfinger, format: :json, params: {resource: "acct:alice@localhost:3000"}
|
||||
end
|
||||
it "succeeds when the person exists" do
|
||||
get :webfinger, format: :json, params: {resource: alice.diaspora_id}
|
||||
expect(response).to be_successful
|
||||
end
|
||||
|
||||
context "xml" do
|
||||
it "succeeds when the person exists" do
|
||||
get :webfinger, format: :json, params: {resource: alice.diaspora_id}
|
||||
expect(response).to be_successful
|
||||
end
|
||||
it "succeeds with 'acct:' in the query when the person exists" do
|
||||
get :webfinger, format: :json, params: {resource: "acct:#{alice.diaspora_id}"}
|
||||
expect(response).to be_successful
|
||||
end
|
||||
|
||||
it "succeeds with 'acct:' in the query when the person exists" do
|
||||
get :webfinger, format: :xml, params: {resource: "acct:#{alice.diaspora_id}"}
|
||||
expect(response).to be_successful
|
||||
end
|
||||
it "contains the diaspora* ID" do
|
||||
get :webfinger, format: :json, params: {resource: "acct:#{alice.diaspora_id}"}
|
||||
expect(response.body).to include "\"subject\": \"acct:alice@localhost:3000\""
|
||||
end
|
||||
|
||||
it "contains the diaspora* ID" do
|
||||
get :webfinger, format: :xml, params: {resource: "acct:#{alice.diaspora_id}"}
|
||||
expect(response.body).to include "<Subject>acct:alice@localhost:3000</Subject>"
|
||||
end
|
||||
it "returns a application/jrd+json" do
|
||||
get :webfinger, format: :json, params: {resource: "acct:#{alice.diaspora_id}"}
|
||||
expect(response.header["Content-Type"]).to include "application/jrd+json"
|
||||
end
|
||||
|
||||
it "returns a application/xrd+xml" do
|
||||
get :webfinger, format: :xml, params: {resource: "acct:#{alice.diaspora_id}"}
|
||||
expect(response.header["Content-Type"]).to include "application/xrd+xml"
|
||||
end
|
||||
it "adds a Access-Control-Allow-Origin header" do
|
||||
get :webfinger, format: :json, params: {resource: "acct:#{alice.diaspora_id}"}
|
||||
expect(response.header["Access-Control-Allow-Origin"]).to eq("*")
|
||||
end
|
||||
|
||||
it "404s when the person does not exist" do
|
||||
get :webfinger, format: :xml, params: {resource: "me@mydiaspora.pod.com"}
|
||||
expect(response).to be_not_found
|
||||
end
|
||||
it "404s when the person does not exist" do
|
||||
get :webfinger, format: :json, params: {resource: "me@mydiaspora.pod.com"}
|
||||
expect(response).to be_not_found
|
||||
end
|
||||
|
||||
it "calls the fetch_person_for_webfinger callback" do
|
||||
expect_callback(:fetch_person_for_webfinger, "alice@localhost:3000").and_call_original
|
||||
it "raises when the resource parameter is missing" do
|
||||
expect {
|
||||
get :webfinger, format: :json
|
||||
}.to raise_error ActionController::ParameterMissing, /param is missing or the value is empty: resource/
|
||||
end
|
||||
|
||||
get :webfinger, format: :xml, params: {resource: "acct:alice@localhost:3000"}
|
||||
end
|
||||
it "calls the fetch_person_for_webfinger callback" do
|
||||
expect_callback(:fetch_person_for_webfinger, "alice@localhost:3000").and_call_original
|
||||
|
||||
get :webfinger, format: :json, params: {resource: "acct:alice@localhost:3000"}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
module DiasporaFederation
|
||||
describe Discovery::Discovery do
|
||||
let(:host_meta_xrd) { Discovery::HostMeta.from_base_url("http://localhost:3000/").to_xml }
|
||||
subject(:discovery) { Discovery::Discovery.new(account) }
|
||||
|
||||
let(:webfinger_data) {
|
||||
{
|
||||
acct_uri: "acct:#{alice.diaspora_id}",
|
||||
|
|
@ -17,9 +18,6 @@ module DiasporaFederation
|
|||
public_key: alice.serialized_public_key
|
||||
}
|
||||
}
|
||||
let(:webfinger_xrd) {
|
||||
DiasporaFederation::Discovery::WebFinger.new(webfinger_data).to_xml
|
||||
}
|
||||
let(:webfinger_jrd) {
|
||||
JSON.pretty_generate(DiasporaFederation::Discovery::WebFinger.new(webfinger_data).to_json)
|
||||
}
|
||||
|
|
@ -40,7 +38,6 @@ module DiasporaFederation
|
|||
}
|
||||
let(:account) { alice.diaspora_id }
|
||||
let(:default_image) { "http://localhost:3000/assets/user/default.png" }
|
||||
subject { Discovery::Discovery.new(account) }
|
||||
|
||||
describe "#intialize" do
|
||||
it "sets diaspora* ID" do
|
||||
|
|
@ -62,7 +59,7 @@ module DiasporaFederation
|
|||
.to_return(status: 200, body: hcard_html)
|
||||
|
||||
expect_callback(:save_person_after_webfinger, kind_of(Entities::Person))
|
||||
person = subject.fetch_and_save
|
||||
person = discovery.fetch_and_save
|
||||
|
||||
expect(person.guid).to eq(alice.guid)
|
||||
expect(person.diaspora_id).to eq(account)
|
||||
|
|
@ -93,7 +90,7 @@ module DiasporaFederation
|
|||
callback_person = person
|
||||
end
|
||||
|
||||
expect(subject.fetch_and_save).to be(callback_person)
|
||||
expect(discovery.fetch_and_save).to be(callback_person)
|
||||
end
|
||||
|
||||
it "fails if the diaspora* ID does not match" do
|
||||
|
|
@ -102,67 +99,32 @@ module DiasporaFederation
|
|||
stub_request(:get, "https://localhost:3000/.well-known/webfinger?resource=acct:#{account}")
|
||||
.to_return(status: 200, body: modified_webfinger)
|
||||
|
||||
expect { subject.fetch_and_save }.to raise_error Discovery::DiscoveryError
|
||||
expect { discovery.fetch_and_save }.to raise_error Discovery::DiscoveryError
|
||||
end
|
||||
|
||||
it "fails if the diaspora* ID was not found" do
|
||||
stub_request(:get, "https://localhost:3000/.well-known/webfinger?resource=acct:#{account}")
|
||||
.to_return(status: 404)
|
||||
stub_request(:get, "http://localhost:3000/.well-known/webfinger?resource=acct:#{account}")
|
||||
.to_return(status: 404)
|
||||
stub_request(:get, "https://localhost:3000/.well-known/host-meta")
|
||||
.to_return(status: 200, body: host_meta_xrd)
|
||||
stub_request(:get, "http://localhost:3000/.well-known/webfinger.xml?resource=acct:#{account}")
|
||||
.to_return(status: 404)
|
||||
|
||||
expect { subject.fetch_and_save }.to raise_error Discovery::DiscoveryError
|
||||
expect { discovery.fetch_and_save }.to raise_error Discovery::DiscoveryError
|
||||
end
|
||||
|
||||
context "http fallback" do
|
||||
context "http fallback disabled (default)" do
|
||||
it "falls back to legacy WebFinger if https fails with 404" do
|
||||
stub_request(:get, "https://localhost:3000/.well-known/webfinger?resource=acct:#{account}")
|
||||
.to_return(status: 404)
|
||||
stub_request(:get, "https://localhost:3000/.well-known/host-meta")
|
||||
.to_return(status: 200, body: host_meta_xrd)
|
||||
stub_request(:get, "http://localhost:3000/.well-known/webfinger.xml?resource=acct:#{account}")
|
||||
.to_return(status: 200, body: webfinger_xrd)
|
||||
stub_request(:get, "http://localhost:3000/hcard/users/#{alice.guid}")
|
||||
.to_return(status: 200, body: hcard_html)
|
||||
|
||||
expect_callback(:save_person_after_webfinger, kind_of(Entities::Person))
|
||||
person = subject.fetch_and_save
|
||||
|
||||
expect(person.guid).to eq(alice.guid)
|
||||
expect(person.diaspora_id).to eq(account)
|
||||
end
|
||||
|
||||
it "falls back to legacy WebFinger if https fails with ssl error" do
|
||||
context "with http fallback" do
|
||||
context "when http fallback disabled (default)" do
|
||||
it "does not fall back to http if https fails with ssl error" do
|
||||
stub_request(:get, "https://localhost:3000/.well-known/webfinger?resource=acct:#{account}")
|
||||
.to_raise(OpenSSL::SSL::SSLError)
|
||||
stub_request(:get, "https://localhost:3000/.well-known/host-meta")
|
||||
.to_raise(OpenSSL::SSL::SSLError)
|
||||
stub_request(:get, "http://localhost:3000/.well-known/host-meta")
|
||||
.to_return(status: 200, body: host_meta_xrd)
|
||||
stub_request(:get, "http://localhost:3000/.well-known/webfinger.xml?resource=acct:#{account}")
|
||||
.to_return(status: 200, body: webfinger_xrd)
|
||||
stub_request(:get, "http://localhost:3000/hcard/users/#{alice.guid}")
|
||||
.to_return(status: 200, body: hcard_html)
|
||||
|
||||
expect_callback(:save_person_after_webfinger, kind_of(Entities::Person))
|
||||
person = subject.fetch_and_save
|
||||
|
||||
expect(person.guid).to eq(alice.guid)
|
||||
expect(person.diaspora_id).to eq(account)
|
||||
expect { discovery.fetch_and_save }.to raise_error Discovery::DiscoveryError
|
||||
end
|
||||
end
|
||||
|
||||
context "http fallback enabled" do
|
||||
before :all do
|
||||
context "when http fallback enabled" do
|
||||
before do
|
||||
DiasporaFederation.webfinger_http_fallback = true
|
||||
end
|
||||
|
||||
after :all do
|
||||
after do
|
||||
DiasporaFederation.webfinger_http_fallback = false
|
||||
end
|
||||
|
||||
|
|
@ -175,7 +137,7 @@ module DiasporaFederation
|
|||
.to_return(status: 200, body: hcard_html)
|
||||
|
||||
expect_callback(:save_person_after_webfinger, kind_of(Entities::Person))
|
||||
person = subject.fetch_and_save
|
||||
person = discovery.fetch_and_save
|
||||
|
||||
expect(person.guid).to eq(alice.guid)
|
||||
expect(person.diaspora_id).to eq(account)
|
||||
|
|
@ -190,7 +152,7 @@ module DiasporaFederation
|
|||
.to_return(status: 200, body: hcard_html)
|
||||
|
||||
expect_callback(:save_person_after_webfinger, kind_of(Entities::Person))
|
||||
person = subject.fetch_and_save
|
||||
person = discovery.fetch_and_save
|
||||
|
||||
expect(person.guid).to eq(alice.guid)
|
||||
expect(person.diaspora_id).to eq(account)
|
||||
|
|
@ -198,118 +160,33 @@ module DiasporaFederation
|
|||
end
|
||||
end
|
||||
|
||||
context "legacy WebFinger" do
|
||||
it "falls back to legacy WebFinger" do
|
||||
incomplete_webfinger_json = "{\"links\":[{\"rel\":\"http://openid.net/specs/connect/1.0/issuer\"," \
|
||||
"\"href\":\"https://localhost:3000/\"}],\"subject\":\"acct:#{account}\"}"
|
||||
stub_request(:get, "https://localhost:3000/.well-known/webfinger?resource=acct:#{account}")
|
||||
.to_return(status: 200, body: incomplete_webfinger_json)
|
||||
stub_request(:get, "https://localhost:3000/.well-known/host-meta")
|
||||
.to_return(status: 200, body: host_meta_xrd)
|
||||
stub_request(:get, "http://localhost:3000/.well-known/webfinger.xml?resource=acct:#{account}")
|
||||
.to_return(status: 200, body: webfinger_xrd)
|
||||
stub_request(:get, "http://localhost:3000/hcard/users/#{alice.guid}")
|
||||
.to_return(status: 200, body: hcard_html)
|
||||
|
||||
expect_callback(:save_person_after_webfinger, kind_of(Entities::Person))
|
||||
person = subject.fetch_and_save
|
||||
|
||||
expect(person.guid).to eq(alice.guid)
|
||||
expect(person.diaspora_id).to eq(account)
|
||||
expect(person.url).to eq(alice.url)
|
||||
expect(person.exported_key).to eq(alice.serialized_public_key)
|
||||
|
||||
profile = person.profile
|
||||
|
||||
expect(profile.diaspora_id).to eq(alice.diaspora_id)
|
||||
expect(profile.first_name).to eq("Dummy")
|
||||
expect(profile.last_name).to eq("User")
|
||||
|
||||
expect(profile.image_url).to eq(default_image)
|
||||
expect(profile.image_url_medium).to eq(default_image)
|
||||
expect(profile.image_url_small).to eq(default_image)
|
||||
end
|
||||
|
||||
it "falls back to http if https fails with 404" do
|
||||
stub_request(:get, "https://localhost:3000/.well-known/webfinger?resource=acct:#{account}")
|
||||
.to_return(status: 404)
|
||||
stub_request(:get, "https://localhost:3000/.well-known/host-meta")
|
||||
.to_return(status: 404)
|
||||
stub_request(:get, "http://localhost:3000/.well-known/host-meta")
|
||||
.to_return(status: 200, body: host_meta_xrd)
|
||||
stub_request(:get, "http://localhost:3000/.well-known/webfinger.xml?resource=acct:#{account}")
|
||||
.to_return(status: 200, body: webfinger_xrd)
|
||||
stub_request(:get, "http://localhost:3000/hcard/users/#{alice.guid}")
|
||||
.to_return(status: 200, body: hcard_html)
|
||||
|
||||
expect_callback(:save_person_after_webfinger, kind_of(Entities::Person))
|
||||
person = subject.fetch_and_save
|
||||
|
||||
expect(person.guid).to eq(alice.guid)
|
||||
expect(person.diaspora_id).to eq(account)
|
||||
end
|
||||
|
||||
it "falls back to http if https fails with ssl error" do
|
||||
stub_request(:get, "https://localhost:3000/.well-known/webfinger?resource=acct:#{account}")
|
||||
.to_raise(OpenSSL::SSL::SSLError)
|
||||
stub_request(:get, "https://localhost:3000/.well-known/host-meta")
|
||||
.to_raise(OpenSSL::SSL::SSLError)
|
||||
stub_request(:get, "http://localhost:3000/.well-known/host-meta")
|
||||
.to_return(status: 200, body: host_meta_xrd)
|
||||
stub_request(:get, "http://localhost:3000/.well-known/webfinger.xml?resource=acct:#{account}")
|
||||
.to_return(status: 200, body: webfinger_xrd)
|
||||
stub_request(:get, "http://localhost:3000/hcard/users/#{alice.guid}")
|
||||
.to_return(status: 200, body: hcard_html)
|
||||
|
||||
expect_callback(:save_person_after_webfinger, kind_of(Entities::Person))
|
||||
person = subject.fetch_and_save
|
||||
|
||||
expect(person.guid).to eq(alice.guid)
|
||||
expect(person.diaspora_id).to eq(account)
|
||||
end
|
||||
|
||||
it "fails if the diaspora* ID does not match" do
|
||||
modified_webfinger = webfinger_xrd.gsub(account, "anonther_user@example.com")
|
||||
|
||||
stub_request(:get, "https://localhost:3000/.well-known/webfinger?resource=acct:#{account}")
|
||||
.to_return(status: 200, body: "foobar")
|
||||
stub_request(:get, "https://localhost:3000/.well-known/host-meta")
|
||||
.to_return(status: 200, body: host_meta_xrd)
|
||||
stub_request(:get, "http://localhost:3000/.well-known/webfinger.xml?resource=acct:#{account}")
|
||||
.to_return(status: 200, body: modified_webfinger)
|
||||
|
||||
expect { subject.fetch_and_save }.to raise_error Discovery::DiscoveryError
|
||||
end
|
||||
end
|
||||
|
||||
context "error handling" do
|
||||
context "with error handling" do
|
||||
it "re-raises DiscoveryError" do
|
||||
expect(subject).to receive(:validate_diaspora_id)
|
||||
expect(discovery).to receive(:validate_diaspora_id)
|
||||
.and_raise(Discovery::DiscoveryError, "Something went wrong!")
|
||||
|
||||
expect { subject.fetch_and_save }.to raise_error Discovery::DiscoveryError, "Something went wrong!"
|
||||
expect { discovery.fetch_and_save }.to raise_error Discovery::DiscoveryError, "Something went wrong!"
|
||||
end
|
||||
|
||||
it "re-raises InvalidDocument" do
|
||||
expect(subject).to receive(:validate_diaspora_id)
|
||||
expect(discovery).to receive(:validate_diaspora_id)
|
||||
.and_raise(Discovery::InvalidDocument, "Wrong document!")
|
||||
|
||||
expect { subject.fetch_and_save }.to raise_error Discovery::InvalidDocument, "Wrong document!"
|
||||
expect { discovery.fetch_and_save }.to raise_error Discovery::InvalidDocument, "Wrong document!"
|
||||
end
|
||||
|
||||
it "re-raises InvalidData" do
|
||||
expect(subject).to receive(:validate_diaspora_id)
|
||||
expect(discovery).to receive(:validate_diaspora_id)
|
||||
.and_raise(Discovery::InvalidData, "Wrong data!")
|
||||
|
||||
expect { subject.fetch_and_save }.to raise_error Discovery::InvalidData, "Wrong data!"
|
||||
expect { discovery.fetch_and_save }.to raise_error Discovery::InvalidData, "Wrong data!"
|
||||
end
|
||||
|
||||
it "raises a DiscoveryError when an unhandled error occurs" do
|
||||
expect(subject).to receive(:validate_diaspora_id)
|
||||
.and_raise("OMG! EVERYTHING IS BROKEN!")
|
||||
allow(discovery).to receive(:validate_diaspora_id).and_raise("OMG! EVERYTHING IS BROKEN!")
|
||||
|
||||
expect {
|
||||
subject.fetch_and_save
|
||||
discovery.fetch_and_save
|
||||
}.to raise_error Discovery::DiscoveryError,
|
||||
"Failed discovery for #{account}: RuntimeError: OMG! EVERYTHING IS BROKEN!"
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,103 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module DiasporaFederation
|
||||
describe Discovery::HostMeta do
|
||||
let(:base_url) { "https://pod.example.tld/" }
|
||||
let(:xml) { <<~XML }
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
|
||||
<Link rel="lrdd" type="application/xrd+xml" template="#{base_url}.well-known/webfinger.xml?resource={uri}"/>
|
||||
</XRD>
|
||||
XML
|
||||
|
||||
it "must not create blank instances" do
|
||||
expect { Discovery::HostMeta.new }.to raise_error NoMethodError
|
||||
end
|
||||
|
||||
context "generation" do
|
||||
it "creates a nice XML document" do
|
||||
hm = Discovery::HostMeta.from_base_url(base_url)
|
||||
expect(hm.to_xml).to eq(xml)
|
||||
end
|
||||
|
||||
it "converts object to string" do
|
||||
hm = Discovery::HostMeta.from_base_url(URI(base_url))
|
||||
expect(hm.to_xml).to eq(xml)
|
||||
end
|
||||
|
||||
it "appends a '/' if necessary" do
|
||||
hm = Discovery::HostMeta.from_base_url("https://pod.example.tld")
|
||||
expect(hm.to_xml).to eq(xml)
|
||||
end
|
||||
|
||||
it "fails if the base_url was omitted" do
|
||||
expect { Discovery::HostMeta.from_base_url("") }.to raise_error Discovery::InvalidData
|
||||
end
|
||||
end
|
||||
|
||||
context "parsing" do
|
||||
it "parses its own output" do
|
||||
hm = Discovery::HostMeta.from_xml(xml)
|
||||
expect(hm.webfinger_template_url).to eq("#{base_url}.well-known/webfinger.xml?resource={uri}")
|
||||
end
|
||||
|
||||
it "also reads old-style XML" do
|
||||
historic_xml = <<~XML
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
|
||||
|
||||
<!-- Resource-specific Information -->
|
||||
|
||||
<Link rel="lrdd"
|
||||
type="application/xrd+xml"
|
||||
template="#{base_url}webfinger?q={uri}" />
|
||||
|
||||
</XRD>
|
||||
XML
|
||||
hm = Discovery::HostMeta.from_xml(historic_xml)
|
||||
expect(hm.webfinger_template_url).to eq("#{base_url}webfinger?q={uri}")
|
||||
end
|
||||
|
||||
it "also reads friendica/redmatrix XML" do
|
||||
friendica_redmatrix_xml = <<~XML
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'
|
||||
xmlns:hm='http://host-meta.net/xrd/1.0'>
|
||||
|
||||
<hm:Host>pod.example.tld</hm:Host>
|
||||
|
||||
<Link rel='lrdd' template='#{base_url}xrd/?uri={uri}' />
|
||||
<Link rel="http://oexchange.org/spec/0.8/rel/resident-target" type="application/xrd+xml"
|
||||
href="https://pod.example.tld/oexchange/xrd" />
|
||||
|
||||
</XRD>
|
||||
XML
|
||||
hm = Discovery::HostMeta.from_xml(friendica_redmatrix_xml)
|
||||
expect(hm.webfinger_template_url).to eq("#{base_url}xrd/?uri={uri}")
|
||||
end
|
||||
|
||||
it "fails if the document does not contain a webfinger url" do
|
||||
invalid_xml = <<~XML
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
|
||||
</XRD>
|
||||
XML
|
||||
expect { Discovery::HostMeta.from_xml(invalid_xml) }.to raise_error Discovery::InvalidData
|
||||
end
|
||||
|
||||
it "fails if the document contains a malformed webfinger url" do
|
||||
invalid_xml = <<~XML
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
|
||||
<Link rel="lrdd" type="application/xrd+xml" template="#{base_url}webfinger?q="/>
|
||||
</XRD>
|
||||
XML
|
||||
expect { Discovery::HostMeta.from_xml(invalid_xml) }.to raise_error Discovery::InvalidData
|
||||
end
|
||||
|
||||
it "fails if the document is invalid" do
|
||||
expect { Discovery::HostMeta.from_xml("") }.to raise_error Discovery::InvalidDocument
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -18,29 +18,6 @@ module DiasporaFederation
|
|||
}
|
||||
}
|
||||
|
||||
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>#{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.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="http://ostatus.org/schema/1.0/subscribe" template="#{person.subscribe_url}"/>
|
||||
</XRD>
|
||||
XML
|
||||
|
||||
let(:minimal_xml) { <<~XML }
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
|
||||
<Subject>#{acct}</Subject>
|
||||
<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.url}"/>
|
||||
</XRD>
|
||||
XML
|
||||
|
||||
let(:json) { <<~JSON }
|
||||
{
|
||||
"subject": "#{acct}",
|
||||
|
|
@ -74,7 +51,7 @@ module DiasporaFederation
|
|||
},
|
||||
{
|
||||
"rel": "http://ostatus.org/schema/1.0/subscribe",
|
||||
"template": "http://somehost:3000/people?q={uri}"
|
||||
"template": "#{person.url}people?q={uri}"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -102,7 +79,7 @@ module DiasporaFederation
|
|||
|
||||
it_behaves_like "an Entity subclass"
|
||||
|
||||
context "generation" do
|
||||
context "when generating" do
|
||||
let(:minimal_data) { {acct_uri: acct, hcard_url: person.hcard_url, seed_url: person.url} }
|
||||
let(:additional_data) {
|
||||
{
|
||||
|
|
@ -120,113 +97,66 @@ module DiasporaFederation
|
|||
}
|
||||
}
|
||||
|
||||
context "xml" do
|
||||
it "creates a nice XML document" do
|
||||
wf = Discovery::WebFinger.new(data, aliases: [person.alias_url])
|
||||
expect(wf.to_xml).to eq(xml)
|
||||
end
|
||||
|
||||
it "creates minimal XML document" do
|
||||
wf = Discovery::WebFinger.new(minimal_data)
|
||||
expect(wf.to_xml).to eq(minimal_xml)
|
||||
end
|
||||
|
||||
it "creates XML document with additional data" do
|
||||
xml_with_additional_data = <<~XML
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
|
||||
<Subject>#{acct}</Subject>
|
||||
<Alias>#{person.alias_url}</Alias>
|
||||
<Alias>#{person.profile_url}</Alias>
|
||||
<Property type="http://webfinger.example/ns/name">Bob Smith</Property>
|
||||
<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.url}"/>
|
||||
<Link rel="http://portablecontacts.net/spec/1.0" href="https://pod.example.tld/poco/trouble"/>
|
||||
<Link rel="http://webfinger.net/rel/avatar" type="image/jpeg" href="http://localhost:3000/assets/user/default.png"/>
|
||||
<Link rel="http://openid.net/specs/connect/1.0/issuer" href="https://pod.example.tld/"/>
|
||||
</XRD>
|
||||
XML
|
||||
|
||||
wf = Discovery::WebFinger.new(minimal_data, additional_data)
|
||||
expect(wf.to_xml).to eq(xml_with_additional_data)
|
||||
end
|
||||
it "creates a nice JSON document" do
|
||||
wf = Discovery::WebFinger.new(data, aliases: [person.alias_url])
|
||||
expect(JSON.pretty_generate(wf.to_json)).to eq(json.strip)
|
||||
end
|
||||
|
||||
context "json" do
|
||||
it "creates a nice JSON document" do
|
||||
wf = Discovery::WebFinger.new(data, aliases: [person.alias_url])
|
||||
expect(JSON.pretty_generate(wf.to_json)).to eq(json.strip)
|
||||
end
|
||||
it "creates minimal JSON document" do
|
||||
wf = Discovery::WebFinger.new(minimal_data)
|
||||
expect(JSON.pretty_generate(wf.to_json)).to eq(minimal_json.strip)
|
||||
end
|
||||
|
||||
it "creates minimal JSON document" do
|
||||
wf = Discovery::WebFinger.new(minimal_data)
|
||||
expect(JSON.pretty_generate(wf.to_json)).to eq(minimal_json.strip)
|
||||
end
|
||||
|
||||
it "creates JSON document with additional data" do
|
||||
json_with_additional_data = <<~JSON
|
||||
{
|
||||
"subject": "#{acct}",
|
||||
"aliases": [
|
||||
"#{person.alias_url}",
|
||||
"#{person.profile_url}"
|
||||
],
|
||||
"properties": {
|
||||
"http://webfinger.example/ns/name": "Bob Smith"
|
||||
it "creates JSON document with additional data" do
|
||||
json_with_additional_data = <<~JSON
|
||||
{
|
||||
"subject": "#{acct}",
|
||||
"aliases": [
|
||||
"#{person.alias_url}",
|
||||
"#{person.profile_url}"
|
||||
],
|
||||
"properties": {
|
||||
"http://webfinger.example/ns/name": "Bob Smith"
|
||||
},
|
||||
"links": [
|
||||
{
|
||||
"rel": "http://microformats.org/profile/hcard",
|
||||
"type": "text/html",
|
||||
"href": "#{person.hcard_url}"
|
||||
},
|
||||
"links": [
|
||||
{
|
||||
"rel": "http://microformats.org/profile/hcard",
|
||||
"type": "text/html",
|
||||
"href": "#{person.hcard_url}"
|
||||
},
|
||||
{
|
||||
"rel": "http://joindiaspora.com/seed_location",
|
||||
"type": "text/html",
|
||||
"href": "#{person.url}"
|
||||
},
|
||||
{
|
||||
"rel": "http://portablecontacts.net/spec/1.0",
|
||||
"href": "https://pod.example.tld/poco/trouble"
|
||||
},
|
||||
{
|
||||
"rel": "http://webfinger.net/rel/avatar",
|
||||
"type": "image/jpeg",
|
||||
"href": "http://localhost:3000/assets/user/default.png"
|
||||
},
|
||||
{
|
||||
"rel": "http://openid.net/specs/connect/1.0/issuer",
|
||||
"href": "https://pod.example.tld/"
|
||||
}
|
||||
]
|
||||
}
|
||||
JSON
|
||||
{
|
||||
"rel": "http://joindiaspora.com/seed_location",
|
||||
"type": "text/html",
|
||||
"href": "#{person.url}"
|
||||
},
|
||||
{
|
||||
"rel": "http://portablecontacts.net/spec/1.0",
|
||||
"href": "https://pod.example.tld/poco/trouble"
|
||||
},
|
||||
{
|
||||
"rel": "http://webfinger.net/rel/avatar",
|
||||
"type": "image/jpeg",
|
||||
"href": "http://localhost:3000/assets/user/default.png"
|
||||
},
|
||||
{
|
||||
"rel": "http://openid.net/specs/connect/1.0/issuer",
|
||||
"href": "https://pod.example.tld/"
|
||||
}
|
||||
]
|
||||
}
|
||||
JSON
|
||||
|
||||
wf = Discovery::WebFinger.new(minimal_data, additional_data)
|
||||
expect(JSON.pretty_generate(wf.to_json)).to eq(json_with_additional_data.strip)
|
||||
end
|
||||
wf = Discovery::WebFinger.new(minimal_data, additional_data)
|
||||
expect(JSON.pretty_generate(wf.to_json)).to eq(json_with_additional_data.strip)
|
||||
end
|
||||
|
||||
it "does not support XML anymore" do
|
||||
expect { Discovery::WebFinger.new(minimal_data).to_xml }
|
||||
.to raise_error "Generating WebFinger to XML is not supported anymore, use 'to_json' instead."
|
||||
end
|
||||
end
|
||||
|
||||
context "parsing" do
|
||||
it "reads its own xml output" do
|
||||
wf = Discovery::WebFinger.from_xml(xml)
|
||||
expect(wf.acct_uri).to eq(acct)
|
||||
expect(wf.hcard_url).to eq(person.hcard_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)
|
||||
expect(wf.subscribe_url).to eq(person.subscribe_url)
|
||||
end
|
||||
|
||||
it "reads minimal xml" do
|
||||
wf = Discovery::WebFinger.from_xml(minimal_xml)
|
||||
expect(wf.acct_uri).to eq(acct)
|
||||
expect(wf.hcard_url).to eq(person.hcard_url)
|
||||
expect(wf.seed_url).to eq(person.url)
|
||||
end
|
||||
|
||||
context "when parsing" do
|
||||
it "reads its own json output" do
|
||||
wf = Discovery::WebFinger.from_json(json)
|
||||
expect(wf.acct_uri).to eq(acct)
|
||||
|
|
@ -246,119 +176,219 @@ module DiasporaFederation
|
|||
end
|
||||
|
||||
it "is frozen after parsing" do
|
||||
wf = Discovery::WebFinger.from_xml(xml)
|
||||
wf = Discovery::WebFinger.from_json(json)
|
||||
expect(wf).to be_frozen
|
||||
end
|
||||
|
||||
it "reads friendica XML (two aliases, first with acct)" do
|
||||
friendica_xml = <<~XML
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
|
||||
it "reads friendica JSON" do
|
||||
friendica_hcard_url = "#{person.url}hcard/#{person.nickname}"
|
||||
friendica_profile_url = "#{person.url}profile/#{person.nickname}"
|
||||
friendica_atom_url = "#{person.url}dfrn_poll/#{person.nickname}"
|
||||
friendica_salmon_url = "#{person.url}salmon/#{person.nickname}"
|
||||
friendica_subscribe_url = "#{person.url}follow?url={uri}"
|
||||
|
||||
<Subject>#{acct}</Subject>
|
||||
<Alias>#{acct}</Alias>
|
||||
<Alias>#{person.alias_url}</Alias>
|
||||
friendica_json = <<~JSON
|
||||
{
|
||||
"subject": "#{acct}",
|
||||
"aliases": [
|
||||
"#{person.url}~#{person.nickname}",
|
||||
"#{friendica_profile_url}"
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"rel": "http://purl.org/macgirvin/dfrn/1.0",
|
||||
"href": "#{person.url}profile/#{person.nickname}"
|
||||
},
|
||||
{
|
||||
"rel": "http://schemas.google.com/g/2010#updates-from",
|
||||
"type": "application/atom+xml",
|
||||
"href": "#{friendica_atom_url}"
|
||||
},
|
||||
{
|
||||
"rel": "http://webfinger.net/rel/profile-page",
|
||||
"type": "text/html",
|
||||
"href": "#{friendica_profile_url}"
|
||||
},
|
||||
{
|
||||
"rel": "self",
|
||||
"type": "application/activity+json",
|
||||
"href": "#{friendica_profile_url}"
|
||||
},
|
||||
{
|
||||
"rel": "http://microformats.org/profile/hcard",
|
||||
"type": "text/html",
|
||||
"href": "#{friendica_hcard_url}"
|
||||
},
|
||||
{
|
||||
"rel": "http://portablecontacts.net/spec/1.0",
|
||||
"href": "#{person.url}poco/#{person.nickname}"
|
||||
},
|
||||
{
|
||||
"rel": "http://webfinger.net/rel/avatar",
|
||||
"type": "image/png",
|
||||
"href": "#{person.url}photo/profile/#{person.nickname}.png"
|
||||
},
|
||||
{
|
||||
"rel": "http://joindiaspora.com/seed_location",
|
||||
"type": "text/html",
|
||||
"href": "#{person.url}"
|
||||
},
|
||||
{
|
||||
"rel": "salmon",
|
||||
"href": "#{friendica_salmon_url}"
|
||||
},
|
||||
{
|
||||
"rel": "http://salmon-protocol.org/ns/salmon-replies",
|
||||
"href": "#{friendica_salmon_url}"
|
||||
},
|
||||
{
|
||||
"rel": "http://salmon-protocol.org/ns/salmon-mention",
|
||||
"href": "#{friendica_salmon_url}/mention"
|
||||
},
|
||||
{
|
||||
"rel": "http://ostatus.org/schema/1.0/subscribe",
|
||||
"template": "#{person.url}follow?url={uri}"
|
||||
},
|
||||
{
|
||||
"rel": "magic-public-key",
|
||||
"href": "data:application/magic-public-key,RSA.abcdef1234567890"
|
||||
},
|
||||
{
|
||||
"rel": "http://purl.org/openwebauth/v1",
|
||||
"type": "application/x-zot+json",
|
||||
"href": "#{person.url}owa"
|
||||
}
|
||||
]
|
||||
}
|
||||
JSON
|
||||
|
||||
<Link rel="http://purl.org/macgirvin/dfrn/1.0"
|
||||
href="#{person.profile_url}" />
|
||||
<Link rel="http://schemas.google.com/g/2010#updates-from"
|
||||
type="application/atom+xml"
|
||||
href="#{person.atom_url}" />
|
||||
<Link rel="http://webfinger.net/rel/profile-page"
|
||||
type="text/html"
|
||||
href="#{person.profile_url}" />
|
||||
<Link rel="http://microformats.org/profile/hcard"
|
||||
type="text/html"
|
||||
href="#{person.hcard_url}" />
|
||||
<Link rel="http://portablecontacts.net/spec/1.0"
|
||||
href="https://pod.example.tld/poco/trouble" />
|
||||
<Link rel="http://webfinger.net/rel/avatar"
|
||||
type="image/jpeg"
|
||||
href="http://localhost:3000/assets/user/default.png" />
|
||||
<Link rel="http://joindiaspora.com/seed_location" type="text/html" href="#{person.url}" />
|
||||
<Link rel="http://joindiaspora.com/guid" type="text/html" href="#{person.guid}" />
|
||||
<Link rel="diaspora-public-key" type="RSA" href="#{public_key_base64}" />
|
||||
|
||||
<Link rel="salmon"
|
||||
href="#{person.salmon_url}" />
|
||||
<Link rel="http://salmon-protocol.org/ns/salmon-replies"
|
||||
href="https://pod.example.tld/salmon/trouble" />
|
||||
<Link rel="http://salmon-protocol.org/ns/salmon-mention"
|
||||
href="https://pod.example.tld/salmon/trouble/mention" />
|
||||
<Link rel="http://ostatus.org/schema/1.0/subscribe"
|
||||
template="https://pod.example.tld/follow?url={uri}" />
|
||||
<Link rel="magic-public-key"
|
||||
href="data:application/magic-public-key,RSA.abcdef1234567890" />
|
||||
|
||||
<Property xmlns:mk="http://salmon-protocol.org/ns/magic-key"
|
||||
type="http://salmon-protocol.org/ns/magic-key"
|
||||
mk:key_id="1">RSA.abcdef1234567890</Property>
|
||||
|
||||
</XRD>
|
||||
XML
|
||||
|
||||
wf = Discovery::WebFinger.from_xml(friendica_xml)
|
||||
wf = Discovery::WebFinger.from_json(friendica_json)
|
||||
expect(wf.acct_uri).to eq(acct)
|
||||
expect(wf.hcard_url).to eq(person.hcard_url)
|
||||
expect(wf.hcard_url).to eq(friendica_hcard_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)
|
||||
expect(wf.subscribe_url).to eq("https://pod.example.tld/follow?url={uri}")
|
||||
expect(wf.profile_url).to eq(friendica_profile_url)
|
||||
expect(wf.atom_url).to eq(friendica_atom_url)
|
||||
expect(wf.salmon_url).to eq(friendica_salmon_url)
|
||||
expect(wf.subscribe_url).to eq(friendica_subscribe_url)
|
||||
end
|
||||
|
||||
it "reads redmatrix XML (no alias)" do
|
||||
redmatrix_xml = <<~XML
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
|
||||
it "reads hubzilla JSON" do
|
||||
hubzilla_hcard_url = "#{person.url}hcard/#{person.nickname}"
|
||||
hubzilla_profile_url = "#{person.url}profile/#{person.nickname}"
|
||||
hubzilla_atom_url = "#{person.url}ofeed/#{person.nickname}"
|
||||
hubzilla_subscribe_url = "#{person.url}follow?f=&url={uri}"
|
||||
|
||||
<Subject>#{person.diaspora_id}</Subject>
|
||||
hubzilla_json = <<~JSON
|
||||
{
|
||||
"subject": "#{acct}",
|
||||
"aliases": [
|
||||
"#{person.url}channel/#{person.nickname}",
|
||||
"#{person.url}~#{person.nickname}",
|
||||
"#{person.url}@#{person.nickname}"
|
||||
],
|
||||
"properties": {
|
||||
"http://webfinger.net/ns/name": "#{person.full_name}",
|
||||
"http://xmlns.com/foaf/0.1/name": "#{person.full_name}",
|
||||
"https://w3id.org/security/v1#publicKeyPem": #{person.serialized_public_key.dump},
|
||||
"http://purl.org/zot/federation": "zot6,zot,activitypub,diaspora"
|
||||
},
|
||||
"links": [
|
||||
{
|
||||
"rel": "http://webfinger.net/rel/avatar",
|
||||
"type": "image/jpeg",
|
||||
"href": "#{person.url}photo/profile/l/2"
|
||||
},
|
||||
{
|
||||
"rel": "http://microformats.org/profile/hcard",
|
||||
"type": "text/html",
|
||||
"href": "#{hubzilla_hcard_url}"
|
||||
},
|
||||
{
|
||||
"rel": "http://openid.net/specs/connect/1.0/issuer",
|
||||
"href": "#{person.url}"
|
||||
},
|
||||
{
|
||||
"rel": "http://webfinger.net/rel/profile-page",
|
||||
"href": "#{hubzilla_profile_url}"
|
||||
},
|
||||
{
|
||||
"rel": "http://schemas.google.com/g/2010#updates-from",
|
||||
"type": "application/atom+xml",
|
||||
"href": "#{hubzilla_atom_url}"
|
||||
},
|
||||
{
|
||||
"rel": "http://webfinger.net/rel/blog",
|
||||
"href": "#{person.url}channel/#{person.nickname}"
|
||||
},
|
||||
{
|
||||
"rel": "http://ostatus.org/schema/1.0/subscribe",
|
||||
"template": "#{hubzilla_subscribe_url}"
|
||||
},
|
||||
{
|
||||
"rel": "http://purl.org/zot/protocol/6.0",
|
||||
"type": "application/x-zot+json",
|
||||
"href": "#{person.url}channel/#{person.nickname}"
|
||||
},
|
||||
{
|
||||
"rel": "http://purl.org/zot/protocol",
|
||||
"href": "#{person.url}.well-known/zot-info?address=#{person.nickname}@#{person.diaspora_id.split('@')[1]}"
|
||||
},
|
||||
{
|
||||
"rel": "http://purl.org/openwebauth/v1",
|
||||
"type": "application/x-zot+json",
|
||||
"href": "#{person.url}owa"
|
||||
},
|
||||
{
|
||||
"rel": "magic-public-key",
|
||||
"href": "data:application/magic-public-key,RSA.abcdef1234567890"
|
||||
},
|
||||
{
|
||||
"rel": "self",
|
||||
"type": "application/ld+json; profile=\\\"https://www.w3.org/ns/activitystreams\\\"",
|
||||
"href": "#{person.url}channel/#{person.nickname}"
|
||||
},
|
||||
{
|
||||
"rel": "self",
|
||||
"type": "application/activity+json",
|
||||
"href": "#{person.url}channel/#{person.nickname}"
|
||||
},
|
||||
{
|
||||
"rel": "http://joindiaspora.com/seed_location",
|
||||
"type": "text/html",
|
||||
"href": "#{person.url}"
|
||||
},
|
||||
{
|
||||
"rel": "salmon",
|
||||
"href": "#{person.salmon_url}"
|
||||
}
|
||||
]
|
||||
}
|
||||
JSON
|
||||
|
||||
<Link rel="http://schemas.google.com/g/2010#updates-from"
|
||||
type="application/atom+xml"
|
||||
href="#{person.atom_url}" />
|
||||
<Link rel="http://webfinger.net/rel/profile-page"
|
||||
type="text/html"
|
||||
href="#{person.profile_url}" />
|
||||
<Link rel="http://portablecontacts.net/spec/1.0"
|
||||
href="https://pod.example.tld/poco/trouble" />
|
||||
<Link rel="http://webfinger.net/rel/avatar"
|
||||
type="image/jpeg"
|
||||
href="http://localhost:3000/assets/user/default.png" />
|
||||
<Link rel="http://microformats.org/profile/hcard"
|
||||
type="text/html"
|
||||
href="#{person.hcard_url}" />
|
||||
|
||||
<Link rel="magic-public-key"
|
||||
href="data:application/magic-public-key,RSA.abcdef1234567890" />
|
||||
|
||||
<Link rel="http://joindiaspora.com/seed_location" type="text/html" href="#{person.url}" />
|
||||
<Link rel="http://joindiaspora.com/guid" type="text/html" href="#{person.guid}" />
|
||||
<Link rel="diaspora-public-key" type="RSA" href="#{public_key_base64}" />
|
||||
|
||||
</XRD>
|
||||
XML
|
||||
|
||||
wf = Discovery::WebFinger.from_xml(redmatrix_xml)
|
||||
expect(wf.acct_uri).to eq(person.diaspora_id)
|
||||
expect(wf.hcard_url).to eq(person.hcard_url)
|
||||
wf = Discovery::WebFinger.from_json(hubzilla_json)
|
||||
expect(wf.acct_uri).to eq(acct)
|
||||
expect(wf.hcard_url).to eq(hubzilla_hcard_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 be_nil
|
||||
expect(wf.profile_url).to eq(hubzilla_profile_url)
|
||||
expect(wf.atom_url).to eq(hubzilla_atom_url)
|
||||
expect(wf.salmon_url).to eq(person.salmon_url)
|
||||
expect(wf.subscribe_url).to eq(hubzilla_subscribe_url)
|
||||
end
|
||||
|
||||
it "fails if the document is empty" do
|
||||
invalid_xml = <<~XML
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
|
||||
</XRD>
|
||||
XML
|
||||
expect { Discovery::WebFinger.from_xml(invalid_xml) }.to raise_error Discovery::InvalidData
|
||||
invalid_json = <<~JSON
|
||||
{}
|
||||
JSON
|
||||
expect { Discovery::WebFinger.from_json(invalid_json) }.to raise_error Discovery::InvalidData
|
||||
end
|
||||
|
||||
it "fails if the document is not XML" do
|
||||
expect { Discovery::WebFinger.from_xml("") }.to raise_error Discovery::InvalidDocument
|
||||
it "fails if the document is not JSON" do
|
||||
expect { Discovery::WebFinger.from_json("") }.to raise_error Discovery::InvalidDocument
|
||||
end
|
||||
|
||||
it "does not support XML anymore" do
|
||||
expect { Discovery::WebFinger.from_xml("") }
|
||||
.to raise_error "Parsing WebFinger as XML is not supported anymore, use 'from_json' instead."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,13 +4,6 @@ module DiasporaFederation
|
|||
describe ReceiveController, type: :routing do
|
||||
routes { DiasporaFederation::Engine.routes }
|
||||
|
||||
it "routes GET host-meta" do
|
||||
expect(get: ".well-known/host-meta").to route_to(
|
||||
controller: "diaspora_federation/webfinger",
|
||||
action: "host_meta"
|
||||
)
|
||||
end
|
||||
|
||||
it "routes GET webfinger" do
|
||||
expect(get: "/.well-known/webfinger").to route_to(
|
||||
controller: "diaspora_federation/webfinger",
|
||||
|
|
|
|||
Loading…
Reference in a new issue