diaspora_federation 0.0.13 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +15 -32
- data/lib/diaspora_federation.rb +9 -31
- data/lib/diaspora_federation/discovery/h_card.rb +8 -15
- data/lib/diaspora_federation/discovery/host_meta.rb +2 -4
- data/lib/diaspora_federation/discovery/web_finger.rb +11 -11
- data/lib/diaspora_federation/discovery/xrd_document.rb +4 -8
- data/lib/diaspora_federation/entities.rb +2 -0
- data/lib/diaspora_federation/entities/account_deletion.rb +5 -0
- data/lib/diaspora_federation/entities/comment.rb +3 -6
- data/lib/diaspora_federation/entities/contact.rb +5 -0
- data/lib/diaspora_federation/entities/conversation.rb +10 -1
- data/lib/diaspora_federation/entities/message.rb +29 -4
- data/lib/diaspora_federation/entities/participation.rb +24 -0
- data/lib/diaspora_federation/entities/poll_participation.rb +3 -6
- data/lib/diaspora_federation/entities/profile.rb +5 -0
- data/lib/diaspora_federation/entities/related_entity.rb +33 -0
- data/lib/diaspora_federation/entities/relayable.rb +55 -40
- data/lib/diaspora_federation/entities/relayable_retraction.rb +21 -12
- data/lib/diaspora_federation/entities/request.rb +6 -2
- data/lib/diaspora_federation/entities/reshare.rb +5 -0
- data/lib/diaspora_federation/entities/retraction.rb +37 -0
- data/lib/diaspora_federation/entities/signed_retraction.rb +16 -5
- data/lib/diaspora_federation/entities/status_message.rb +11 -0
- data/lib/diaspora_federation/entity.rb +73 -30
- data/lib/diaspora_federation/federation/fetcher.rb +11 -1
- data/lib/diaspora_federation/federation/receiver.rb +10 -0
- data/lib/diaspora_federation/federation/receiver/abstract_receiver.rb +18 -4
- data/lib/diaspora_federation/federation/receiver/exceptions.rb +4 -0
- data/lib/diaspora_federation/federation/receiver/public.rb +10 -0
- data/lib/diaspora_federation/federation/sender.rb +1 -1
- data/lib/diaspora_federation/http_client.rb +1 -2
- data/lib/diaspora_federation/logging.rb +6 -0
- data/lib/diaspora_federation/properties_dsl.rb +4 -2
- data/lib/diaspora_federation/salmon/encrypted_magic_envelope.rb +2 -2
- data/lib/diaspora_federation/salmon/encrypted_slap.rb +3 -5
- data/lib/diaspora_federation/salmon/exceptions.rb +1 -1
- data/lib/diaspora_federation/salmon/magic_envelope.rb +16 -17
- data/lib/diaspora_federation/salmon/slap.rb +1 -2
- data/lib/diaspora_federation/salmon/xml_payload.rb +1 -2
- data/lib/diaspora_federation/validators.rb +2 -0
- data/lib/diaspora_federation/validators/conversation_validator.rb +2 -0
- data/lib/diaspora_federation/validators/message_validator.rb +2 -2
- data/lib/diaspora_federation/validators/participation_validator.rb +3 -2
- data/lib/diaspora_federation/validators/poll_validator.rb +1 -0
- data/lib/diaspora_federation/validators/related_entity_validator.rb +12 -0
- data/lib/diaspora_federation/validators/relayable_retraction_validator.rb +1 -1
- data/lib/diaspora_federation/validators/relayable_validator.rb +1 -0
- data/lib/diaspora_federation/validators/retraction_validator.rb +1 -1
- data/lib/diaspora_federation/validators/rules/diaspora_id.rb +8 -11
- data/lib/diaspora_federation/validators/rules/diaspora_id_count.rb +1 -1
- data/lib/diaspora_federation/validators/signed_retraction_validator.rb +1 -1
- data/lib/diaspora_federation/validators/status_message_validator.rb +2 -0
- data/lib/diaspora_federation/validators/web_finger_validator.rb +2 -2
- data/lib/diaspora_federation/version.rb +1 -1
- metadata +9 -7
@@ -30,10 +30,15 @@ module DiasporaFederation
|
|
30
30
|
# @return [String] author signature
|
31
31
|
property :target_author_signature, default: nil
|
32
32
|
|
33
|
+
# @!attribute [r] target
|
34
|
+
# target entity
|
35
|
+
# @return [RelatedEntity] target entity
|
36
|
+
entity :target, Entities::RelatedEntity
|
37
|
+
|
33
38
|
# use only {Retraction} for receive
|
34
39
|
# @return [Retraction] instance as normal retraction
|
35
40
|
def to_retraction
|
36
|
-
Retraction.new(author: author, target_guid: target_guid, target_type: target_type)
|
41
|
+
Retraction.new(author: author, target_guid: target_guid, target_type: target_type, target: target)
|
37
42
|
end
|
38
43
|
|
39
44
|
# Create signature for a retraction
|
@@ -44,14 +49,20 @@ module DiasporaFederation
|
|
44
49
|
Base64.strict_encode64(privkey.sign(Relayable::DIGEST, [ret.target_guid, ret.target_type].join(";")))
|
45
50
|
end
|
46
51
|
|
52
|
+
# @return [String] string representation of this object
|
53
|
+
def to_s
|
54
|
+
"SignedRetraction:#{target_type}:#{target_guid}"
|
55
|
+
end
|
56
|
+
|
47
57
|
private
|
48
58
|
|
49
59
|
# @param [Nokogiri::XML::Element] root_node xml nodes
|
50
60
|
# @return [Retraction] instance
|
51
|
-
def self.populate_entity(root_node)
|
52
|
-
|
61
|
+
private_class_method def self.populate_entity(root_node)
|
62
|
+
entity_data = entity_data(root_node)
|
63
|
+
entity_data[:target] = Retraction.send(:fetch_target, entity_data[:target_type], entity_data[:target_guid])
|
64
|
+
new(entity_data).to_retraction
|
53
65
|
end
|
54
|
-
private_class_method :populate_entity
|
55
66
|
|
56
67
|
# It updates also the signatures with the keys of the author and the parent
|
57
68
|
# if the signatures are not there yet and if the keys are available.
|
@@ -64,7 +75,7 @@ module DiasporaFederation
|
|
64
75
|
end
|
65
76
|
|
66
77
|
def sign_with_author
|
67
|
-
privkey = DiasporaFederation.callbacks.trigger(:
|
78
|
+
privkey = DiasporaFederation.callbacks.trigger(:fetch_private_key, author)
|
68
79
|
SignedRetraction.sign_with_key(privkey, self) unless privkey.nil?
|
69
80
|
end
|
70
81
|
end
|
@@ -30,6 +30,17 @@ module DiasporaFederation
|
|
30
30
|
# shows whether the status message is visible to everyone or only to some aspects
|
31
31
|
# @return [Boolean] is it public
|
32
32
|
property :public, default: false
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def validate
|
37
|
+
super
|
38
|
+
photos.each do |photo|
|
39
|
+
if photo.author != author
|
40
|
+
raise ValidationError, "nested #{photo} has different author: author=#{author} obj=#{self}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
33
44
|
end
|
34
45
|
end
|
35
46
|
end
|
@@ -34,6 +34,11 @@ module DiasporaFederation
|
|
34
34
|
# are intended to be immutable data containers, only.
|
35
35
|
class Entity
|
36
36
|
extend PropertiesDSL
|
37
|
+
include Logging
|
38
|
+
|
39
|
+
# Invalid XML characters
|
40
|
+
# @see https://www.w3.org/TR/REC-xml/#charsets "Extensible Markup Language (XML) 1.0"
|
41
|
+
INVALID_XML_REGEX = /[^\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD\u{10000}-\u{10FFFF}]/
|
37
42
|
|
38
43
|
# Initializes the Entity with the given attribute hash and freezes the created
|
39
44
|
# instance it returns.
|
@@ -50,27 +55,35 @@ module DiasporaFederation
|
|
50
55
|
# @param [Hash] data entity data
|
51
56
|
# @return [Entity] new instance
|
52
57
|
def initialize(data)
|
58
|
+
logger.debug "create entity #{self.class} with data: #{data}"
|
53
59
|
raise ArgumentError, "expected a Hash" unless data.is_a?(Hash)
|
60
|
+
|
54
61
|
entity_data = self.class.resolv_aliases(data)
|
55
|
-
|
56
|
-
unless missing_props.empty?
|
57
|
-
raise ArgumentError, "missing required properties: #{missing_props.join(', ')}"
|
58
|
-
end
|
62
|
+
validate_missing_props(entity_data)
|
59
63
|
|
60
64
|
self.class.default_values.merge(entity_data).each do |name, value|
|
61
|
-
instance_variable_set("@#{name}", nilify(value)) if setable?(name, value)
|
65
|
+
instance_variable_set("@#{name}", instantiate_nested(name, nilify(value))) if setable?(name, value)
|
62
66
|
end
|
63
67
|
|
64
68
|
freeze
|
65
69
|
validate
|
66
70
|
end
|
67
71
|
|
68
|
-
# Returns a Hash representing this Entity (attributes => values)
|
72
|
+
# Returns a Hash representing this Entity (attributes => values).
|
73
|
+
# Nested entities are also converted to a Hash.
|
69
74
|
# @return [Hash] entity data (mostly equal to the hash used for initialization).
|
70
75
|
def to_h
|
71
|
-
|
72
|
-
|
73
|
-
|
76
|
+
properties.map {|key, value|
|
77
|
+
type = self.class.class_props[key]
|
78
|
+
|
79
|
+
if type == String || value.nil?
|
80
|
+
[key, value]
|
81
|
+
elsif type.instance_of?(Class)
|
82
|
+
[key, value.to_h]
|
83
|
+
elsif type.instance_of?(Array)
|
84
|
+
[key, value.map(&:to_h)]
|
85
|
+
end
|
86
|
+
}.to_h
|
74
87
|
end
|
75
88
|
|
76
89
|
# Returns the XML representation for this entity constructed out of
|
@@ -131,8 +144,18 @@ module DiasporaFederation
|
|
131
144
|
Entities.const_get(class_name)
|
132
145
|
end
|
133
146
|
|
147
|
+
# @return [String] string representation of this object
|
148
|
+
def to_s
|
149
|
+
"#{self.class.name.rpartition('::').last}#{":#{guid}" if respond_to?(:guid)}"
|
150
|
+
end
|
151
|
+
|
134
152
|
private
|
135
153
|
|
154
|
+
def validate_missing_props(entity_data)
|
155
|
+
missing_props = self.class.missing_props(entity_data)
|
156
|
+
raise ArgumentError, "missing required properties: #{missing_props.join(', ')}" unless missing_props.empty?
|
157
|
+
end
|
158
|
+
|
136
159
|
def setable?(name, val)
|
137
160
|
type = self.class.class_props[name]
|
138
161
|
return false if type.nil? # property undefined
|
@@ -145,18 +168,30 @@ module DiasporaFederation
|
|
145
168
|
end
|
146
169
|
|
147
170
|
def setable_nested?(type, val)
|
148
|
-
type.
|
171
|
+
type.instance_of?(Class) && type.ancestors.include?(Entity) && (val.is_a?(Entity) || val.is_a?(Hash))
|
149
172
|
end
|
150
173
|
|
151
174
|
def setable_multi?(type, val)
|
152
|
-
type.instance_of?(Array) && val.instance_of?(Array) &&
|
175
|
+
type.instance_of?(Array) && val.instance_of?(Array) &&
|
176
|
+
(val.all? {|v| v.instance_of?(type.first) } || val.all? {|v| v.instance_of?(Hash) })
|
153
177
|
end
|
154
178
|
|
155
179
|
def nilify(value)
|
156
|
-
return nil if value.respond_to?(:empty?) && value.empty?
|
180
|
+
return nil if value.respond_to?(:empty?) && value.empty? && !value.instance_of?(Array)
|
157
181
|
value
|
158
182
|
end
|
159
183
|
|
184
|
+
def instantiate_nested(name, value)
|
185
|
+
if value.instance_of?(Array)
|
186
|
+
return value unless value.first.instance_of?(Hash)
|
187
|
+
value.map {|hash| self.class.class_props[name].first.new(hash) }
|
188
|
+
elsif value.instance_of?(Hash)
|
189
|
+
self.class.class_props[name].new(value)
|
190
|
+
else
|
191
|
+
value
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
160
195
|
def validate
|
161
196
|
validator_name = "#{self.class.name.split('::').last}Validator"
|
162
197
|
return unless Validators.const_defined? validator_name
|
@@ -173,8 +208,15 @@ module DiasporaFederation
|
|
173
208
|
"Failed validation for properties: #{errors.join(' | ')}"
|
174
209
|
end
|
175
210
|
|
211
|
+
# @return [Hash] hash with all properties
|
212
|
+
def properties
|
213
|
+
self.class.class_props.keys.each_with_object({}) do |prop, hash|
|
214
|
+
hash[prop] = public_send(prop)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
176
218
|
def xml_elements
|
177
|
-
|
219
|
+
properties.map {|name, value| [name, self.class.class_props[name] == String ? value.to_s : value] }.to_h
|
178
220
|
end
|
179
221
|
|
180
222
|
def add_property_to_xml(doc, root_element, name, value)
|
@@ -183,7 +225,8 @@ module DiasporaFederation
|
|
183
225
|
else
|
184
226
|
# call #to_xml for each item and append to root
|
185
227
|
[*value].compact.each do |item|
|
186
|
-
|
228
|
+
child = item.to_xml
|
229
|
+
root_element << child if child
|
187
230
|
end
|
188
231
|
end
|
189
232
|
end
|
@@ -192,26 +235,30 @@ module DiasporaFederation
|
|
192
235
|
def simple_node(doc, name, value)
|
193
236
|
xml_name = self.class.xml_names[name]
|
194
237
|
Nokogiri::XML::Element.new(xml_name ? xml_name.to_s : name, doc).tap do |node|
|
195
|
-
node.content = value unless value.empty?
|
238
|
+
node.content = value.gsub(INVALID_XML_REGEX, "\uFFFD") unless value.empty?
|
196
239
|
end
|
197
240
|
end
|
198
241
|
|
199
242
|
# @param [Nokogiri::XML::Element] root_node xml nodes
|
200
243
|
# @return [Entity] instance
|
201
|
-
def self.populate_entity(root_node)
|
202
|
-
entity_data
|
203
|
-
|
204
|
-
}]
|
244
|
+
private_class_method def self.populate_entity(root_node)
|
245
|
+
new(entity_data(root_node))
|
246
|
+
end
|
205
247
|
|
206
|
-
|
248
|
+
# @param [Nokogiri::XML::Element] root_node xml nodes
|
249
|
+
# @return [Hash] entity data
|
250
|
+
private_class_method def self.entity_data(root_node)
|
251
|
+
class_props.map {|name, type|
|
252
|
+
value = parse_element_from_node(name, type, root_node)
|
253
|
+
[name, value] if value
|
254
|
+
}.compact.to_h
|
207
255
|
end
|
208
|
-
private_class_method :populate_entity
|
209
256
|
|
210
257
|
# @param [String] name property name to parse
|
211
258
|
# @param [Class] type target type to parse
|
212
259
|
# @param [Nokogiri::XML::Element] root_node XML node to parse
|
213
260
|
# @return [Object] parsed data
|
214
|
-
def self.parse_element_from_node(name, type, root_node)
|
261
|
+
private_class_method def self.parse_element_from_node(name, type, root_node)
|
215
262
|
if type == String
|
216
263
|
parse_string_from_node(name, root_node)
|
217
264
|
elsif type.instance_of?(Array)
|
@@ -220,41 +267,37 @@ module DiasporaFederation
|
|
220
267
|
parse_entity_from_node(type, root_node)
|
221
268
|
end
|
222
269
|
end
|
223
|
-
private_class_method :parse_element_from_node
|
224
270
|
|
225
271
|
# create simple entry in data hash
|
226
272
|
#
|
227
273
|
# @param [String] name xml tag to parse
|
228
274
|
# @param [Nokogiri::XML::Element] root_node XML root_node to parse
|
229
275
|
# @return [String] data
|
230
|
-
def self.parse_string_from_node(name, root_node)
|
276
|
+
private_class_method def self.parse_string_from_node(name, root_node)
|
231
277
|
node = root_node.xpath(name.to_s)
|
232
278
|
node = root_node.xpath(xml_names[name].to_s) if node.empty?
|
233
279
|
node.first.text if node.any?
|
234
280
|
end
|
235
|
-
private_class_method :parse_string_from_node
|
236
281
|
|
237
282
|
# create an entry in the data hash for the nested entity
|
238
283
|
#
|
239
284
|
# @param [Class] type target type to parse
|
240
285
|
# @param [Nokogiri::XML::Element] root_node XML node to parse
|
241
286
|
# @return [Entity] parsed child entity
|
242
|
-
def self.parse_entity_from_node(type, root_node)
|
287
|
+
private_class_method def self.parse_entity_from_node(type, root_node)
|
243
288
|
node = root_node.xpath(type.entity_name)
|
244
289
|
type.from_xml(node.first) if node.any?
|
245
290
|
end
|
246
|
-
private_class_method :parse_entity_from_node
|
247
291
|
|
248
292
|
# collect all nested children of that type and create an array in the data hash
|
249
293
|
#
|
250
294
|
# @param [Class] type target type to parse
|
251
295
|
# @param [Nokogiri::XML::Element] root_node XML node to parse
|
252
296
|
# @return [Array<Entity>] array with parsed child entities
|
253
|
-
def self.parse_array_from_node(type, root_node)
|
297
|
+
private_class_method def self.parse_array_from_node(type, root_node)
|
254
298
|
node = root_node.xpath(type.entity_name)
|
255
|
-
node.map {|child| type.from_xml(child) }
|
299
|
+
node.map {|child| type.from_xml(child) } unless node.empty?
|
256
300
|
end
|
257
|
-
private_class_method :parse_array_from_node
|
258
301
|
|
259
302
|
# Raised, if entity is not valid
|
260
303
|
class ValidationError < RuntimeError
|
@@ -7,7 +7,9 @@ module DiasporaFederation
|
|
7
7
|
# @param [Symbol, String] entity_type snake_case version of the entity class
|
8
8
|
# @param [String] guid guid of the entity to fetch
|
9
9
|
def self.fetch_public(author, entity_type, guid)
|
10
|
-
url = DiasporaFederation.callbacks.trigger(
|
10
|
+
url = DiasporaFederation.callbacks.trigger(
|
11
|
+
:fetch_person_url_to, author, "/fetch/#{entity_name(entity_type)}/#{guid}"
|
12
|
+
)
|
11
13
|
response = HttpClient.get(url)
|
12
14
|
raise "Failed to fetch #{url}: #{response.status}" unless response.success?
|
13
15
|
|
@@ -18,6 +20,14 @@ module DiasporaFederation
|
|
18
20
|
raise NotFetchable, "Failed to fetch #{entity_type}:#{guid} from #{author}: #{e.class}: #{e.message}"
|
19
21
|
end
|
20
22
|
|
23
|
+
private_class_method def self.entity_name(class_name)
|
24
|
+
return class_name if class_name =~ /^[a-z]*(_[a-z]*)*$/
|
25
|
+
|
26
|
+
raise DiasporaFederation::Entity::UnknownEntity, class_name unless Entities.const_defined?(class_name)
|
27
|
+
|
28
|
+
class_name.gsub(/(.)([A-Z])/, '\1_\2').downcase
|
29
|
+
end
|
30
|
+
|
21
31
|
# Raised, if the entity is not fetchable
|
22
32
|
class NotFetchable < RuntimeError
|
23
33
|
end
|
@@ -2,6 +2,8 @@ module DiasporaFederation
|
|
2
2
|
module Federation
|
3
3
|
# this module is for parse and receive entities.
|
4
4
|
module Receiver
|
5
|
+
extend Logging
|
6
|
+
|
5
7
|
# receive a public message
|
6
8
|
# @param [String] data message to receive
|
7
9
|
# @param [Boolean] legacy use old slap parser
|
@@ -13,6 +15,10 @@ module DiasporaFederation
|
|
13
15
|
Salmon::MagicEnvelope.unenvelop(magic_env_xml)
|
14
16
|
end
|
15
17
|
Public.new(magic_env).receive
|
18
|
+
rescue => e
|
19
|
+
logger.error "failed to receive public message: #{e.class}: #{e.message}"
|
20
|
+
logger.debug "received data:\n#{data}"
|
21
|
+
raise e
|
16
22
|
end
|
17
23
|
|
18
24
|
# receive a private message
|
@@ -30,6 +36,10 @@ module DiasporaFederation
|
|
30
36
|
Salmon::MagicEnvelope.unenvelop(magic_env_xml)
|
31
37
|
end
|
32
38
|
Private.new(magic_env, recipient_id).receive
|
39
|
+
rescue => e
|
40
|
+
logger.error "failed to receive private message for #{recipient_id}: #{e.class}: #{e.message}"
|
41
|
+
logger.debug "received data:\n#{data}"
|
42
|
+
raise e
|
33
43
|
end
|
34
44
|
end
|
35
45
|
end
|
@@ -3,6 +3,8 @@ module DiasporaFederation
|
|
3
3
|
module Receiver
|
4
4
|
# common functionality for receivers
|
5
5
|
class AbstractReceiver
|
6
|
+
include Logging
|
7
|
+
|
6
8
|
# create a new receiver
|
7
9
|
# @param [MagicEnvelope] magic_envelope the received magic envelope
|
8
10
|
# @param [Object] recipient_id the identifier of the recipient of a private message
|
@@ -14,20 +16,32 @@ module DiasporaFederation
|
|
14
16
|
|
15
17
|
# validate and receive the entity
|
16
18
|
def receive
|
17
|
-
|
18
|
-
|
19
|
+
validate_and_receive
|
20
|
+
rescue => e
|
21
|
+
logger.error "failed to receive #{entity}"
|
22
|
+
raise e
|
19
23
|
end
|
20
24
|
|
21
25
|
private
|
22
26
|
|
23
27
|
attr_reader :entity, :sender, :recipient_id
|
24
28
|
|
29
|
+
def validate_and_receive
|
30
|
+
validate
|
31
|
+
DiasporaFederation.callbacks.trigger(:receive_entity, entity, recipient_id)
|
32
|
+
logger.info "successfully received #{entity} from person #{sender}#{" for #{recipient_id}" if recipient_id}"
|
33
|
+
end
|
34
|
+
|
25
35
|
def validate
|
26
|
-
raise InvalidSender unless sender_valid?
|
36
|
+
raise InvalidSender, "invalid sender: #{sender}" unless sender_valid?
|
27
37
|
end
|
28
38
|
|
29
39
|
def sender_valid?
|
30
|
-
|
40
|
+
if entity.respond_to?(:sender_valid?)
|
41
|
+
entity.sender_valid?(sender)
|
42
|
+
else
|
43
|
+
sender == entity.author
|
44
|
+
end
|
31
45
|
end
|
32
46
|
end
|
33
47
|
end
|
@@ -8,6 +8,10 @@ module DiasporaFederation
|
|
8
8
|
# Raised, if receiving a private message without recipient.
|
9
9
|
class RecipientRequired < RuntimeError
|
10
10
|
end
|
11
|
+
|
12
|
+
# Raised, if receiving a message with public receiver which is not public but should be.
|
13
|
+
class NotPublic < RuntimeError
|
14
|
+
end
|
11
15
|
end
|
12
16
|
end
|
13
17
|
end
|
@@ -3,6 +3,16 @@ module DiasporaFederation
|
|
3
3
|
module Receiver
|
4
4
|
# receiver for public entities
|
5
5
|
class Public < AbstractReceiver
|
6
|
+
private
|
7
|
+
|
8
|
+
def validate
|
9
|
+
super
|
10
|
+
raise NotPublic if entity_can_be_public_but_it_is_not?
|
11
|
+
end
|
12
|
+
|
13
|
+
def entity_can_be_public_but_it_is_not?
|
14
|
+
entity.respond_to?(:public) && !entity.public
|
15
|
+
end
|
6
16
|
end
|
7
17
|
end
|
8
18
|
end
|
@@ -24,7 +24,7 @@ module DiasporaFederation
|
|
24
24
|
def self.private(sender_id, obj_str, targets)
|
25
25
|
hydra = HydraWrapper.new(sender_id, obj_str)
|
26
26
|
targets.each {|url, xml| hydra.insert_job(url, xml) }
|
27
|
-
|
27
|
+
hydra.send.map {|url| [url, targets[url]] }.to_h
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end
|
@@ -23,7 +23,7 @@ module DiasporaFederation
|
|
23
23
|
@connection.dup
|
24
24
|
end
|
25
25
|
|
26
|
-
def self.create_default_connection
|
26
|
+
private_class_method def self.create_default_connection
|
27
27
|
options = {
|
28
28
|
request: {timeout: DiasporaFederation.http_timeout},
|
29
29
|
ssl: {ca_file: DiasporaFederation.certificate_authorities}
|
@@ -36,6 +36,5 @@ module DiasporaFederation
|
|
36
36
|
|
37
37
|
@connection.headers["User-Agent"] = DiasporaFederation.http_user_agent
|
38
38
|
end
|
39
|
-
private_class_method :create_default_connection
|
40
39
|
end
|
41
40
|
end
|
@@ -3,6 +3,12 @@ module DiasporaFederation
|
|
3
3
|
#
|
4
4
|
# it uses the logging-gem if available
|
5
5
|
module Logging
|
6
|
+
# add +logger+ also as class method when included
|
7
|
+
# @param [Class] klass the class into which the module is included
|
8
|
+
def self.included(klass)
|
9
|
+
klass.extend(self)
|
10
|
+
end
|
11
|
+
|
6
12
|
private
|
7
13
|
|
8
14
|
# get the logger for this class
|