Add support for inlined objects in activity audience (#14514)

* Add support for inlined objects in activity audience

* Add tests
This commit is contained in:
ThibG 2020-08-24 14:11:47 +02:00 committed by Eugen Rochko
parent 8b448aecef
commit aea0161e83
5 changed files with 62 additions and 12 deletions

View file

@ -172,7 +172,7 @@ class ActivityPub::Activity
end end
def first_mentioned_local_account def first_mentioned_local_account
audience = (as_array(@json['to']) + as_array(@json['cc'])).uniq audience = (as_array(@json['to']) + as_array(@json['cc'])).map { |x| value_or_id(x) }.uniq
local_usernames = audience.select { |uri| ActivityPub::TagManager.instance.local_uri?(uri) } local_usernames = audience.select { |uri| ActivityPub::TagManager.instance.local_uri?(uri) }
.map { |uri| ActivityPub::TagManager.instance.uri_to_local_id(uri, :username) } .map { |uri| ActivityPub::TagManager.instance.uri_to_local_id(uri, :username) }

View file

@ -34,12 +34,20 @@ class ActivityPub::Activity::Announce < ActivityPub::Activity
private private
def audience_to
as_array(@json['to']).map { |x| value_or_id(x) }
end
def audience_cc
as_array(@json['cc']).map { |x| value_or_id(x) }
end
def visibility_from_audience def visibility_from_audience
if equals_or_includes?(@json['to'], ActivityPub::TagManager::COLLECTIONS[:public]) if audience_to.include?(ActivityPub::TagManager::COLLECTIONS[:public])
:public :public
elsif equals_or_includes?(@json['cc'], ActivityPub::TagManager::COLLECTIONS[:public]) elsif audience_cc.include?(ActivityPub::TagManager::COLLECTIONS[:public])
:unlisted :unlisted
elsif equals_or_includes?(@json['to'], @account.followers_url) elsif audience_to.include?(@account.followers_url)
:private :private
else else
:direct :direct

View file

@ -65,11 +65,11 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
end end
def audience_to def audience_to
@object['to'] || @json['to'] as_array(@object['to'] || @json['to']).map { |x| value_or_id(x) }
end end
def audience_cc def audience_cc
@object['cc'] || @json['cc'] as_array(@object['cc'] || @json['cc']).map { |x| value_or_id(x) }
end end
def process_status def process_status
@ -122,7 +122,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
end end
def process_audience def process_audience
(as_array(audience_to) + as_array(audience_cc)).uniq.each do |audience| (audience_to + audience_cc).uniq.each do |audience|
next if audience == ActivityPub::TagManager::COLLECTIONS[:public] next if audience == ActivityPub::TagManager::COLLECTIONS[:public]
# Unlike with tags, there is no point in resolving accounts we don't already # Unlike with tags, there is no point in resolving accounts we don't already
@ -352,11 +352,11 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
end end
def visibility_from_audience def visibility_from_audience
if equals_or_includes?(audience_to, ActivityPub::TagManager::COLLECTIONS[:public]) if audience_to.include?(ActivityPub::TagManager::COLLECTIONS[:public])
:public :public
elsif equals_or_includes?(audience_cc, ActivityPub::TagManager::COLLECTIONS[:public]) elsif audience_cc.include?(ActivityPub::TagManager::COLLECTIONS[:public])
:unlisted :unlisted
elsif equals_or_includes?(audience_to, @account.followers_url) elsif audience_to.include?(@account.followers_url)
:private :private
else else
:direct :direct
@ -365,7 +365,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
def audience_includes?(account) def audience_includes?(account)
uri = ActivityPub::TagManager.instance.uri_for(account) uri = ActivityPub::TagManager.instance.uri_for(account)
equals_or_includes?(audience_to, uri) || equals_or_includes?(audience_cc, uri) audience_to.include?(uri) || audience_cc.include?(uri)
end end
def replied_to_status def replied_to_status
@ -477,7 +477,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
def addresses_local_accounts? def addresses_local_accounts?
return true if @options[:delivered_to_account_id] return true if @options[:delivered_to_account_id]
local_usernames = (as_array(audience_to) + as_array(audience_cc)).uniq.select { |uri| ActivityPub::TagManager.instance.local_uri?(uri) }.map { |uri| ActivityPub::TagManager.instance.uri_to_local_id(uri, :username) } local_usernames = (audience_to + audience_cc).uniq.select { |uri| ActivityPub::TagManager.instance.local_uri?(uri) }.map { |uri| ActivityPub::TagManager.instance.uri_to_local_id(uri, :username) }
return false if local_usernames.empty? return false if local_usernames.empty?

View file

@ -73,6 +73,26 @@ RSpec.describe ActivityPub::Activity::Announce do
expect(sender.reblogged?(sender.statuses.first)).to be true expect(sender.reblogged?(sender.statuses.first)).to be true
end end
end end
context 'self-boost of a previously unknown status with correct attributedTo, inlined Collection in audience' do
let(:object_json) do
{
id: 'https://example.com/actor#bar',
type: 'Note',
content: 'Lorem ipsum',
attributedTo: 'https://example.com/actor',
to: {
'type': 'OrderedCollection',
'id': 'http://example.com/followers',
'first': 'http://example.com/followers?page=true',
}
}
end
it 'creates a reblog by sender of status' do
expect(sender.reblogged?(sender.statuses.first)).to be true
end
end
end end
context 'when the status belongs to a local user' do context 'when the status belongs to a local user' do

View file

@ -121,6 +121,28 @@ RSpec.describe ActivityPub::Activity::Create do
end end
end end
context 'private with inlined Collection in audience' do
let(:object_json) do
{
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
type: 'Note',
content: 'Lorem ipsum',
to: {
'type': 'OrderedCollection',
'id': 'http://example.com/followers',
'first': 'http://example.com/followers?page=true',
}
}
end
it 'creates status' do
status = sender.statuses.first
expect(status).to_not be_nil
expect(status.visibility).to eq 'private'
end
end
context 'limited' do context 'limited' do
let(:recipient) { Fabricate(:account) } let(:recipient) { Fabricate(:account) }