forked from fedi/mastodon
7467361d70
When an ActivityPub Announce is processed and the boosted toot is not known, fetch it on behalf of one of the booster's followers. This is to allow fetching self-boosts of previously-unknown private toots. If fetching on behalf of a user fails, try fetching it anonymously: the selected follower of a boosting user may be banned by the boosted toot's author.
53 lines
1.5 KiB
Ruby
53 lines
1.5 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class ActivityPub::FetchRemoteStatusService < BaseService
|
|
include JsonLdHelper
|
|
|
|
# Should be called when uri has already been checked for locality
|
|
def call(uri, id: true, prefetched_body: nil, on_behalf_of: nil)
|
|
@json = if prefetched_body.nil?
|
|
fetch_resource(uri, id, on_behalf_of)
|
|
else
|
|
body_to_json(prefetched_body)
|
|
end
|
|
|
|
return unless supported_context? && expected_type?
|
|
|
|
return if actor_id.nil? || !trustworthy_attribution?(@json['id'], actor_id)
|
|
|
|
actor = ActivityPub::TagManager.instance.uri_to_resource(actor_id, Account)
|
|
actor = ActivityPub::FetchRemoteAccountService.new.call(actor_id, id: true) if actor.nil? || needs_update(actor)
|
|
|
|
return if actor.nil? || actor.suspended?
|
|
|
|
ActivityPub::Activity.factory(activity_json, actor).perform
|
|
end
|
|
|
|
private
|
|
|
|
def activity_json
|
|
{ 'type' => 'Create', 'actor' => actor_id, 'object' => @json }
|
|
end
|
|
|
|
def actor_id
|
|
value_or_id(first_of_value(@json['attributedTo']))
|
|
end
|
|
|
|
def trustworthy_attribution?(uri, attributed_to)
|
|
return false if uri.nil? || attributed_to.nil?
|
|
Addressable::URI.parse(uri).normalized_host.casecmp(Addressable::URI.parse(attributed_to).normalized_host).zero?
|
|
end
|
|
|
|
def supported_context?
|
|
super(@json)
|
|
end
|
|
|
|
def expected_type?
|
|
equals_or_includes_any?(@json['type'], ActivityPub::Activity::Create::SUPPORTED_TYPES + ActivityPub::Activity::Create::CONVERTED_TYPES)
|
|
end
|
|
|
|
def needs_update(actor)
|
|
actor.possibly_stale?
|
|
end
|
|
end
|