diaspora_federation 0.1.9 → 0.2.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 +34 -0
- data/lib/diaspora_federation/discovery/discovery.rb +2 -2
- data/lib/diaspora_federation/discovery/h_card.rb +2 -10
- data/lib/diaspora_federation/discovery/host_meta.rb +1 -1
- data/lib/diaspora_federation/discovery/web_finger.rb +47 -87
- data/lib/diaspora_federation/discovery/xrd_document.rb +20 -7
- data/lib/diaspora_federation/entities/account_migration.rb +74 -0
- data/lib/diaspora_federation/entities/comment.rb +0 -4
- data/lib/diaspora_federation/entities/event_participation.rb +0 -8
- data/lib/diaspora_federation/entities/like.rb +6 -10
- data/lib/diaspora_federation/entities/message.rb +14 -49
- data/lib/diaspora_federation/entities/participation.rb +23 -13
- data/lib/diaspora_federation/entities/poll_participation.rb +0 -4
- data/lib/diaspora_federation/entities/profile.rb +5 -0
- data/lib/diaspora_federation/entities/related_entity.rb +17 -0
- data/lib/diaspora_federation/entities/relayable.rb +82 -113
- data/lib/diaspora_federation/entities/relayable_retraction.rb +4 -43
- data/lib/diaspora_federation/entities/request.rb +4 -12
- data/lib/diaspora_federation/entities/reshare.rb +11 -7
- data/lib/diaspora_federation/entities/retraction.rb +4 -5
- data/lib/diaspora_federation/entities/signable.rb +54 -0
- data/lib/diaspora_federation/entities/signed_retraction.rb +4 -44
- data/lib/diaspora_federation/entities.rb +2 -0
- data/lib/diaspora_federation/entity.rb +74 -96
- data/lib/diaspora_federation/federation/fetcher.rb +1 -1
- data/lib/diaspora_federation/federation/receiver.rb +1 -1
- data/lib/diaspora_federation/federation/sender/hydra_wrapper.rb +37 -12
- data/lib/diaspora_federation/federation/sender.rb +2 -2
- data/lib/diaspora_federation/parsers/base_parser.rb +61 -0
- data/lib/diaspora_federation/parsers/json_parser.rb +60 -0
- data/lib/diaspora_federation/parsers/relayable_json_parser.rb +25 -0
- data/lib/diaspora_federation/parsers/relayable_xml_parser.rb +22 -0
- data/lib/diaspora_federation/parsers/xml_parser.rb +84 -0
- data/lib/diaspora_federation/parsers.rb +13 -0
- data/lib/diaspora_federation/properties_dsl.rb +1 -1
- data/lib/diaspora_federation/salmon/encrypted_magic_envelope.rb +1 -1
- data/lib/diaspora_federation/salmon/encrypted_slap.rb +2 -99
- data/lib/diaspora_federation/salmon/magic_envelope.rb +3 -19
- data/lib/diaspora_federation/salmon/slap.rb +1 -42
- data/lib/diaspora_federation/salmon/xml_payload.rb +0 -19
- data/lib/diaspora_federation/schemas/federation_entities.json +379 -0
- data/lib/diaspora_federation/validators/account_deletion_validator.rb +1 -1
- data/lib/diaspora_federation/validators/account_migration_validator.rb +12 -0
- data/lib/diaspora_federation/validators/contact_validator.rb +2 -2
- data/lib/diaspora_federation/validators/conversation_validator.rb +1 -1
- data/lib/diaspora_federation/validators/event_validator.rb +1 -1
- data/lib/diaspora_federation/validators/h_card_validator.rb +2 -5
- data/lib/diaspora_federation/validators/message_validator.rb +1 -1
- data/lib/diaspora_federation/validators/participation_validator.rb +1 -1
- data/lib/diaspora_federation/validators/person_validator.rb +2 -2
- data/lib/diaspora_federation/validators/photo_validator.rb +1 -1
- data/lib/diaspora_federation/validators/profile_validator.rb +1 -1
- data/lib/diaspora_federation/validators/related_entity_validator.rb +1 -1
- data/lib/diaspora_federation/validators/relayable_validator.rb +1 -1
- data/lib/diaspora_federation/validators/reshare_validator.rb +2 -2
- data/lib/diaspora_federation/validators/retraction_validator.rb +1 -1
- data/lib/diaspora_federation/validators/rules/boolean.rb +2 -2
- data/lib/diaspora_federation/validators/status_message_validator.rb +1 -1
- data/lib/diaspora_federation/validators/web_finger_validator.rb +5 -6
- data/lib/diaspora_federation/validators.rb +1 -5
- data/lib/diaspora_federation/version.rb +1 -1
- data/lib/diaspora_federation.rb +6 -2
- metadata +14 -11
- data/lib/diaspora_federation/validators/relayable_retraction_validator.rb +0 -15
- data/lib/diaspora_federation/validators/request_validator.rb +0 -12
- data/lib/diaspora_federation/validators/signed_retraction_validator.rb +0 -15
- data/lib/tasks/build.rake +0 -14
- data/lib/tasks/diaspora_federation_tasks.rake +0 -4
- data/lib/tasks/rails4.rake +0 -15
- data/lib/tasks/tests.rake +0 -18
@@ -48,32 +48,12 @@ module DiasporaFederation
|
|
48
48
|
# Finally, before decrypting the magic envelope payload, the signature should
|
49
49
|
# first be verified.
|
50
50
|
#
|
51
|
-
# @example Generating an encrypted Salmon Slap
|
52
|
-
# author_id = "author@pod.example.tld"
|
53
|
-
# author_privkey = however_you_retrieve_the_authors_private_key(author_id)
|
54
|
-
# recipient_pubkey = however_you_retrieve_the_recipients_public_key()
|
55
|
-
# entity = YourEntity.new(attr: "val")
|
56
|
-
#
|
57
|
-
# slap_xml = EncryptedSlap.prepare(author_id, author_privkey, entity).generate_xml(recipient_pubkey)
|
58
|
-
#
|
59
51
|
# @example Parsing a Salmon Slap
|
60
52
|
# recipient_privkey = however_you_retrieve_the_recipients_private_key()
|
61
53
|
# entity = EncryptedSlap.from_xml(slap_xml, recipient_privkey).payload
|
62
54
|
#
|
63
55
|
# @deprecated
|
64
56
|
class EncryptedSlap < Slap
|
65
|
-
# the author of the slap
|
66
|
-
# @param [String] value the author diaspora* ID
|
67
|
-
attr_writer :author_id
|
68
|
-
|
69
|
-
# the key and iv if it is an encrypted slap
|
70
|
-
# @param [Hash] value hash containing the key and iv
|
71
|
-
attr_writer :cipher_params
|
72
|
-
|
73
|
-
# the prepared encrypted magic envelope xml
|
74
|
-
# @param [Nokogiri::XML::Element] value magic envelope xml
|
75
|
-
attr_writer :magic_envelope_xml
|
76
|
-
|
77
57
|
# Creates a {MagicEnvelope} instance from the data within the given XML string
|
78
58
|
# containing an encrypted payload.
|
79
59
|
#
|
@@ -87,7 +67,7 @@ module DiasporaFederation
|
|
87
67
|
# @raise [MissingMagicEnvelope] if the +me:env+ element is missing in the XML
|
88
68
|
def self.from_xml(slap_xml, privkey)
|
89
69
|
raise ArgumentError unless slap_xml.instance_of?(String) && privkey.instance_of?(OpenSSL::PKey::RSA)
|
90
|
-
doc = Nokogiri::XML
|
70
|
+
doc = Nokogiri::XML(slap_xml)
|
91
71
|
|
92
72
|
header_elem = doc.at_xpath("d:diaspora/d:encrypted_header", Slap::NS)
|
93
73
|
raise MissingHeader if header_elem.nil?
|
@@ -98,44 +78,6 @@ module DiasporaFederation
|
|
98
78
|
MagicEnvelope.unenvelop(magic_env_from_doc(doc), sender, cipher_params)
|
99
79
|
end
|
100
80
|
|
101
|
-
# Creates an encrypted Salmon Slap.
|
102
|
-
#
|
103
|
-
# @param [String] author_id diaspora* ID of the author
|
104
|
-
# @param [OpenSSL::PKey::RSA] privkey sender private key for signing the magic envelope
|
105
|
-
# @param [Entity] entity payload
|
106
|
-
# @return [EncryptedSlap] encrypted Slap instance
|
107
|
-
# @raise [ArgumentError] if any of the arguments is of the wrong type
|
108
|
-
def self.prepare(author_id, privkey, entity)
|
109
|
-
raise ArgumentError unless author_id.instance_of?(String) &&
|
110
|
-
privkey.instance_of?(OpenSSL::PKey::RSA) &&
|
111
|
-
entity.is_a?(Entity)
|
112
|
-
|
113
|
-
EncryptedSlap.new.tap do |slap|
|
114
|
-
slap.author_id = author_id
|
115
|
-
|
116
|
-
magic_envelope = MagicEnvelope.new(entity)
|
117
|
-
slap.cipher_params = magic_envelope.encrypt!
|
118
|
-
slap.magic_envelope_xml = magic_envelope.envelop(privkey)
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
# Creates an encrypted Salmon Slap XML string.
|
123
|
-
#
|
124
|
-
# @param [OpenSSL::PKey::RSA] pubkey recipient public key for encrypting the AES key
|
125
|
-
# @return [String] Salmon XML string
|
126
|
-
# @raise [ArgumentError] if any of the arguments is of the wrong type
|
127
|
-
def generate_xml(pubkey)
|
128
|
-
raise ArgumentError unless pubkey.instance_of?(OpenSSL::PKey::RSA)
|
129
|
-
|
130
|
-
Slap.build_xml do |xml|
|
131
|
-
xml.encrypted_header(encrypted_header(@author_id, @cipher_params, pubkey))
|
132
|
-
|
133
|
-
xml.parent << @magic_envelope_xml
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
private
|
138
|
-
|
139
81
|
# Decrypts and reads the data from the encrypted XML header
|
140
82
|
# @param [String] data base64 encoded, encrypted header data
|
141
83
|
# @param [OpenSSL::PKey::RSA] privkey private key for decryption
|
@@ -160,46 +102,7 @@ module DiasporaFederation
|
|
160
102
|
key = JSON.parse(privkey.private_decrypt(Base64.decode64(cipher_header["aes_key"])))
|
161
103
|
|
162
104
|
xml = AES.decrypt(cipher_header["ciphertext"], Base64.decode64(key["key"]), Base64.decode64(key["iv"]))
|
163
|
-
Nokogiri::XML
|
164
|
-
end
|
165
|
-
|
166
|
-
# Encrypt the header xml with an AES cipher and encrypt the cipher params
|
167
|
-
# with the recipients public_key.
|
168
|
-
# @param [String] author_id diaspora_handle
|
169
|
-
# @param [Hash] envelope_key envelope cipher params
|
170
|
-
# @param [OpenSSL::PKey::RSA] pubkey recipient public_key
|
171
|
-
# @return [String] encrypted base64 encoded header
|
172
|
-
def encrypted_header(author_id, envelope_key, pubkey)
|
173
|
-
data = header_xml(author_id, strict_base64_encode(envelope_key))
|
174
|
-
header_key = AES.generate_key_and_iv
|
175
|
-
ciphertext = AES.encrypt(data, header_key[:key], header_key[:iv])
|
176
|
-
|
177
|
-
json_key = JSON.generate(strict_base64_encode(header_key))
|
178
|
-
encrypted_key = Base64.strict_encode64(pubkey.public_encrypt(json_key))
|
179
|
-
|
180
|
-
json_header = JSON.generate(aes_key: encrypted_key, ciphertext: ciphertext)
|
181
|
-
|
182
|
-
Base64.strict_encode64(json_header)
|
183
|
-
end
|
184
|
-
|
185
|
-
# Generate the header xml string, including the author, aes_key and iv
|
186
|
-
# @param [String] author_id diaspora_handle of the author
|
187
|
-
# @param [Hash] envelope_key { key: "...", iv: "..." } (values in base64)
|
188
|
-
# @return [String] header XML string
|
189
|
-
def header_xml(author_id, envelope_key)
|
190
|
-
@header_xml ||= Nokogiri::XML::Builder.new(encoding: "UTF-8") {|xml|
|
191
|
-
xml.decrypted_header {
|
192
|
-
xml.iv(envelope_key[:iv])
|
193
|
-
xml.aes_key(envelope_key[:key])
|
194
|
-
xml.author_id(author_id)
|
195
|
-
}
|
196
|
-
}.to_xml.strip
|
197
|
-
end
|
198
|
-
|
199
|
-
# @param [Hash] hash { key: "...", iv: "..." }
|
200
|
-
# @return [Hash] encoded hash: { key: "...", iv: "..." }
|
201
|
-
def strict_base64_encode(hash)
|
202
|
-
hash.map {|k, v| [k, Base64.strict_encode64(v)] }.to_h
|
105
|
+
Nokogiri::XML(xml).root
|
203
106
|
end
|
204
107
|
end
|
205
108
|
end
|
@@ -76,22 +76,6 @@ module DiasporaFederation
|
|
76
76
|
}
|
77
77
|
end
|
78
78
|
|
79
|
-
# Encrypts the payload with a new, random AES cipher and returns the cipher
|
80
|
-
# params that were used.
|
81
|
-
#
|
82
|
-
# This must happen after the MagicEnvelope instance was created and before
|
83
|
-
# {MagicEnvelope#envelop} is called.
|
84
|
-
#
|
85
|
-
# @see AES#generate_key_and_iv
|
86
|
-
# @see AES#encrypt
|
87
|
-
#
|
88
|
-
# @return [Hash] AES key and iv. E.g.: { key: "...", iv: "..." }
|
89
|
-
def encrypt!
|
90
|
-
AES.generate_key_and_iv.tap do |key|
|
91
|
-
@payload_data = AES.encrypt(payload_data, key[:key], key[:iv])
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
79
|
# Extracts the entity encoded in the magic envelope data, if the signature
|
96
80
|
# is valid. If +cipher_params+ is given, also attempts to decrypt the payload first.
|
97
81
|
#
|
@@ -128,7 +112,7 @@ module DiasporaFederation
|
|
128
112
|
|
129
113
|
logger.debug "unenvelop message from #{sender}:\n#{data}"
|
130
114
|
|
131
|
-
new(XmlPayload.unpack(Nokogiri::XML
|
115
|
+
new(XmlPayload.unpack(Nokogiri::XML(data).root), sender)
|
132
116
|
end
|
133
117
|
|
134
118
|
private
|
@@ -136,7 +120,7 @@ module DiasporaFederation
|
|
136
120
|
# The payload data as string
|
137
121
|
# @return [String] payload data
|
138
122
|
def payload_data
|
139
|
-
@payload_data ||=
|
123
|
+
@payload_data ||= payload.to_xml.to_xml.strip.tap do |data|
|
140
124
|
logger.debug "send payload:\n#{data}"
|
141
125
|
end
|
142
126
|
end
|
@@ -153,7 +137,7 @@ module DiasporaFederation
|
|
153
137
|
def build_xml
|
154
138
|
Nokogiri::XML::Builder.new(encoding: "UTF-8") {|xml|
|
155
139
|
yield xml
|
156
|
-
}.doc
|
140
|
+
}.doc
|
157
141
|
end
|
158
142
|
|
159
143
|
# Creates the signature for all fields according to specification
|
@@ -13,13 +13,6 @@ module DiasporaFederation
|
|
13
13
|
# {magic_envelope}
|
14
14
|
# </diaspora>
|
15
15
|
#
|
16
|
-
# @example Generating a Salmon Slap
|
17
|
-
# author_id = "author@pod.example.tld"
|
18
|
-
# author_privkey = however_you_retrieve_the_authors_private_key(author_id)
|
19
|
-
# entity = YourEntity.new(attr: "val")
|
20
|
-
#
|
21
|
-
# slap_xml = Slap.generate_xml(author_id, author_privkey, entity)
|
22
|
-
#
|
23
16
|
# @example Parsing a Salmon Slap
|
24
17
|
# entity = Slap.from_xml(slap_xml).payload
|
25
18
|
#
|
@@ -40,7 +33,7 @@ module DiasporaFederation
|
|
40
33
|
# @raise [MissingMagicEnvelope] if the +me:env+ element is missing from the XML
|
41
34
|
def self.from_xml(slap_xml)
|
42
35
|
raise ArgumentError unless slap_xml.instance_of?(String)
|
43
|
-
doc = Nokogiri::XML
|
36
|
+
doc = Nokogiri::XML(slap_xml)
|
44
37
|
|
45
38
|
author_elem = doc.at_xpath("d:diaspora/d:header/d:author_id", Slap::NS)
|
46
39
|
raise MissingAuthor if author_elem.nil? || author_elem.content.empty?
|
@@ -49,40 +42,6 @@ module DiasporaFederation
|
|
49
42
|
MagicEnvelope.unenvelop(magic_env_from_doc(doc), sender)
|
50
43
|
end
|
51
44
|
|
52
|
-
# Creates an unencrypted Salmon Slap and returns the XML string.
|
53
|
-
#
|
54
|
-
# @param [String] author_id diaspora* ID of the author
|
55
|
-
# @param [OpenSSL::PKey::RSA] privkey sender private_key for signing the magic envelope
|
56
|
-
# @param [Entity] entity payload
|
57
|
-
# @return [String] Salmon XML string
|
58
|
-
# @raise [ArgumentError] if any of the arguments is not the correct type
|
59
|
-
def self.generate_xml(author_id, privkey, entity)
|
60
|
-
raise ArgumentError unless author_id.instance_of?(String) &&
|
61
|
-
privkey.instance_of?(OpenSSL::PKey::RSA) &&
|
62
|
-
entity.is_a?(Entity)
|
63
|
-
|
64
|
-
build_xml do |xml|
|
65
|
-
xml.header {
|
66
|
-
xml.author_id(author_id)
|
67
|
-
}
|
68
|
-
|
69
|
-
xml.parent << MagicEnvelope.new(entity, author_id).envelop(privkey)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
# Builds the xml for the Salmon Slap.
|
74
|
-
#
|
75
|
-
# @yield [xml] Invokes the block with the
|
76
|
-
# {http://www.rubydoc.info/gems/nokogiri/Nokogiri/XML/Builder Nokogiri::XML::Builder}
|
77
|
-
# @return [String] Slap XML
|
78
|
-
def self.build_xml
|
79
|
-
Nokogiri::XML::Builder.new(encoding: "UTF-8") {|xml|
|
80
|
-
xml.diaspora("xmlns" => Salmon::XMLNS, "xmlns:me" => MagicEnvelope::XMLNS) {
|
81
|
-
yield xml
|
82
|
-
}
|
83
|
-
}.to_xml
|
84
|
-
end
|
85
|
-
|
86
45
|
# Parses the magic envelop from the document.
|
87
46
|
#
|
88
47
|
# @param [Nokogiri::XML::Document] doc Salmon XML Document
|
@@ -13,25 +13,6 @@ module DiasporaFederation
|
|
13
13
|
# (The +post+ element is there for historic reasons...)
|
14
14
|
# @deprecated
|
15
15
|
module XmlPayload
|
16
|
-
# Encapsulates an Entity inside the wrapping xml structure
|
17
|
-
# and returns the XML Object.
|
18
|
-
#
|
19
|
-
# @param [Entity] entity subject
|
20
|
-
# @return [Nokogiri::XML::Element] XML root node
|
21
|
-
# @raise [ArgumentError] if the argument is not an Entity subclass
|
22
|
-
def self.pack(entity)
|
23
|
-
raise ArgumentError, "only instances of DiasporaFederation::Entity allowed" unless entity.is_a?(Entity)
|
24
|
-
|
25
|
-
entity_xml = entity.to_xml
|
26
|
-
doc = entity_xml.document
|
27
|
-
wrap = Nokogiri::XML::Element.new("XML", doc)
|
28
|
-
wrap_post = Nokogiri::XML::Element.new("post", doc)
|
29
|
-
entity_xml.parent = wrap_post
|
30
|
-
wrap << wrap_post
|
31
|
-
|
32
|
-
wrap
|
33
|
-
end
|
34
|
-
|
35
16
|
# Extracts the Entity XML from the wrapping XML structure, parses the entity
|
36
17
|
# XML and returns a new instance of the Entity that was packed inside the
|
37
18
|
# given payload.
|
@@ -0,0 +1,379 @@
|
|
1
|
+
{
|
2
|
+
"$schema": "http://json-schema.org/draft-04/schema#",
|
3
|
+
"id": "https://diaspora.github.io/diaspora_federation/schemas/federation_entities.json",
|
4
|
+
"oneOf": [
|
5
|
+
{"$ref": "#/definitions/comment"},
|
6
|
+
{"$ref": "#/definitions/like"},
|
7
|
+
{"$ref": "#/definitions/participation"},
|
8
|
+
{"$ref": "#/definitions/poll_participation"},
|
9
|
+
{"$ref": "#/definitions/status_message"},
|
10
|
+
{"$ref": "#/definitions/reshare"},
|
11
|
+
{"$ref": "#/definitions/profile"},
|
12
|
+
{"$ref": "#/definitions/location"},
|
13
|
+
{"$ref": "#/definitions/photo"},
|
14
|
+
{"$ref": "#/definitions/poll"},
|
15
|
+
{"$ref": "#/definitions/poll_answer"}
|
16
|
+
],
|
17
|
+
|
18
|
+
"definitions": {
|
19
|
+
"signature": {
|
20
|
+
"oneOf" : [
|
21
|
+
{
|
22
|
+
"type": "string",
|
23
|
+
"minLength": 30
|
24
|
+
},
|
25
|
+
{
|
26
|
+
"type": "string",
|
27
|
+
"maxLength": 0,
|
28
|
+
"description": "Allow empty string when no signature is provided"
|
29
|
+
}
|
30
|
+
]
|
31
|
+
},
|
32
|
+
|
33
|
+
"guid": {
|
34
|
+
"type": "string",
|
35
|
+
"minLength": 16,
|
36
|
+
"maxLength": 255
|
37
|
+
},
|
38
|
+
|
39
|
+
"relayable": {
|
40
|
+
"type": "object",
|
41
|
+
"description": "please don't use this object unless you're defining a new child relayable schema",
|
42
|
+
"properties": {
|
43
|
+
"entity_data": {
|
44
|
+
"type": "object",
|
45
|
+
"properties": {
|
46
|
+
"author": { "type": "string" },
|
47
|
+
"guid": { "$ref": "#/definitions/guid" },
|
48
|
+
"parent_guid": { "$ref": "#/definitions/guid" },
|
49
|
+
"author_signature": { "$ref": "#/definitions/signature" }
|
50
|
+
},
|
51
|
+
"required": [
|
52
|
+
"author", "guid", "parent_guid"
|
53
|
+
]
|
54
|
+
},
|
55
|
+
"property_order": {
|
56
|
+
"type": "array",
|
57
|
+
"items": { "type": "string" }
|
58
|
+
}
|
59
|
+
},
|
60
|
+
"required": [
|
61
|
+
"entity_data", "entity_type", "property_order"
|
62
|
+
]
|
63
|
+
},
|
64
|
+
|
65
|
+
"comment": {
|
66
|
+
"allOf": [
|
67
|
+
{"$ref": "#/definitions/relayable"},
|
68
|
+
{
|
69
|
+
"type": "object",
|
70
|
+
"properties": {
|
71
|
+
"entity_data": {
|
72
|
+
"type": "object",
|
73
|
+
"properties": {
|
74
|
+
"text": { "type": "string" },
|
75
|
+
"created_at": { "type": "string" }
|
76
|
+
},
|
77
|
+
"required": ["text"]
|
78
|
+
},
|
79
|
+
"entity_type": {
|
80
|
+
"type": "string",
|
81
|
+
"pattern": "^comment$"
|
82
|
+
}
|
83
|
+
}
|
84
|
+
}
|
85
|
+
]
|
86
|
+
},
|
87
|
+
|
88
|
+
"like": {
|
89
|
+
"allOf": [
|
90
|
+
{"$ref": "#/definitions/relayable"},
|
91
|
+
{
|
92
|
+
"type": "object",
|
93
|
+
"properties": {
|
94
|
+
"entity_type": {
|
95
|
+
"type": "string",
|
96
|
+
"pattern": "^like$"
|
97
|
+
},
|
98
|
+
"entity_data": {
|
99
|
+
"type": "object",
|
100
|
+
"properties": {
|
101
|
+
"positive": { "type": "boolean" },
|
102
|
+
"parent_type": { "enum": ["Post", "Comment"] }
|
103
|
+
},
|
104
|
+
"required": ["positive"]
|
105
|
+
}
|
106
|
+
}
|
107
|
+
}
|
108
|
+
]
|
109
|
+
},
|
110
|
+
|
111
|
+
"participation": {
|
112
|
+
"type": "object",
|
113
|
+
"properties": {
|
114
|
+
"entity_type": {
|
115
|
+
"type": "string",
|
116
|
+
"pattern": "^participation$"
|
117
|
+
},
|
118
|
+
"entity_data": {
|
119
|
+
"type": "object",
|
120
|
+
"properties": {
|
121
|
+
"author": { "type": "string" },
|
122
|
+
"guid": { "$ref": "#/definitions/guid" },
|
123
|
+
"parent_guid": { "$ref": "#/definitions/guid" },
|
124
|
+
"parent_type": {"enum": ["Post"]}
|
125
|
+
}
|
126
|
+
}
|
127
|
+
}
|
128
|
+
},
|
129
|
+
|
130
|
+
"poll_participation": {
|
131
|
+
"allOf": [
|
132
|
+
{"$ref": "#/definitions/relayable"},
|
133
|
+
{
|
134
|
+
"type": "object",
|
135
|
+
"properties": {
|
136
|
+
"entity_type": {
|
137
|
+
"type": "string",
|
138
|
+
"pattern": "^poll_participation$"
|
139
|
+
},
|
140
|
+
"entity_data": {
|
141
|
+
"type": "object",
|
142
|
+
"properties": {
|
143
|
+
"poll_answer_guid": { "$ref": "#/definitions/guid" }
|
144
|
+
},
|
145
|
+
"required": ["poll_answer_guid"]
|
146
|
+
}
|
147
|
+
}
|
148
|
+
}
|
149
|
+
]
|
150
|
+
},
|
151
|
+
|
152
|
+
"post": {
|
153
|
+
"type": "object",
|
154
|
+
"description": "please don't use this object unless you're defining a new child post schema",
|
155
|
+
"properties": {
|
156
|
+
"entity_data": {
|
157
|
+
"type": "object",
|
158
|
+
"properties": {
|
159
|
+
"guid": { "$ref": "#/definitions/guid" },
|
160
|
+
"public": { "type": "boolean" },
|
161
|
+
"created_at": { "type": "string" },
|
162
|
+
"provider_display_name" : { "type": "string" }
|
163
|
+
},
|
164
|
+
"required": [
|
165
|
+
"guid", "public", "created_at"
|
166
|
+
]
|
167
|
+
},
|
168
|
+
"required": [
|
169
|
+
"entity_type", "entity_data"
|
170
|
+
]
|
171
|
+
}
|
172
|
+
},
|
173
|
+
|
174
|
+
"status_message": {
|
175
|
+
"allOf": [
|
176
|
+
{"$ref": "#/definitions/post"},
|
177
|
+
{
|
178
|
+
"type": "object",
|
179
|
+
"properties": {
|
180
|
+
"entity_type": {
|
181
|
+
"type": "string",
|
182
|
+
"pattern": "^status_message$"
|
183
|
+
},
|
184
|
+
|
185
|
+
"entity_data": {
|
186
|
+
"type": "object",
|
187
|
+
"properties": {
|
188
|
+
"text": { "type": "string" },
|
189
|
+
|
190
|
+
"location": {
|
191
|
+
"oneOf": [
|
192
|
+
{ "$ref": "#/definitions/location" },
|
193
|
+
{ "type": "null" }
|
194
|
+
]
|
195
|
+
},
|
196
|
+
|
197
|
+
"poll": {
|
198
|
+
"oneOf": [
|
199
|
+
{ "$ref": "#/definitions/poll" },
|
200
|
+
{ "type": "null" }
|
201
|
+
]
|
202
|
+
},
|
203
|
+
|
204
|
+
"photos": {
|
205
|
+
"type": ["array", "null"],
|
206
|
+
"items": { "$ref": "#/definitions/photo" }
|
207
|
+
}
|
208
|
+
},
|
209
|
+
|
210
|
+
"required": ["text"]
|
211
|
+
}
|
212
|
+
}
|
213
|
+
}
|
214
|
+
]
|
215
|
+
},
|
216
|
+
|
217
|
+
"reshare": {
|
218
|
+
"allOf": [
|
219
|
+
{"$ref": "#/definitions/post"},
|
220
|
+
{
|
221
|
+
"type": "object",
|
222
|
+
"properties": {
|
223
|
+
"entity_type": {
|
224
|
+
"type": "string",
|
225
|
+
"pattern": "^reshare$"
|
226
|
+
},
|
227
|
+
|
228
|
+
"entity_data": {
|
229
|
+
"type": "object",
|
230
|
+
"properties": {
|
231
|
+
"root_author": {"type": "string"},
|
232
|
+
"root_guid": {"$ref": "#/definitions/guid"}
|
233
|
+
},
|
234
|
+
|
235
|
+
"required": ["root_author", "root_guid"]
|
236
|
+
}
|
237
|
+
}
|
238
|
+
}
|
239
|
+
]
|
240
|
+
},
|
241
|
+
|
242
|
+
"profile": {
|
243
|
+
"type": "object",
|
244
|
+
"properties": {
|
245
|
+
"entity_type": {
|
246
|
+
"type": "string",
|
247
|
+
"pattern": "^profile$"
|
248
|
+
},
|
249
|
+
"entity_data": {
|
250
|
+
"type": "object",
|
251
|
+
"properties": {
|
252
|
+
"first_name": { "type": ["string", "null"] },
|
253
|
+
"last_name": { "type": ["string", "null"] },
|
254
|
+
"gender": { "type": ["string", "null"] },
|
255
|
+
"bio": { "type": ["string", "null"] },
|
256
|
+
"birthday": { "type": ["string", "null"] },
|
257
|
+
"location": { "type": ["string", "null"] },
|
258
|
+
"image_url": { "type": ["string", "null"] },
|
259
|
+
"author": { "type": "string" }
|
260
|
+
},
|
261
|
+
"required": [
|
262
|
+
"author"
|
263
|
+
]
|
264
|
+
}
|
265
|
+
},
|
266
|
+
"required" :["entity_data", "entity_type"]
|
267
|
+
},
|
268
|
+
|
269
|
+
"photo": {
|
270
|
+
"type": "object",
|
271
|
+
"properties": {
|
272
|
+
"entity_type": {
|
273
|
+
"type": "string",
|
274
|
+
"pattern": "^photo$"
|
275
|
+
},
|
276
|
+
"entity_data": {
|
277
|
+
"type": "object",
|
278
|
+
"properties": {
|
279
|
+
"author": { "type": "string" },
|
280
|
+
"guid": {"$ref": "#/definitions/guid"},
|
281
|
+
"public": {"type": "boolean"},
|
282
|
+
"created_at": {"type": "string"},
|
283
|
+
"remote_photo_path": {"type": "string"},
|
284
|
+
"remote_photo_name": {"type": "string"},
|
285
|
+
"text": {"type": ["null", "string"]},
|
286
|
+
"status_message_guid": {"$ref": "#/definitions/guid"},
|
287
|
+
"width": {"type": "number"},
|
288
|
+
"height": {"type": "number"}
|
289
|
+
},
|
290
|
+
"required": [
|
291
|
+
"author", "guid", "public", "created_at", "remote_photo_path", "remote_photo_name", "width", "height"
|
292
|
+
]
|
293
|
+
}
|
294
|
+
}
|
295
|
+
},
|
296
|
+
|
297
|
+
"poll_answer": {
|
298
|
+
"type": "object",
|
299
|
+
"properties": {
|
300
|
+
"entity_type": {
|
301
|
+
"type": "string",
|
302
|
+
"pattern": "^poll_answer$"
|
303
|
+
},
|
304
|
+
"entity_data": {
|
305
|
+
"type": "object",
|
306
|
+
"properties": {
|
307
|
+
"guid": { "$ref": "#/definitions/guid" },
|
308
|
+
"answer": { "type": "string" }
|
309
|
+
},
|
310
|
+
"required": [
|
311
|
+
"answer",
|
312
|
+
"guid"
|
313
|
+
]
|
314
|
+
}
|
315
|
+
}
|
316
|
+
},
|
317
|
+
|
318
|
+
"poll": {
|
319
|
+
"type": "object",
|
320
|
+
"properties": {
|
321
|
+
"entity_type": {
|
322
|
+
"type": "string",
|
323
|
+
"pattern": "^poll$"
|
324
|
+
},
|
325
|
+
"entity_data": {
|
326
|
+
"type": "object",
|
327
|
+
"properties": {
|
328
|
+
"guid": {
|
329
|
+
"$ref": "#/definitions/guid"
|
330
|
+
},
|
331
|
+
"question": {
|
332
|
+
"type": "string"
|
333
|
+
},
|
334
|
+
"poll_answers": {
|
335
|
+
"type": "array",
|
336
|
+
"items": {
|
337
|
+
"$ref": "#/definitions/poll_answer"
|
338
|
+
}
|
339
|
+
}
|
340
|
+
},
|
341
|
+
"required": [
|
342
|
+
"guid",
|
343
|
+
"question",
|
344
|
+
"poll_answers"
|
345
|
+
]
|
346
|
+
}
|
347
|
+
}
|
348
|
+
},
|
349
|
+
|
350
|
+
"location": {
|
351
|
+
"type": "object",
|
352
|
+
"properties": {
|
353
|
+
"entity_type": {
|
354
|
+
"type": "string",
|
355
|
+
"pattern": "^location$"
|
356
|
+
},
|
357
|
+
"entity_data": {
|
358
|
+
"type": "object",
|
359
|
+
"properties": {
|
360
|
+
"address": {
|
361
|
+
"type": "string"
|
362
|
+
},
|
363
|
+
"lat": {
|
364
|
+
"type": "string"
|
365
|
+
},
|
366
|
+
"lng": {
|
367
|
+
"type": "string"
|
368
|
+
}
|
369
|
+
},
|
370
|
+
"required": [
|
371
|
+
"address",
|
372
|
+
"lat",
|
373
|
+
"lng"
|
374
|
+
]
|
375
|
+
}
|
376
|
+
}
|
377
|
+
}
|
378
|
+
}
|
379
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module DiasporaFederation
|
2
|
+
module Validators
|
3
|
+
# This validates a {Entities::AccountMigration}.
|
4
|
+
class AccountMigrationValidator < Validation::Validator
|
5
|
+
include Validation
|
6
|
+
|
7
|
+
rule :author, %i[not_empty diaspora_id]
|
8
|
+
|
9
|
+
rule :profile, :not_nil
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -4,8 +4,8 @@ module DiasporaFederation
|
|
4
4
|
class ContactValidator < Validation::Validator
|
5
5
|
include Validation
|
6
6
|
|
7
|
-
rule :author, %i
|
8
|
-
rule :recipient, %i
|
7
|
+
rule :author, %i[not_empty diaspora_id]
|
8
|
+
rule :recipient, %i[not_empty diaspora_id]
|
9
9
|
rule :following, :boolean
|
10
10
|
rule :sharing, :boolean
|
11
11
|
end
|