forked from cybrespace/mastodon
Prevent silenced local users from notifying remote users not following them (#10575)
* Prevent silenced local users from notifying remote users not following them This is an attempt to extend the local restrictions of silenced users to the federation. * Add tests * Add tests for making sure private status don't get sent over OStatus
This commit is contained in:
parent
26fc21c188
commit
62f5235b6f
|
@ -65,7 +65,14 @@ class ActivityPub::TagManager
|
||||||
when 'unlisted', 'private'
|
when 'unlisted', 'private'
|
||||||
[account_followers_url(status.account)]
|
[account_followers_url(status.account)]
|
||||||
when 'direct', 'limited'
|
when 'direct', 'limited'
|
||||||
status.active_mentions.map { |mention| uri_for(mention.account) }
|
if status.account.silenced?
|
||||||
|
# Only notify followers if the account is locally silenced
|
||||||
|
account_ids = status.active_mentions.pluck(:account_id)
|
||||||
|
to = status.account.followers.where(id: account_ids).map { |account| uri_for(account) }
|
||||||
|
to.concat(FollowRequest.where(target_account_id: status.account_id, account_id: account_ids).map { |request| uri_for(request.account) })
|
||||||
|
else
|
||||||
|
status.active_mentions.map { |mention| uri_for(mention.account) }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -86,7 +93,16 @@ class ActivityPub::TagManager
|
||||||
cc << COLLECTIONS[:public]
|
cc << COLLECTIONS[:public]
|
||||||
end
|
end
|
||||||
|
|
||||||
cc.concat(status.active_mentions.map { |mention| uri_for(mention.account) }) unless status.direct_visibility? || status.limited_visibility?
|
unless status.direct_visibility? || status.limited_visibility?
|
||||||
|
if status.account.silenced?
|
||||||
|
# Only notify followers if the account is locally silenced
|
||||||
|
account_ids = status.active_mentions.pluck(:account_id)
|
||||||
|
cc.concat(status.account.followers.where(id: account_ids).map { |account| uri_for(account) })
|
||||||
|
cc.concat(FollowRequest.where(target_account_id: status.account_id, account_id: account_ids).map { |request| uri_for(request.account) })
|
||||||
|
else
|
||||||
|
cc.concat(status.active_mentions.map { |mention| uri_for(mention.account) })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
cc
|
cc
|
||||||
end
|
end
|
||||||
|
|
|
@ -41,6 +41,22 @@ RSpec.describe ActivityPub::TagManager do
|
||||||
status.mentions.create(account: mentioned)
|
status.mentions.create(account: mentioned)
|
||||||
expect(subject.to(status)).to eq [subject.uri_for(mentioned)]
|
expect(subject.to(status)).to eq [subject.uri_for(mentioned)]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "returns URIs of mentions for direct silenced author's status only if they are followers or requesting to be" do
|
||||||
|
bob = Fabricate(:account, username: 'bob')
|
||||||
|
alice = Fabricate(:account, username: 'alice')
|
||||||
|
foo = Fabricate(:account)
|
||||||
|
author = Fabricate(:account, username: 'author', silenced: true)
|
||||||
|
status = Fabricate(:status, visibility: :direct, account: author)
|
||||||
|
bob.follow!(author)
|
||||||
|
FollowRequest.create!(account: foo, target_account: author)
|
||||||
|
status.mentions.create(account: alice)
|
||||||
|
status.mentions.create(account: bob)
|
||||||
|
status.mentions.create(account: foo)
|
||||||
|
expect(subject.to(status)).to include(subject.uri_for(bob))
|
||||||
|
expect(subject.to(status)).to include(subject.uri_for(foo))
|
||||||
|
expect(subject.to(status)).to_not include(subject.uri_for(alice))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#cc' do
|
describe '#cc' do
|
||||||
|
@ -70,6 +86,22 @@ RSpec.describe ActivityPub::TagManager do
|
||||||
status.mentions.create(account: mentioned)
|
status.mentions.create(account: mentioned)
|
||||||
expect(subject.cc(status)).to include(subject.uri_for(mentioned))
|
expect(subject.cc(status)).to include(subject.uri_for(mentioned))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "returns URIs of mentions for silenced author's non-direct status only if they are followers or requesting to be" do
|
||||||
|
bob = Fabricate(:account, username: 'bob')
|
||||||
|
alice = Fabricate(:account, username: 'alice')
|
||||||
|
foo = Fabricate(:account)
|
||||||
|
author = Fabricate(:account, username: 'author', silenced: true)
|
||||||
|
status = Fabricate(:status, visibility: :public, account: author)
|
||||||
|
bob.follow!(author)
|
||||||
|
FollowRequest.create!(account: foo, target_account: author)
|
||||||
|
status.mentions.create(account: alice)
|
||||||
|
status.mentions.create(account: bob)
|
||||||
|
status.mentions.create(account: foo)
|
||||||
|
expect(subject.cc(status)).to include(subject.uri_for(bob))
|
||||||
|
expect(subject.cc(status)).to include(subject.uri_for(foo))
|
||||||
|
expect(subject.cc(status)).to_not include(subject.uri_for(alice))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#local_uri?' do
|
describe '#local_uri?' do
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
RSpec.describe ProcessMentionsService, type: :service do
|
RSpec.describe ProcessMentionsService, type: :service do
|
||||||
let(:account) { Fabricate(:account, username: 'alice') }
|
let(:account) { Fabricate(:account, username: 'alice') }
|
||||||
let(:status) { Fabricate(:status, account: account, text: "Hello @#{remote_user.acct}") }
|
let(:visibility) { :public }
|
||||||
|
let(:status) { Fabricate(:status, account: account, text: "Hello @#{remote_user.acct}", visibility: visibility) }
|
||||||
|
|
||||||
context 'OStatus' do
|
context 'OStatus with public toot' do
|
||||||
let(:remote_user) { Fabricate(:account, username: 'remote_user', protocol: :ostatus, domain: 'example.com', salmon_url: 'http://salmon.example.com') }
|
let(:remote_user) { Fabricate(:account, username: 'remote_user', protocol: :ostatus, domain: 'example.com', salmon_url: 'http://salmon.example.com') }
|
||||||
|
|
||||||
subject { ProcessMentionsService.new }
|
subject { ProcessMentionsService.new }
|
||||||
|
@ -23,6 +24,26 @@ RSpec.describe ProcessMentionsService, type: :service do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'OStatus with private toot' do
|
||||||
|
let(:visibility) { :private }
|
||||||
|
let(:remote_user) { Fabricate(:account, username: 'remote_user', protocol: :ostatus, domain: 'example.com', salmon_url: 'http://salmon.example.com') }
|
||||||
|
|
||||||
|
subject { ProcessMentionsService.new }
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub_request(:post, remote_user.salmon_url)
|
||||||
|
subject.call(status)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not create a mention' do
|
||||||
|
expect(remote_user.mentions.where(status: status).count).to eq 0
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not post to remote user\'s Salmon end point' do
|
||||||
|
expect(a_request(:post, remote_user.salmon_url)).to_not have_been_made
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'ActivityPub' do
|
context 'ActivityPub' do
|
||||||
let(:remote_user) { Fabricate(:account, username: 'remote_user', protocol: :activitypub, domain: 'example.com', inbox_url: 'http://example.com/inbox') }
|
let(:remote_user) { Fabricate(:account, username: 'remote_user', protocol: :activitypub, domain: 'example.com', inbox_url: 'http://example.com/inbox') }
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue