about summary refs log tree commit diff
path: root/spec/services
diff options
context:
space:
mode:
Diffstat (limited to 'spec/services')
-rw-r--r--spec/services/activitypub/process_account_service_spec.rb80
-rw-r--r--spec/services/activitypub/process_collection_service_spec.rb43
-rw-r--r--spec/services/resolve_account_service_spec.rb29
-rw-r--r--spec/services/resolve_url_service_spec.rb97
4 files changed, 246 insertions, 3 deletions
diff --git a/spec/services/activitypub/process_account_service_spec.rb b/spec/services/activitypub/process_account_service_spec.rb
index 5141e3f16..56e7f8321 100644
--- a/spec/services/activitypub/process_account_service_spec.rb
+++ b/spec/services/activitypub/process_account_service_spec.rb
@@ -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
diff --git a/spec/services/activitypub/process_collection_service_spec.rb b/spec/services/activitypub/process_collection_service_spec.rb
index b3baf6b6b..00d71a86a 100644
--- a/spec/services/activitypub/process_collection_service_spec.rb
+++ b/spec/services/activitypub/process_collection_service_spec.rb
@@ -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') }
 
diff --git a/spec/services/resolve_account_service_spec.rb b/spec/services/resolve_account_service_spec.rb
index cea942e39..76cb9ed8d 100644
--- a/spec/services/resolve_account_service_spec.rb
+++ b/spec/services/resolve_account_service_spec.rb
@@ -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')
diff --git a/spec/services/resolve_url_service_spec.rb b/spec/services/resolve_url_service_spec.rb
index aa4204637..a38b23590 100644
--- a/spec/services/resolve_url_service_spec.rb
+++ b/spec/services/resolve_url_service_spec.rb
@@ -15,5 +15,102 @@ describe ResolveURLService, type: :service do
 
       expect(subject.call(url)).to be_nil
     end
+
+    context 'searching for a remote private status' do
+      let(:account)  { Fabricate(:account) }
+      let(:poster)   { Fabricate(:account, domain: 'example.com') }
+      let(:url)      { 'https://example.com/@foo/42' }
+      let(:uri)      { 'https://example.com/users/foo/statuses/42' }
+      let!(:status)  { Fabricate(:status, url: url, uri: uri, account: poster, visibility: :private) }
+
+      before do
+        stub_request(:get, url).to_return(status: 404) if url.present?
+        stub_request(:get, uri).to_return(status: 404)
+      end
+
+      context 'when the account follows the poster' do
+        before do
+          account.follow!(poster)
+        end
+
+        context 'when the status uses Mastodon-style URLs' do
+          let(:url) { 'https://example.com/@foo/42' }
+          let(:uri) { 'https://example.com/users/foo/statuses/42' }
+
+          it 'returns status by url' do
+            expect(subject.call(url, on_behalf_of: account)).to eq(status)
+          end
+
+          it 'returns status by uri' do
+            expect(subject.call(uri, on_behalf_of: account)).to eq(status)
+          end
+        end
+
+        context 'when the status uses pleroma-style URLs' do
+          let(:url) { nil }
+          let(:uri) { 'https://example.com/objects/0123-456-789-abc-def' }
+
+          it 'returns status by uri' do
+            expect(subject.call(uri, on_behalf_of: account)).to eq(status)
+          end
+        end
+      end
+
+      context 'when the account does not follow the poster' do
+        context 'when the status uses Mastodon-style URLs' do
+          let(:url) { 'https://example.com/@foo/42' }
+          let(:uri) { 'https://example.com/users/foo/statuses/42' }
+
+          it 'does not return the status by url' do
+            expect(subject.call(url, on_behalf_of: account)).to be_nil
+          end
+
+          it 'does not return the status by uri' do
+            expect(subject.call(uri, on_behalf_of: account)).to be_nil
+          end
+        end
+
+        context 'when the status uses pleroma-style URLs' do
+          let(:url) { nil }
+          let(:uri) { 'https://example.com/objects/0123-456-789-abc-def' }
+
+          it 'returns status by uri' do
+            expect(subject.call(uri, on_behalf_of: account)).to be_nil
+          end
+        end
+      end
+    end
+
+    context 'searching for a local private status' do
+      let(:account) { Fabricate(:account) }
+      let(:poster)  { Fabricate(:account) }
+      let!(:status) { Fabricate(:status, account: poster, visibility: :private) }
+      let(:url)     { ActivityPub::TagManager.instance.url_for(status) }
+      let(:uri)     { ActivityPub::TagManager.instance.uri_for(status) }
+
+      context 'when the account follows the poster' do
+        before do
+          account.follow!(poster)
+        end
+
+        it 'returns status by url' do
+          expect(subject.call(url, on_behalf_of: account)).to eq(status)
+        end
+
+        it 'returns status by uri' do
+          expect(subject.call(uri, on_behalf_of: account)).to eq(status)
+        end
+      end
+
+      context 'when the account does not follow the poster' do
+        it 'does not return the status by url' do
+          expect(subject.call(url, on_behalf_of: account)).to be_nil
+        end
+
+        it 'does not return the status by uri' do
+          expect(subject.call(uri, on_behalf_of: account)).to be_nil
+        end
+      end
+    end
   end
 end