diaspora_federation 0.2.7 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Changelog.md +25 -0
- data/lib/diaspora_federation/callbacks.rb +2 -0
- data/lib/diaspora_federation/discovery/discovery.rb +13 -22
- data/lib/diaspora_federation/discovery/exceptions.rb +2 -0
- data/lib/diaspora_federation/discovery/h_card.rb +3 -12
- data/lib/diaspora_federation/discovery/web_finger.rb +33 -36
- data/lib/diaspora_federation/discovery/xrd_document.rb +14 -15
- data/lib/diaspora_federation/discovery.rb +2 -1
- data/lib/diaspora_federation/entities/account_deletion.rb +3 -1
- data/lib/diaspora_federation/entities/account_migration/signable.rb +2 -0
- data/lib/diaspora_federation/entities/account_migration.rb +5 -1
- data/lib/diaspora_federation/entities/comment.rb +3 -1
- data/lib/diaspora_federation/entities/contact.rb +2 -0
- data/lib/diaspora_federation/entities/conversation.rb +4 -2
- data/lib/diaspora_federation/entities/embed.rb +2 -0
- data/lib/diaspora_federation/entities/event.rb +2 -0
- data/lib/diaspora_federation/entities/event_participation.rb +3 -1
- data/lib/diaspora_federation/entities/like.rb +3 -1
- data/lib/diaspora_federation/entities/location.rb +2 -0
- data/lib/diaspora_federation/entities/message.rb +3 -1
- data/lib/diaspora_federation/entities/participation.rb +5 -3
- data/lib/diaspora_federation/entities/person.rb +3 -1
- data/lib/diaspora_federation/entities/photo.rb +3 -1
- data/lib/diaspora_federation/entities/poll.rb +2 -0
- data/lib/diaspora_federation/entities/poll_answer.rb +2 -0
- data/lib/diaspora_federation/entities/poll_participation.rb +3 -1
- data/lib/diaspora_federation/entities/post.rb +3 -1
- data/lib/diaspora_federation/entities/profile.rb +3 -1
- data/lib/diaspora_federation/entities/related_entity.rb +3 -1
- data/lib/diaspora_federation/entities/relayable.rb +18 -31
- data/lib/diaspora_federation/entities/reshare.rb +4 -2
- data/lib/diaspora_federation/entities/retraction.rb +6 -4
- data/lib/diaspora_federation/entities/signable.rb +3 -1
- data/lib/diaspora_federation/entities/status_message.rb +3 -1
- data/lib/diaspora_federation/entities.rb +2 -5
- data/lib/diaspora_federation/entity.rb +15 -11
- data/lib/diaspora_federation/federation/diaspora_url_parser.rb +4 -1
- data/lib/diaspora_federation/federation/fetcher.rb +3 -0
- data/lib/diaspora_federation/federation/receiver/abstract_receiver.rb +2 -0
- data/lib/diaspora_federation/federation/receiver/exceptions.rb +2 -0
- data/lib/diaspora_federation/federation/receiver/private.rb +3 -0
- data/lib/diaspora_federation/federation/receiver/public.rb +2 -0
- data/lib/diaspora_federation/federation/receiver.rb +9 -16
- data/lib/diaspora_federation/federation/sender/hydra_wrapper.rb +2 -0
- data/lib/diaspora_federation/federation/sender.rb +3 -1
- data/lib/diaspora_federation/federation.rb +2 -0
- data/lib/diaspora_federation/http_client.rb +5 -2
- data/lib/diaspora_federation/logging.rb +8 -6
- data/lib/diaspora_federation/parsers/base_parser.rb +4 -0
- data/lib/diaspora_federation/parsers/json_parser.rb +9 -6
- data/lib/diaspora_federation/parsers/relayable_json_parser.rb +3 -0
- data/lib/diaspora_federation/parsers/relayable_xml_parser.rb +2 -0
- data/lib/diaspora_federation/parsers/xml_parser.rb +20 -8
- data/lib/diaspora_federation/parsers.rb +2 -0
- data/lib/diaspora_federation/properties_dsl.rb +8 -41
- data/lib/diaspora_federation/salmon/aes.rb +5 -3
- data/lib/diaspora_federation/salmon/encrypted_magic_envelope.rb +4 -2
- data/lib/diaspora_federation/salmon/exceptions.rb +2 -20
- data/lib/diaspora_federation/salmon/magic_envelope.rb +13 -10
- data/lib/diaspora_federation/salmon.rb +3 -4
- data/lib/diaspora_federation/validators/account_deletion_validator.rb +2 -0
- data/lib/diaspora_federation/validators/account_migration_validator.rb +2 -0
- data/lib/diaspora_federation/validators/comment_validator.rb +2 -0
- data/lib/diaspora_federation/validators/contact_validator.rb +2 -0
- data/lib/diaspora_federation/validators/conversation_validator.rb +2 -0
- data/lib/diaspora_federation/validators/embed_validator.rb +2 -0
- data/lib/diaspora_federation/validators/event_participation_validator.rb +2 -0
- data/lib/diaspora_federation/validators/event_validator.rb +2 -0
- data/lib/diaspora_federation/validators/h_card_validator.rb +2 -0
- data/lib/diaspora_federation/validators/like_validator.rb +2 -0
- data/lib/diaspora_federation/validators/location_validator.rb +2 -0
- data/lib/diaspora_federation/validators/message_validator.rb +2 -0
- data/lib/diaspora_federation/validators/optional_aware_validator.rb +3 -0
- data/lib/diaspora_federation/validators/participation_validator.rb +2 -0
- data/lib/diaspora_federation/validators/person_validator.rb +2 -0
- data/lib/diaspora_federation/validators/photo_validator.rb +2 -0
- data/lib/diaspora_federation/validators/poll_answer_validator.rb +2 -0
- data/lib/diaspora_federation/validators/poll_participation_validator.rb +2 -0
- data/lib/diaspora_federation/validators/poll_validator.rb +2 -0
- data/lib/diaspora_federation/validators/profile_validator.rb +2 -0
- data/lib/diaspora_federation/validators/related_entity_validator.rb +2 -0
- data/lib/diaspora_federation/validators/relayable_validator.rb +2 -0
- data/lib/diaspora_federation/validators/reshare_validator.rb +2 -0
- data/lib/diaspora_federation/validators/retraction_validator.rb +2 -0
- data/lib/diaspora_federation/validators/rules/birthday.rb +3 -1
- data/lib/diaspora_federation/validators/rules/boolean.rb +6 -5
- data/lib/diaspora_federation/validators/rules/diaspora_id.rb +3 -1
- data/lib/diaspora_federation/validators/rules/diaspora_id_list.rb +3 -0
- data/lib/diaspora_federation/validators/rules/guid.rb +3 -1
- data/lib/diaspora_federation/validators/rules/not_nil.rb +2 -0
- data/lib/diaspora_federation/validators/rules/public_key.rb +2 -0
- data/lib/diaspora_federation/validators/rules/tag_count.rb +2 -0
- data/lib/diaspora_federation/validators/status_message_validator.rb +2 -0
- data/lib/diaspora_federation/validators/web_finger_validator.rb +2 -0
- data/lib/diaspora_federation/validators.rb +2 -0
- data/lib/diaspora_federation/version.rb +3 -1
- data/lib/diaspora_federation.rb +3 -2
- metadata +16 -28
- data/lib/diaspora_federation/discovery/host_meta.rb +0 -90
- data/lib/diaspora_federation/entities/relayable_retraction.rb +0 -66
- data/lib/diaspora_federation/entities/request.rb +0 -31
- data/lib/diaspora_federation/entities/signed_retraction.rb +0 -43
- data/lib/diaspora_federation/salmon/encrypted_slap.rb +0 -109
- data/lib/diaspora_federation/salmon/slap.rb +0 -55
- data/lib/diaspora_federation/salmon/xml_payload.rb +0 -41
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module DiasporaFederation
|
2
4
|
module Parsers
|
3
5
|
# This is a parser of JSON serialized object. JSON object format is defined by
|
@@ -15,27 +17,29 @@ module DiasporaFederation
|
|
15
17
|
private
|
16
18
|
|
17
19
|
def parse_entity_data(entity_data)
|
18
|
-
hash = entity_data.
|
19
|
-
property = entity_type.
|
20
|
+
hash = entity_data.to_h {|key, value|
|
21
|
+
property = entity_type.class_props.keys.find {|name| name.to_s == key }
|
20
22
|
if property
|
21
23
|
type = entity_type.class_props[property]
|
22
24
|
[property, parse_element_from_value(type, entity_data[key])]
|
23
25
|
else
|
24
26
|
[key, value]
|
25
27
|
end
|
26
|
-
}
|
28
|
+
}
|
27
29
|
|
28
30
|
[hash]
|
29
31
|
end
|
30
32
|
|
31
33
|
def parse_element_from_value(type, value)
|
32
34
|
return if value.nil?
|
35
|
+
|
33
36
|
if %i[integer boolean timestamp].include?(type) && !value.is_a?(String)
|
34
37
|
value
|
35
38
|
elsif type.instance_of?(Symbol)
|
36
39
|
parse_string(type, value)
|
37
40
|
elsif type.instance_of?(Array)
|
38
41
|
raise DeserializationError, "Expected array for #{type}" unless value.respond_to?(:map)
|
42
|
+
|
39
43
|
value.map {|element|
|
40
44
|
type.first.from_json(element)
|
41
45
|
}
|
@@ -45,10 +49,9 @@ module DiasporaFederation
|
|
45
49
|
end
|
46
50
|
|
47
51
|
def from_json_sanity_validation(json_hash)
|
48
|
-
missing = %w[entity_type entity_data].
|
49
|
-
prop if json_hash[prop].nil?
|
50
|
-
}.compact.join(", ")
|
52
|
+
missing = %w[entity_type entity_data].select {|prop| json_hash[prop].nil? }.join(", ")
|
51
53
|
raise DeserializationError, "Required properties are missing in JSON object: #{missing}" unless missing.empty?
|
54
|
+
|
52
55
|
assert_parsability_of(json_hash["entity_type"])
|
53
56
|
end
|
54
57
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module DiasporaFederation
|
2
4
|
module Parsers
|
3
5
|
# This is a parser of JSON serialized object, that is normally used for parsing data of relayables.
|
@@ -18,6 +20,7 @@ module DiasporaFederation
|
|
18
20
|
def from_json_sanity_validation(json_hash)
|
19
21
|
super
|
20
22
|
return unless json_hash["property_order"].nil?
|
23
|
+
|
21
24
|
raise DeserializationError, "Required property is missing in JSON object: property_order"
|
22
25
|
end
|
23
26
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module DiasporaFederation
|
2
4
|
module Parsers
|
3
5
|
# This is a parser of XML serialized object.
|
@@ -12,23 +14,33 @@ module DiasporaFederation
|
|
12
14
|
def parse(root_node)
|
13
15
|
from_xml_sanity_validation(root_node)
|
14
16
|
|
15
|
-
hash = root_node.element_children.uniq(&:name).
|
16
|
-
|
17
|
-
property = entity_type.find_property_for_xml_name(xml_name)
|
17
|
+
hash = root_node.element_children.uniq(&:name).to_h {|child|
|
18
|
+
property, type = find_property_for(child.name)
|
18
19
|
if property
|
19
|
-
|
20
|
-
value = parse_element_from_node(xml_name, type, root_node)
|
20
|
+
value = parse_element_from_node(child.name, type, root_node)
|
21
21
|
[property, value]
|
22
22
|
else
|
23
|
-
[
|
23
|
+
[child.name, child.text]
|
24
24
|
end
|
25
|
-
}
|
25
|
+
}
|
26
26
|
|
27
27
|
[hash]
|
28
28
|
end
|
29
29
|
|
30
30
|
private
|
31
31
|
|
32
|
+
def find_property_for(xml_name)
|
33
|
+
class_properties.find {|name, type|
|
34
|
+
if type.instance_of?(Symbol)
|
35
|
+
name.to_s == xml_name
|
36
|
+
elsif type.instance_of?(Array)
|
37
|
+
type.first.entity_name == xml_name
|
38
|
+
elsif type.ancestors.include?(Entity)
|
39
|
+
type.entity_name == xml_name
|
40
|
+
end
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
32
44
|
# @param [String] name property name to parse
|
33
45
|
# @param [Class, Symbol] type target type to parse
|
34
46
|
# @param [Nokogiri::XML::Element] root_node XML node to parse
|
@@ -51,7 +63,6 @@ module DiasporaFederation
|
|
51
63
|
# @return [String] data
|
52
64
|
def parse_string_from_node(name, type, root_node)
|
53
65
|
node = root_node.xpath(name.to_s)
|
54
|
-
node = root_node.xpath(xml_names[name].to_s) if node.empty?
|
55
66
|
parse_string(type, node.first.text) if node.any?
|
56
67
|
end
|
57
68
|
|
@@ -77,6 +88,7 @@ module DiasporaFederation
|
|
77
88
|
|
78
89
|
def from_xml_sanity_validation(root_node)
|
79
90
|
raise ArgumentError, "only Nokogiri::XML::Element allowed" unless root_node.instance_of?(Nokogiri::XML::Element)
|
91
|
+
|
80
92
|
assert_parsability_of(root_node.name)
|
81
93
|
end
|
82
94
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module DiasporaFederation
|
2
4
|
# Provides a simple DSL for specifying {Entity} properties during class
|
3
5
|
# definition.
|
@@ -6,7 +8,6 @@ module DiasporaFederation
|
|
6
8
|
# property :prop
|
7
9
|
# property :optional, default: false
|
8
10
|
# property :dynamic_default, default: -> { Time.now }
|
9
|
-
# property :another_prop, xml_name: :another_name
|
10
11
|
# property :original_prop, alias: :alias_prop
|
11
12
|
# entity :nested, NestedEntity
|
12
13
|
# entity :multiple, [OtherEntity]
|
@@ -22,7 +23,6 @@ module DiasporaFederation
|
|
22
23
|
# @param [Hash] opts further options
|
23
24
|
# @option opts [Object, #call] :default a default value, making the
|
24
25
|
# property optional
|
25
|
-
# @option opts [Symbol] :xml_name another name used for xml generation
|
26
26
|
def property(name, type, opts={})
|
27
27
|
raise InvalidType unless property_type_valid?(type)
|
28
28
|
|
@@ -57,67 +57,34 @@ module DiasporaFederation
|
|
57
57
|
# resolved on each call
|
58
58
|
# @return [Hash] default values
|
59
59
|
def default_values
|
60
|
-
optional_props.
|
61
|
-
|
62
|
-
}
|
60
|
+
optional_props.to_h {|name| [name, nil] }.merge(default_props).transform_values {|prop|
|
61
|
+
prop.respond_to?(:call) ? prop.call : prop
|
62
|
+
}
|
63
63
|
end
|
64
64
|
|
65
65
|
# @param [Hash] data entity data
|
66
66
|
# @return [Hash] hash with resolved aliases
|
67
67
|
def resolv_aliases(data)
|
68
|
-
data.
|
68
|
+
data.to_h {|name, value|
|
69
69
|
if class_prop_aliases.has_key? name
|
70
70
|
prop_name = class_prop_aliases[name]
|
71
71
|
raise InvalidData, "only use '#{name}' OR '#{prop_name}'" if data.has_key? prop_name
|
72
|
+
|
72
73
|
[prop_name, value]
|
73
74
|
else
|
74
75
|
[name, value]
|
75
76
|
end
|
76
|
-
}
|
77
|
-
end
|
78
|
-
|
79
|
-
# @return [Symbol] alias for the xml-generation/parsing
|
80
|
-
# @deprecated
|
81
|
-
def xml_names
|
82
|
-
@xml_names ||= {}
|
83
|
-
end
|
84
|
-
|
85
|
-
# Finds a property by +xml_name+ or +name+
|
86
|
-
# @param [String] xml_name name of the property from the received xml
|
87
|
-
# @return [Hash] the property data
|
88
|
-
def find_property_for_xml_name(xml_name)
|
89
|
-
class_props.keys.find {|name| name.to_s == xml_name || xml_names[name].to_s == xml_name }
|
77
|
+
}
|
90
78
|
end
|
91
79
|
|
92
80
|
private
|
93
81
|
|
94
|
-
# @deprecated
|
95
|
-
def determine_xml_name(name, type, opts={})
|
96
|
-
if !type.instance_of?(Symbol) && opts.has_key?(:xml_name)
|
97
|
-
raise ArgumentError, "xml_name is not supported for nested entities"
|
98
|
-
end
|
99
|
-
|
100
|
-
if type.instance_of?(Symbol)
|
101
|
-
if opts.has_key? :xml_name
|
102
|
-
raise InvalidName, "invalid xml_name" unless name_valid?(opts[:xml_name])
|
103
|
-
opts[:xml_name]
|
104
|
-
else
|
105
|
-
name
|
106
|
-
end
|
107
|
-
elsif type.instance_of?(Array)
|
108
|
-
type.first.entity_name.to_sym
|
109
|
-
elsif type.ancestors.include?(Entity)
|
110
|
-
type.entity_name.to_sym
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
82
|
def define_property(name, type, opts={})
|
115
83
|
raise InvalidName unless name_valid?(name)
|
116
84
|
|
117
85
|
class_props[name] = type
|
118
86
|
optional_props << name if opts[:optional]
|
119
87
|
default_props[name] = opts[:default] if opts.has_key? :default
|
120
|
-
xml_names[name] = determine_xml_name(name, type, opts)
|
121
88
|
|
122
89
|
instance_eval { attr_reader name }
|
123
90
|
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module DiasporaFederation
|
2
4
|
module Salmon
|
3
5
|
# Class for AES encryption and decryption
|
4
6
|
class AES
|
5
7
|
# OpenSSL aes cipher definition
|
6
|
-
CIPHER = "AES-256-CBC"
|
8
|
+
CIPHER = "AES-256-CBC"
|
7
9
|
|
8
10
|
# Generates a random AES key and initialization vector
|
9
11
|
# @return [Hash] { key: "...", iv: "..." }
|
@@ -19,7 +21,7 @@ module DiasporaFederation
|
|
19
21
|
# @param [String] iv AES initialization vector
|
20
22
|
# @return [String] base64 encoded ciphertext
|
21
23
|
# @raise [ArgumentError] if any of the arguments is missing or not the correct type
|
22
|
-
def self.encrypt(data, key, iv) # rubocop:disable Naming/
|
24
|
+
def self.encrypt(data, key, iv) # rubocop:disable Naming/MethodParameterName
|
23
25
|
raise ArgumentError unless data.instance_of?(String) &&
|
24
26
|
key.instance_of?(String) &&
|
25
27
|
iv.instance_of?(String)
|
@@ -41,7 +43,7 @@ module DiasporaFederation
|
|
41
43
|
# @param [String] iv AES initialization vector
|
42
44
|
# @return [String] decrypted plain message
|
43
45
|
# @raise [ArgumentError] if any of the arguments is missing or not the correct type
|
44
|
-
def self.decrypt(ciphertext, key, iv) # rubocop:disable Naming/
|
46
|
+
def self.decrypt(ciphertext, key, iv) # rubocop:disable Naming/MethodParameterName
|
45
47
|
raise ArgumentError unless ciphertext.instance_of?(String) &&
|
46
48
|
key.instance_of?(String) &&
|
47
49
|
iv.instance_of?(String)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module DiasporaFederation
|
2
4
|
module Salmon
|
3
5
|
# This is a simple crypt-wrapper for {MagicEnvelope}.
|
@@ -36,7 +38,7 @@ module DiasporaFederation
|
|
36
38
|
key = AES.generate_key_and_iv
|
37
39
|
encrypted_env = AES.encrypt(magic_env.to_xml, key[:key], key[:iv])
|
38
40
|
|
39
|
-
encoded_key = key.
|
41
|
+
encoded_key = key.transform_values {|v| Base64.strict_encode64(v) }
|
40
42
|
encrypted_key = Base64.strict_encode64(pubkey.public_encrypt(JSON.generate(encoded_key)))
|
41
43
|
|
42
44
|
JSON.generate(aes_key: encrypted_key, encrypted_magic_envelope: encrypted_env)
|
@@ -51,7 +53,7 @@ module DiasporaFederation
|
|
51
53
|
encrypted_json = JSON.parse(encrypted_env)
|
52
54
|
|
53
55
|
encoded_key = JSON.parse(privkey.private_decrypt(Base64.decode64(encrypted_json["aes_key"])))
|
54
|
-
key = encoded_key.
|
56
|
+
key = encoded_key.transform_values {|v| Base64.decode64(v) }
|
55
57
|
|
56
58
|
xml = AES.decrypt(encrypted_json["encrypted_magic_envelope"], key["key"], key["iv"])
|
57
59
|
Nokogiri::XML(xml).root
|
@@ -1,25 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module DiasporaFederation
|
2
4
|
module Salmon
|
3
|
-
# Raised, if the element containing the Magic Envelope is missing from the XML
|
4
|
-
# @deprecated
|
5
|
-
class MissingMagicEnvelope < RuntimeError
|
6
|
-
end
|
7
|
-
|
8
|
-
# Raised, if the element containing the author is empty.
|
9
|
-
# @deprecated
|
10
|
-
class MissingAuthor < RuntimeError
|
11
|
-
end
|
12
|
-
|
13
|
-
# Raised, if the element containing the header is missing from the XML
|
14
|
-
# @deprecated
|
15
|
-
class MissingHeader < RuntimeError
|
16
|
-
end
|
17
|
-
|
18
|
-
# Raised, if the decrypted header has an unexpected XML structure
|
19
|
-
# @deprecated
|
20
|
-
class InvalidHeader < RuntimeError
|
21
|
-
end
|
22
|
-
|
23
5
|
# Raised, if failed to fetch the public key of the sender of the received message
|
24
6
|
class SenderKeyNotFound < RuntimeError
|
25
7
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module DiasporaFederation
|
2
4
|
module Salmon
|
3
5
|
# Represents a Magic Envelope for diaspora* federation messages
|
@@ -24,19 +26,19 @@ module DiasporaFederation
|
|
24
26
|
include Logging
|
25
27
|
|
26
28
|
# Encoding used for the payload data
|
27
|
-
ENCODING = "base64url"
|
29
|
+
ENCODING = "base64url"
|
28
30
|
|
29
31
|
# Algorithm used for signing the payload data
|
30
|
-
ALGORITHM = "RSA-SHA256"
|
32
|
+
ALGORITHM = "RSA-SHA256"
|
31
33
|
|
32
34
|
# Mime type describing the payload data
|
33
|
-
DATA_TYPE = "application/xml"
|
35
|
+
DATA_TYPE = "application/xml"
|
34
36
|
|
35
37
|
# Digest instance used for signing
|
36
|
-
DIGEST = OpenSSL::Digest
|
38
|
+
DIGEST = OpenSSL::Digest.new("SHA256")
|
37
39
|
|
38
40
|
# XML namespace url
|
39
|
-
XMLNS = "http://salmon-protocol.org/ns/magic-env"
|
41
|
+
XMLNS = "http://salmon-protocol.org/ns/magic-env"
|
40
42
|
|
41
43
|
# The payload entity of the magic envelope
|
42
44
|
# @return [Entity] payload entity
|
@@ -112,7 +114,8 @@ module DiasporaFederation
|
|
112
114
|
|
113
115
|
logger.debug "unenvelop message from #{sender}:\n#{data}"
|
114
116
|
|
115
|
-
|
117
|
+
xml = Nokogiri::XML(data).root
|
118
|
+
new(Entity.entity_class(xml.name).from_xml(xml), sender)
|
116
119
|
end
|
117
120
|
|
118
121
|
private
|
@@ -134,10 +137,8 @@ module DiasporaFederation
|
|
134
137
|
# @yield [xml] Invokes the block with the
|
135
138
|
# {http://www.rubydoc.info/gems/nokogiri/Nokogiri/XML/Builder Nokogiri::XML::Builder}
|
136
139
|
# @return [Nokogiri::XML::Element] XML root node
|
137
|
-
def build_xml
|
138
|
-
Nokogiri::XML::Builder.new(encoding: "UTF-8")
|
139
|
-
yield xml
|
140
|
-
}.doc
|
140
|
+
def build_xml(&block)
|
141
|
+
Nokogiri::XML::Builder.new(encoding: "UTF-8", &block).doc
|
141
142
|
end
|
142
143
|
|
143
144
|
# Creates the signature for all fields according to specification
|
@@ -153,6 +154,7 @@ module DiasporaFederation
|
|
153
154
|
# @raise [InvalidEnvelope] if the envelope XML structure is malformed
|
154
155
|
private_class_method def self.validate_envelope(env)
|
155
156
|
raise InvalidEnvelope unless env.instance_of?(Nokogiri::XML::Element) && env.name == "env"
|
157
|
+
|
156
158
|
validate_element(env, "me:data")
|
157
159
|
validate_element(env, "me:sig")
|
158
160
|
end
|
@@ -188,6 +190,7 @@ module DiasporaFederation
|
|
188
190
|
private_class_method def self.sender(env)
|
189
191
|
key_id = env.at_xpath("me:sig")["key_id"]
|
190
192
|
raise InvalidEnvelope, "no key_id" unless key_id # TODO: move to `envelope_valid?`
|
193
|
+
|
191
194
|
Base64.urlsafe_decode64(key_id)
|
192
195
|
end
|
193
196
|
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module DiasporaFederation
|
2
4
|
# This module contains a diaspora*-specific implementation of parts of the
|
3
5
|
# {http://www.salmon-protocol.org/ Salmon Protocol}.
|
4
6
|
module Salmon
|
5
7
|
# XML namespace url
|
6
|
-
XMLNS = "https://joindiaspora.com/protocol"
|
8
|
+
XMLNS = "https://joindiaspora.com/protocol"
|
7
9
|
end
|
8
10
|
end
|
9
11
|
|
@@ -11,8 +13,5 @@ require "base64"
|
|
11
13
|
|
12
14
|
require "diaspora_federation/salmon/aes"
|
13
15
|
require "diaspora_federation/salmon/exceptions"
|
14
|
-
require "diaspora_federation/salmon/xml_payload"
|
15
16
|
require "diaspora_federation/salmon/magic_envelope"
|
16
17
|
require "diaspora_federation/salmon/encrypted_magic_envelope"
|
17
|
-
require "diaspora_federation/salmon/slap"
|
18
|
-
require "diaspora_federation/salmon/encrypted_slap"
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module DiasporaFederation
|
2
4
|
module Validators
|
3
5
|
# Abstract validator which only validates optional fields when they are not nil.
|
@@ -14,6 +16,7 @@ module DiasporaFederation
|
|
14
16
|
|
15
17
|
def optional_props
|
16
18
|
return [] unless @obj.class.respond_to?(:optional_props)
|
19
|
+
|
17
20
|
@obj.class.optional_props
|
18
21
|
end
|
19
22
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "date"
|
2
4
|
|
3
5
|
module Validation
|
@@ -20,7 +22,7 @@ module Validation
|
|
20
22
|
return true if value.nil? || (value.is_a?(String) && value.empty?)
|
21
23
|
return true if value.is_a? Date
|
22
24
|
|
23
|
-
if value
|
25
|
+
if value.is_a?(String) && value.match?(/[0-9]{4}-[0-9]{2}-[0-9]{2}/)
|
24
26
|
date_field = value.split("-").map(&:to_i)
|
25
27
|
return Date.valid_civil?(date_field[0], date_field[1], date_field[2])
|
26
28
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Validation
|
2
4
|
module Rule
|
3
5
|
# Boolean validation rule
|
@@ -17,14 +19,13 @@ module Validation
|
|
17
19
|
def valid_value?(value)
|
18
20
|
return false if value.nil?
|
19
21
|
|
20
|
-
|
22
|
+
case value
|
23
|
+
when String
|
21
24
|
true if value =~ /\A(true|false|t|f|yes|no|y|n|1|0)\z/i
|
22
|
-
|
25
|
+
when Integer
|
23
26
|
true if [1, 0].include?(value)
|
24
|
-
elsif [true, false].include?(value)
|
25
|
-
true
|
26
27
|
else
|
27
|
-
false
|
28
|
+
[true, false].include?(value)
|
28
29
|
end
|
29
30
|
end
|
30
31
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Validation
|
2
4
|
module Rule
|
3
5
|
# diaspora* ID validation rule
|
@@ -22,7 +24,7 @@ module Validation
|
|
22
24
|
end
|
23
25
|
|
24
26
|
# The Regex for validating a full diaspora* ID
|
25
|
-
DIASPORA_ID = /\A#{DIASPORA_ID_REGEX}\z/u
|
27
|
+
DIASPORA_ID = /\A#{DIASPORA_ID_REGEX}\z/u.freeze
|
26
28
|
|
27
29
|
# The error key for this rule
|
28
30
|
# @return [Symbol] error key
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Validation
|
2
4
|
module Rule
|
3
5
|
# Rule for validating the number of diaspora* IDs in a string.
|
@@ -31,6 +33,7 @@ module Validation
|
|
31
33
|
ids = value.split(";")
|
32
34
|
return false if params.include?(:maximum) && ids.count > params[:maximum]
|
33
35
|
return false if params.include?(:minimum) && ids.count < params[:minimum]
|
36
|
+
|
34
37
|
ids.each do |id|
|
35
38
|
return false if DiasporaId::DIASPORA_ID.match(id).nil?
|
36
39
|
end
|