diff --git a/app/services/activitypub/process_featured_item_service.rb b/app/services/activitypub/process_featured_item_service.rb index c1470beeff..b9769cc037 100644 --- a/app/services/activitypub/process_featured_item_service.rb +++ b/app/services/activitypub/process_featured_item_service.rb @@ -15,6 +15,7 @@ class ActivityPub::ProcessFeaturedItemService @approval_uri = value_or_id(@item_json['featureAuthorization']) return if non_matching_uri_hosts?(@collection.uri, @item_json['id']) return if non_matching_actor_and_approval_uris? + return if non_supported_object_type? with_redis_lock("collection_item:#{@item_json['id']}") do @collection_item = existing_item || pre_approved_item || new_item @@ -39,7 +40,7 @@ class ActivityPub::ProcessFeaturedItemService def pre_approved_item # This is a local account that has authorized this item already - local_account = ActivityPub::TagManager.instance.uris_to_local_accounts([@item_json['featuredObject']]).first + local_account = ActivityPub::TagManager.instance.uris_to_local_accounts([@actor_uri]).first @collection.collection_items.accepted_partial(local_account).first if local_account.present? end @@ -49,12 +50,26 @@ class ActivityPub::ProcessFeaturedItemService ) end + def local_actor_uri? + return @local_actor_uri if instance_variable_defined?(:@local_actor_uri) + + @local_actor_uri = ActivityPub::TagManager.instance.local_uri?(@actor_uri) + end + def non_matching_actor_and_approval_uris? - return false if ActivityPub::TagManager.instance.local_uri?(@actor_uri) + return false if local_actor_uri? non_matching_uri_hosts?(@actor_uri, @approval_uri) end + def non_supported_object_type? + return false if local_actor_uri? + return false if Account.exists?(uri: @actor_uri) + + object_json = fetch_resource(@actor_uri, true) + (Array(object_json['type']) & ActivityPub::FetchRemoteActorService::SUPPORTED_TYPES).empty? + end + def verify_authorization! ActivityPub::VerifyFeaturedItemService.new.call(@collection_item, @approval_uri, request_id: @request_id) rescue Mastodon::RecursionLimitExceededError, Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS diff --git a/spec/services/activitypub/process_featured_item_service_spec.rb b/spec/services/activitypub/process_featured_item_service_spec.rb index 637c06c5ac..5f071e364e 100644 --- a/spec/services/activitypub/process_featured_item_service_spec.rb +++ b/spec/services/activitypub/process_featured_item_service_spec.rb @@ -9,7 +9,8 @@ RSpec.describe ActivityPub::ProcessFeaturedItemService do let(:collection) { Fabricate(:remote_collection, uri: 'https://other.example.com/collection/1') } let(:position) { 3 } - let(:featured_object_uri) { 'https://example.com/actor/1' } + let(:account) { Fabricate(:remote_account, uri: 'https://example.com/actor/1') } + let(:featured_object_uri) { account.uri } let(:feature_authorization_uri) { 'https://example.com/auth/1' } let(:featured_item_json) do { @@ -42,7 +43,6 @@ RSpec.describe ActivityPub::ProcessFeaturedItemService do end context 'when the actor URI does not match the approval URI' do - let(:featured_object_uri) { 'https://example.com/actor/1' } let(:feature_authorization_uri) { 'https://other.example.com/auth/1' } it 'does not create a collection item and returns `nil`' do @@ -117,6 +117,32 @@ RSpec.describe ActivityPub::ProcessFeaturedItemService do expect(collection_item.reload.uri).to eq 'https://other.example.com/featured_item/1' end end + + context 'when featured object is of an unsupported type' do + let(:hashtag_json) do + { + 'id' => 'https://example.com/hashtags/people', + 'type' => 'Hashtag', + 'name' => '#people', + } + end + let(:featured_object_uri) { hashtag_json['id'] } + + before do + stub_request(:get, featured_object_uri) + .to_return_json( + status: 200, + body: hashtag_json, + headers: { 'Content-Type' => 'application/activity+json' } + ) + end + + it 'does not create a collection item and returns `nil`' do + expect do + expect(subject.call(collection, object, position:)).to be_nil + end.to_not change(CollectionItem, :count) + end + end end context 'when only the id of the collection item is given' do