forked from diaspora/diaspora
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathwebfinger.rb
123 lines (101 loc) · 3.1 KB
/
webfinger.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# Copyright (c) 2010-2012, Diaspora Inc. This file is
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
class Webfinger
include Diaspora::Logging
attr_accessor :host_meta_xrd, :webfinger_profile_xrd,
:webfinger_profile, :hcard, :hcard_xrd, :person,
:account, :ssl
def initialize(account)
self.account = account
self.ssl = true
end
def fetch
return person if existing_person_with_profile?
create_or_update_person_from_webfinger_profile!
end
def self.in_background(account, opts={})
Workers::FetchWebfinger.perform_async(account)
end
#everything below should be private I guess
def account=(str)
@account = str.strip.gsub('acct:','').to_s.downcase
end
def get(url)
logger.info "Getting: #{url} for #{account}"
begin
res = Faraday.get(url)
unless res.success?
raise "Failed to fetch #{url}: #{res.status}"
end
res.body
rescue OpenSSL::SSL::SSLError => e
logger.error "Failed to fetch #{url}: SSL setup invalid"
raise e
rescue => e
logger.error "Failed to fetch: #{url} for #{account}; #{e.message}"
raise e
end
end
def existing_person_with_profile?
cached_person.present? && cached_person.profile.present?
end
def cached_person
self.person ||= Person.by_account_identifier(account)
end
def create_or_update_person_from_webfinger_profile!
logger.info "webfingering #{account}, it is not known or needs updating"
if person #update my profile please
person.assign_new_profile_from_hcard(self.hcard)
else
person = make_person_from_webfinger
end
logger.info "successfully webfingered #{@account}" if person
person
end
#this tries the xrl url with https first, then falls back to http
def host_meta_xrd
begin
get(host_meta_url)
rescue => e
if self.ssl
self.ssl = false
retry
else
raise "there was an error getting the xrd from account #{@account}: #{e.message}"
end
end
end
def hcard
@hcard ||= HCard.build(hcard_xrd)
end
def webfinger_profile
@webfinger_profile ||= WebfingerProfile.new(account, webfinger_profile_xrd)
end
def hcard_url
self.webfinger_profile.hcard
end
def webfinger_profile_url
doc = Nokogiri::XML(self.host_meta_xrd)
return nil if doc.namespaces["xmlns"] != "http://docs.oasis-open.org/ns/xri/xrd-1.0"
swizzle doc.search('Link').find{|x| x['rel']=='lrdd'}['template']
end
def webfinger_profile_xrd
@webfinger_profile_xrd ||= get(webfinger_profile_url)
logger.warn "#{@account} doesn't exists anymore" if @webfinger_profile_xrd == false
@webfinger_profile_xrd
end
def hcard_xrd
@hcard_xrd ||= get(hcard_url)
end
def make_person_from_webfinger
Person.create_from_webfinger(webfinger_profile, hcard) unless webfinger_profile_xrd == false
end
def host_meta_url
domain = account.split('@')[1]
"http#{'s' if self.ssl}://#{domain}/.well-known/host-meta"
end
def swizzle(template)
template.gsub('{uri}', account)
end
end