diaspora_federation 0.1.9 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|