Add support for reversible suspensions through ActivityPub (#14989)

This commit is contained in:
Eugen Rochko
2020-11-08 00:28:39 +01:00
committed by GitHub
parent ee8cf246cf
commit 3134691948
47 changed files with 1049 additions and 204 deletions

View File

@ -73,4 +73,84 @@ RSpec.describe ActivityPub::ProcessAccountService, type: :service do
expect(ProofProvider::Keybase::Worker).to have_received(:perform_async)
end
end
context 'when account is not suspended' do
let!(:account) { Fabricate(:account, username: 'alice', domain: 'example.com') }
let(:payload) do
{
id: 'https://foo.test',
type: 'Actor',
inbox: 'https://foo.test/inbox',
suspended: true,
}.with_indifferent_access
end
before do
allow(Admin::SuspensionWorker).to receive(:perform_async)
end
subject { described_class.new.call('alice', 'example.com', payload) }
it 'suspends account remotely' do
expect(subject.suspended?).to be true
expect(subject.suspension_origin_remote?).to be true
end
it 'queues suspension worker' do
subject
expect(Admin::SuspensionWorker).to have_received(:perform_async)
end
end
context 'when account is suspended' do
let!(:account) { Fabricate(:account, username: 'alice', domain: 'example.com', display_name: '') }
let(:payload) do
{
id: 'https://foo.test',
type: 'Actor',
inbox: 'https://foo.test/inbox',
suspended: false,
name: 'Hoge',
}.with_indifferent_access
end
before do
allow(Admin::UnsuspensionWorker).to receive(:perform_async)
account.suspend!(origin: suspension_origin)
end
subject { described_class.new.call('alice', 'example.com', payload) }
context 'locally' do
let(:suspension_origin) { :local }
it 'does not unsuspend it' do
expect(subject.suspended?).to be true
end
it 'does not update any attributes' do
expect(subject.display_name).to_not eq 'Hoge'
end
end
context 'remotely' do
let(:suspension_origin) { :remote }
it 'unsuspends it' do
expect(subject.suspended?).to be false
end
it 'queues unsuspension worker' do
subject
expect(Admin::UnsuspensionWorker).to have_received(:perform_async)
end
it 'updates attributes' do
expect(subject.display_name).to eq 'Hoge'
end
end
end
end

View File

@ -22,7 +22,48 @@ RSpec.describe ActivityPub::ProcessCollectionService, type: :service do
subject { described_class.new }
describe '#call' do
context 'when actor is the sender'
context 'when actor is suspended' do
before do
actor.suspend!(origin: :remote)
end
%w(Accept Add Announce Block Create Flag Follow Like Move Remove).each do |activity_type|
context "with #{activity_type} activity" do
let(:payload) do
{
'@context': 'https://www.w3.org/ns/activitystreams',
id: 'foo',
type: activity_type,
actor: ActivityPub::TagManager.instance.uri_for(actor),
}
end
it 'does not process payload' do
expect(ActivityPub::Activity).not_to receive(:factory)
subject.call(json, actor)
end
end
end
%w(Delete Reject Undo Update).each do |activity_type|
context "with #{activity_type} activity" do
let(:payload) do
{
'@context': 'https://www.w3.org/ns/activitystreams',
id: 'foo',
type: activity_type,
actor: ActivityPub::TagManager.instance.uri_for(actor),
}
end
it 'processes the payload' do
expect(ActivityPub::Activity).to receive(:factory)
subject.call(json, actor)
end
end
end
end
context 'when actor differs from sender' do
let(:forwarder) { Fabricate(:account, domain: 'example.com', uri: 'http://example.com/other_account') }

View File

@ -13,16 +13,41 @@ RSpec.describe ResolveAccountService, type: :service do
stub_request(:get, "https://ap.example.com/users/foo").to_return(request_fixture('activitypub-actor.txt'))
stub_request(:get, "https://ap.example.com/users/foo.atom").to_return(request_fixture('activitypub-feed.txt'))
stub_request(:get, %r{https://ap.example.com/users/foo/\w+}).to_return(status: 404)
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:hoge@example.com').to_return(status: 410)
end
it 'raises error if no such user can be resolved via webfinger' do
it 'returns nil if no such user can be resolved via webfinger' do
expect(subject.call('catsrgr8@quitter.no')).to be_nil
end
it 'raises error if the domain does not have webfinger' do
it 'returns nil if the domain does not have webfinger' do
expect(subject.call('catsrgr8@example.com')).to be_nil
end
context 'when webfinger returns http gone' do
context 'for a previously known account' do
before do
Fabricate(:account, username: 'hoge', domain: 'example.com', last_webfingered_at: nil)
allow(AccountDeletionWorker).to receive(:perform_async)
end
it 'returns nil' do
expect(subject.call('hoge@example.com')).to be_nil
end
it 'queues account deletion worker' do
subject.call('hoge@example.com')
expect(AccountDeletionWorker).to have_received(:perform_async)
end
end
context 'for a previously unknown account' do
it 'returns nil' do
expect(subject.call('hoge@example.com')).to be_nil
end
end
end
context 'with an ActivityPub account' do
it 'returns new remote account' do
account = subject.call('foo@ap.example.com')