diff --git a/app/models/account.rb b/app/models/account.rb index d80ce39a3a..22b8bce601 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -85,7 +85,7 @@ class Account < ApplicationRecord include Account::Associations include Account::Avatar include Account::Counters - include Account::FaspConcern if Mastodon::Feature.fasp_enabled? + include Account::FaspConcern include Account::FinderConcern include Account::Header include Account::Interactions diff --git a/app/models/concerns/account/fasp_concern.rb b/app/models/concerns/account/fasp_concern.rb index 6c1d6cc710..b18529a3e9 100644 --- a/app/models/concerns/account/fasp_concern.rb +++ b/app/models/concerns/account/fasp_concern.rb @@ -12,6 +12,7 @@ module Account::FaspConcern private def announce_new_account_to_subscribed_fasp + return unless Mastodon::Feature.fasp_enabled? return unless discoverable? uri = ActivityPub::TagManager.instance.uri_for(self) @@ -19,6 +20,7 @@ module Account::FaspConcern end def announce_updated_account_to_subscribed_fasp + return unless Mastodon::Feature.fasp_enabled? return unless discoverable? || saved_change_to_discoverable? uri = ActivityPub::TagManager.instance.uri_for(self) @@ -26,6 +28,7 @@ module Account::FaspConcern end def announce_deleted_account_to_subscribed_fasp + return unless Mastodon::Feature.fasp_enabled? return unless discoverable? uri = ActivityPub::TagManager.instance.uri_for(self) diff --git a/app/models/concerns/favourite/fasp_concern.rb b/app/models/concerns/favourite/fasp_concern.rb index 2293411f3d..c72e7c3792 100644 --- a/app/models/concerns/favourite/fasp_concern.rb +++ b/app/models/concerns/favourite/fasp_concern.rb @@ -10,6 +10,8 @@ module Favourite::FaspConcern private def announce_trends_to_subscribed_fasp + return unless Mastodon::Feature.fasp_enabled? + Fasp::AnnounceTrendWorker.perform_async(status_id, 'favourite') end end diff --git a/app/models/concerns/status/fasp_concern.rb b/app/models/concerns/status/fasp_concern.rb index 82c6e8a9b6..d09dd3ca10 100644 --- a/app/models/concerns/status/fasp_concern.rb +++ b/app/models/concerns/status/fasp_concern.rb @@ -13,6 +13,7 @@ module Status::FaspConcern private def announce_new_content_to_subscribed_fasp + return unless Mastodon::Feature.fasp_enabled? return unless account_indexable? && public_visibility? store_uri unless uri # TODO: solve this more elegantly @@ -20,18 +21,21 @@ module Status::FaspConcern end def announce_updated_content_to_subscribed_fasp + return unless Mastodon::Feature.fasp_enabled? return unless account_indexable? && public_visibility_or_just_changed? Fasp::AnnounceContentLifecycleEventWorker.perform_async(uri, 'update') end def announce_deleted_content_to_subscribed_fasp + return unless Mastodon::Feature.fasp_enabled? return unless account_indexable? && public_visibility? Fasp::AnnounceContentLifecycleEventWorker.perform_async(uri, 'delete') end def announce_trends_to_subscribed_fasp + return unless Mastodon::Feature.fasp_enabled? return unless account_indexable? candidate_id, trend_source = diff --git a/app/models/favourite.rb b/app/models/favourite.rb index 1731ac0d03..7bf793e2a1 100644 --- a/app/models/favourite.rb +++ b/app/models/favourite.rb @@ -13,7 +13,7 @@ class Favourite < ApplicationRecord include Paginable - include Favourite::FaspConcern if Mastodon::Feature.fasp_enabled? + include Favourite::FaspConcern update_index('statuses', :status) diff --git a/app/models/status.rb b/app/models/status.rb index 327a21dc1b..bd5267a7d5 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -35,7 +35,7 @@ class Status < ApplicationRecord include Discard::Model include Paginable include RateLimitable - include Status::FaspConcern if Mastodon::Feature.fasp_enabled? + include Status::FaspConcern include Status::FetchRepliesConcern include Status::SafeReblogInsert include Status::SearchConcern diff --git a/spec/models/concerns/account/fasp_concern_spec.rb b/spec/models/concerns/account/fasp_concern_spec.rb new file mode 100644 index 0000000000..0434689bff --- /dev/null +++ b/spec/models/concerns/account/fasp_concern_spec.rb @@ -0,0 +1,83 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Account::FaspConcern, feature: :fasp do + describe '#create' do + let(:discoverable_attributes) do + Fabricate.attributes_for(:account).except('user_id') + end + let(:undiscoverable_attributes) do + discoverable_attributes.merge('discoverable' => false) + end + + context 'when account is discoverable' do + it 'queues a job to notify provider' do + Account.create(discoverable_attributes) + + expect(Fasp::AnnounceAccountLifecycleEventWorker).to have_enqueued_sidekiq_job + end + end + + context 'when account is not discoverable' do + it 'does not queue a job' do + Account.create(undiscoverable_attributes) + + expect(Fasp::AnnounceAccountLifecycleEventWorker).to_not have_enqueued_sidekiq_job + end + end + end + + describe '#update' do + before do + # Create account and clear sidekiq queue so we only catch + # jobs queued as part of the update + account + Sidekiq::Worker.clear_all + end + + context 'when account is discoverable' do + let(:account) { Fabricate(:account, domain: 'example.com') } + + it 'queues a job to notify provider' do + expect { account.touch }.to enqueue_sidekiq_job(Fasp::AnnounceAccountLifecycleEventWorker) + end + end + + context 'when account was discoverable before' do + let(:account) { Fabricate(:account, domain: 'example.com') } + + it 'queues a job to notify provider' do + expect do + account.update(discoverable: false) + end.to enqueue_sidekiq_job(Fasp::AnnounceAccountLifecycleEventWorker) + end + end + + context 'when account has not been discoverable' do + let(:account) { Fabricate(:account, domain: 'example.com', discoverable: false) } + + it 'does not queue a job' do + expect { account.touch }.to_not enqueue_sidekiq_job(Fasp::AnnounceAccountLifecycleEventWorker) + end + end + end + + describe '#destroy' do + context 'when account is discoverable' do + let(:account) { Fabricate(:account, domain: 'example.com') } + + it 'queues a job to notify provider' do + expect { account.destroy }.to enqueue_sidekiq_job(Fasp::AnnounceAccountLifecycleEventWorker) + end + end + + context 'when account is not discoverable' do + let(:account) { Fabricate(:account, domain: 'example.com', discoverable: false) } + + it 'does not queue a job' do + expect { account.destroy }.to_not enqueue_sidekiq_job(Fasp::AnnounceAccountLifecycleEventWorker) + end + end + end +end diff --git a/spec/models/concerns/favourite/fasp_concern_spec.rb b/spec/models/concerns/favourite/fasp_concern_spec.rb new file mode 100644 index 0000000000..a56618f1f2 --- /dev/null +++ b/spec/models/concerns/favourite/fasp_concern_spec.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Favourite::FaspConcern, feature: :fasp do + describe '#create' do + it 'queues a job to notify provider' do + expect { Fabricate(:favourite) }.to enqueue_sidekiq_job(Fasp::AnnounceTrendWorker) + end + end +end diff --git a/spec/models/concerns/status/fasp_concern_spec.rb b/spec/models/concerns/status/fasp_concern_spec.rb new file mode 100644 index 0000000000..f904a833fc --- /dev/null +++ b/spec/models/concerns/status/fasp_concern_spec.rb @@ -0,0 +1,133 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Status::FaspConcern, feature: :fasp do + describe '#create' do + context 'when account is indexable' do + let(:account) { Fabricate(:account, domain: 'example.com') } + + context 'when status is public' do + it 'queues a job to notify provider of new status' do + expect do + Fabricate(:status, account:) + end.to enqueue_sidekiq_job(Fasp::AnnounceContentLifecycleEventWorker) + end + end + + context 'when status is not public' do + it 'does not queue a job' do + expect do + Fabricate(:status, account:, visibility: :unlisted) + end.to_not enqueue_sidekiq_job(Fasp::AnnounceContentLifecycleEventWorker) + end + end + + context 'when status is in reply to another' do + it 'queues a job to notify provider of possible trend' do + parent = Fabricate(:status) + expect do + Fabricate(:status, account:, thread: parent) + end.to enqueue_sidekiq_job(Fasp::AnnounceTrendWorker) + end + end + + context 'when status is a reblog of another' do + it 'queues a job to notify provider of possible trend' do + original = Fabricate(:status, account:) + expect do + Fabricate(:status, account:, reblog: original) + end.to enqueue_sidekiq_job(Fasp::AnnounceTrendWorker) + end + end + end + + context 'when account is not indexable' do + let(:account) { Fabricate(:account, indexable: false) } + + it 'does not queue a job' do + expect do + Fabricate(:status, account:) + end.to_not enqueue_sidekiq_job(Fasp::AnnounceContentLifecycleEventWorker) + end + end + end + + describe '#update' do + before do + # Create status and clear sidekiq queues to only catch + # jobs queued due to the update + status + Sidekiq::Worker.clear_all + end + + context 'when account is indexable' do + let(:account) { Fabricate(:account, domain: 'example.com') } + let(:status) { Fabricate(:status, account:, visibility:) } + + context 'when status is public' do + let(:visibility) { :public } + + it 'queues a job to notify provider' do + expect { status.touch }.to enqueue_sidekiq_job(Fasp::AnnounceContentLifecycleEventWorker) + end + end + + context 'when status just switched to non-public' do + let(:visibility) { :public } + + it 'queues a job to notify provider' do + expect do + status.update(visibility: :unlisted) + end.to enqueue_sidekiq_job(Fasp::AnnounceContentLifecycleEventWorker) + end + end + + context 'when status has not been public' do + let(:visibility) { :unlisted } + + it 'does not queue a job' do + expect do + status.touch + end.to_not enqueue_sidekiq_job(Fasp::AnnounceContentLifecycleEventWorker) + end + end + end + + context 'when account is not indexable' do + let(:account) { Fabricate(:account, domain: 'example.com', indexable: false) } + let(:status) { Fabricate(:status, account:) } + + it 'does not queue a job' do + expect { status.touch }.to_not enqueue_sidekiq_job(Fasp::AnnounceContentLifecycleEventWorker) + end + end + end + + describe '#destroy' do + let(:status) { Fabricate(:status, account:) } + + before do + # Create status and clear sidekiq queues to only catch + # jobs queued due to the update + status + Sidekiq::Worker.clear_all + end + + context 'when account is indexable' do + let(:account) { Fabricate(:account, domain: 'example.com') } + + it 'queues a job to notify provider' do + expect { status.destroy }.to enqueue_sidekiq_job(Fasp::AnnounceContentLifecycleEventWorker) + end + end + + context 'when account is not indexable' do + let(:account) { Fabricate(:account, domain: 'example.com', indexable: false) } + + it 'does not queue a job' do + expect { status.destroy }.to_not enqueue_sidekiq_job(Fasp::AnnounceContentLifecycleEventWorker) + end + end + end +end