forked from diaspora/diaspora
-
Notifications
You must be signed in to change notification settings - Fork 1
/
public.rb
100 lines (84 loc) · 2.92 KB
/
public.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# Copyright (c) 2010-2011, Diaspora Inc. This file is
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
class Postzord::Receiver::Public < Postzord::Receiver
attr_accessor :salmon, :author
def initialize(xml)
@salmon = Salmon::Slap.from_xml(xml)
@author = Webfinger.new(@salmon.author_id).fetch
FEDERATION_LOGGER.info("Receiving public object from person:#{@author.id}")
end
# @return [Boolean]
def verified_signature?
@salmon.verified_for_key?(@author.public_key)
end
# @return [void]
def receive!
return false unless verified_signature?
# return false unless account_deletion_is_from_author
return false unless save_object
FEDERATION_LOGGER.info("received a #{@object.inspect}")
if @object.respond_to?(:relayable?)
receive_relayable
elsif @object.is_a?(AccountDeletion)
#nothing
elsif @object.is_a?(SignedRetraction) # feels like a hack
self.recipient_user_ids.each do |user_id|
user = User.where(id: user_id).first
@object.perform user if user
end
else
Workers::ReceiveLocalBatch.perform_async(@object.class.to_s, @object.id, self.recipient_user_ids)
true
end
end
# @return [Object]
def receive_relayable
if @object.parent_author.local?
# receive relayable object only for the owner of the parent object
@object.receive(@object.parent_author.owner, @author)
end
# notify everyone who can see the parent object
receiver = Postzord::Receiver::LocalBatch.new(@object, self.recipient_user_ids)
receiver.notify_users
@object
end
# @return [Object]
def save_object
@object = Diaspora::Parser::from_xml(@salmon.parsed_data)
raise "Object is not public" if object_can_be_public_and_it_is_not?
raise Diaspora::RelayableObjectWithoutParent if object_must_have_parent_and_does_not?
raise Diaspora::AuthorXMLAuthorMismatch if author_does_not_match_xml_author?
@object.save! if @object && @object.respond_to?(:save!)
@object
end
# @return [Array<Integer>] User ids
def recipient_user_ids
User.all_sharing_with_person(@author).pluck('users.id')
end
def xml_author
if @object.respond_to?(:relayable?)
#this is public, so it would only be owners sending us other people comments etc
@object.parent_author.local? ? @object.diaspora_handle : @object.parent_diaspora_handle
else
@object.diaspora_handle
end
end
private
def account_deletion_is_from_author
return true unless @object.is_a?(AccountDeletion)
return false if @object.diaspora_handle != @author.diaspora_handle
return true
end
# @return [Boolean]
def object_can_be_public_and_it_is_not?
@object.respond_to?(:public) && !@object.public?
end
def object_must_have_parent_and_does_not?
if @object.respond_to?(:relayable?) # comment, like
@object.parent.nil?
else
false
end
end
end