Refactor local-URI-to-account resolving (#34349)
This commit is contained in:
		@@ -130,12 +130,7 @@ class ActivityPub::Activity
 | 
			
		||||
 | 
			
		||||
  def first_mentioned_local_account
 | 
			
		||||
    audience = (as_array(@json['to']) + as_array(@json['cc'])).map { |x| value_or_id(x) }.uniq
 | 
			
		||||
    local_usernames = audience.select { |uri| ActivityPub::TagManager.instance.local_uri?(uri) }
 | 
			
		||||
                              .map { |uri| ActivityPub::TagManager.instance.uri_to_local_id(uri, :username) }
 | 
			
		||||
 | 
			
		||||
    return if local_usernames.empty?
 | 
			
		||||
 | 
			
		||||
    Account.local.where(username: local_usernames).first
 | 
			
		||||
    ActivityPub::TagManager.instance.uris_to_local_accounts(audience).first
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def first_local_follower
 | 
			
		||||
 
 | 
			
		||||
@@ -412,11 +412,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
 | 
			
		||||
  def addresses_local_accounts?
 | 
			
		||||
    return true if @options[:delivered_to_account_id]
 | 
			
		||||
 | 
			
		||||
    local_usernames = (audience_to + audience_cc).uniq.select { |uri| ActivityPub::TagManager.instance.local_uri?(uri) }.map { |uri| ActivityPub::TagManager.instance.uri_to_local_id(uri, :username) }
 | 
			
		||||
 | 
			
		||||
    return false if local_usernames.empty?
 | 
			
		||||
 | 
			
		||||
    Account.local.exists?(username: local_usernames)
 | 
			
		||||
    ActivityPub::TagManager.instance.uris_to_local_accounts((audience_to + audience_cc).uniq).exists?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def tombstone_exists?
 | 
			
		||||
 
 | 
			
		||||
@@ -203,6 +203,19 @@ class ActivityPub::TagManager
 | 
			
		||||
    path_params[param]
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def uris_to_local_accounts(uris)
 | 
			
		||||
    usernames = []
 | 
			
		||||
    ids = []
 | 
			
		||||
 | 
			
		||||
    uris.each do |uri|
 | 
			
		||||
      param, value = uri_to_local_account_params(uri)
 | 
			
		||||
      usernames << value.downcase if param == :username
 | 
			
		||||
      ids << value if param == :id
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    Account.local.with_username(usernames).or(Account.local.where(id: ids))
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def uri_to_actor(uri)
 | 
			
		||||
    uri_to_resource(uri, Account)
 | 
			
		||||
  end
 | 
			
		||||
@@ -213,7 +226,7 @@ class ActivityPub::TagManager
 | 
			
		||||
    if local_uri?(uri)
 | 
			
		||||
      case klass.name
 | 
			
		||||
      when 'Account'
 | 
			
		||||
        klass.find_local(uri_to_local_id(uri, :username))
 | 
			
		||||
        uris_to_local_accounts([uri]).first
 | 
			
		||||
      else
 | 
			
		||||
        StatusFinder.new(uri).status
 | 
			
		||||
      end
 | 
			
		||||
@@ -225,4 +238,20 @@ class ActivityPub::TagManager
 | 
			
		||||
  rescue ActiveRecord::RecordNotFound
 | 
			
		||||
    nil
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
 | 
			
		||||
  def uri_to_local_account_params(uri)
 | 
			
		||||
    return unless local_uri?(uri)
 | 
			
		||||
 | 
			
		||||
    path_params = Rails.application.routes.recognize_path(uri)
 | 
			
		||||
 | 
			
		||||
    # TODO: handle numeric IDs
 | 
			
		||||
    case path_params[:controller]
 | 
			
		||||
    when 'accounts'
 | 
			
		||||
      [:username, path_params[:username]]
 | 
			
		||||
    when 'instance_actors'
 | 
			
		||||
      [:id, -99]
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -30,10 +30,7 @@ class ActivityPub::SynchronizeFollowersService < BaseService
 | 
			
		||||
    # Account record, and should we not do that, we should have sent a Delete.
 | 
			
		||||
    # In any case there is not much we can do if that occurs.
 | 
			
		||||
 | 
			
		||||
    # TODO: this will need changes when switching to numeric IDs
 | 
			
		||||
 | 
			
		||||
    usernames = items.filter_map { |uri| ActivityPub::TagManager.instance.uri_to_local_id(uri, :username)&.downcase }
 | 
			
		||||
    Account.local.with_username(usernames)
 | 
			
		||||
    ActivityPub::TagManager.instance.uris_to_local_accounts(items)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def remove_unexpected_local_followers!
 | 
			
		||||
 
 | 
			
		||||
@@ -187,6 +187,23 @@ RSpec.describe ActivityPub::TagManager do
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe '#uris_to_local_accounts' do
 | 
			
		||||
    it 'returns the expected local accounts' do
 | 
			
		||||
      account = Fabricate(:account)
 | 
			
		||||
      expect(subject.uris_to_local_accounts([subject.uri_for(account), instance_actor_url])).to contain_exactly(account, Account.representative)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'does not return remote accounts' do
 | 
			
		||||
      account = Fabricate(:account, uri: 'https://example.com/123', domain: 'example.com')
 | 
			
		||||
      expect(subject.uris_to_local_accounts([subject.uri_for(account)])).to be_empty
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'does not return an account for a local post' do
 | 
			
		||||
      status = Fabricate(:status)
 | 
			
		||||
      expect(subject.uris_to_local_accounts([subject.uri_for(status)])).to be_empty
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe '#uri_to_resource' do
 | 
			
		||||
    it 'returns the local account' do
 | 
			
		||||
      account = Fabricate(:account)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user