diaspora_federation 0.2.8 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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 +14 -27
- 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
|