Refactor local-URI-to-account resolving (#34349)
This commit is contained in:
		@@ -130,12 +130,7 @@ class ActivityPub::Activity
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  def first_mentioned_local_account
 | 
					  def first_mentioned_local_account
 | 
				
			||||||
    audience = (as_array(@json['to']) + as_array(@json['cc'])).map { |x| value_or_id(x) }.uniq
 | 
					    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) }
 | 
					    ActivityPub::TagManager.instance.uris_to_local_accounts(audience).first
 | 
				
			||||||
                              .map { |uri| ActivityPub::TagManager.instance.uri_to_local_id(uri, :username) }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return if local_usernames.empty?
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Account.local.where(username: local_usernames).first
 | 
					 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def first_local_follower
 | 
					  def first_local_follower
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -412,11 +412,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
 | 
				
			|||||||
  def addresses_local_accounts?
 | 
					  def addresses_local_accounts?
 | 
				
			||||||
    return true if @options[:delivered_to_account_id]
 | 
					    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) }
 | 
					    ActivityPub::TagManager.instance.uris_to_local_accounts((audience_to + audience_cc).uniq).exists?
 | 
				
			||||||
 | 
					 | 
				
			||||||
    return false if local_usernames.empty?
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Account.local.exists?(username: local_usernames)
 | 
					 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def tombstone_exists?
 | 
					  def tombstone_exists?
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -203,6 +203,19 @@ class ActivityPub::TagManager
 | 
				
			|||||||
    path_params[param]
 | 
					    path_params[param]
 | 
				
			||||||
  end
 | 
					  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)
 | 
					  def uri_to_actor(uri)
 | 
				
			||||||
    uri_to_resource(uri, Account)
 | 
					    uri_to_resource(uri, Account)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
@@ -213,7 +226,7 @@ class ActivityPub::TagManager
 | 
				
			|||||||
    if local_uri?(uri)
 | 
					    if local_uri?(uri)
 | 
				
			||||||
      case klass.name
 | 
					      case klass.name
 | 
				
			||||||
      when 'Account'
 | 
					      when 'Account'
 | 
				
			||||||
        klass.find_local(uri_to_local_id(uri, :username))
 | 
					        uris_to_local_accounts([uri]).first
 | 
				
			||||||
      else
 | 
					      else
 | 
				
			||||||
        StatusFinder.new(uri).status
 | 
					        StatusFinder.new(uri).status
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
@@ -225,4 +238,20 @@ class ActivityPub::TagManager
 | 
				
			|||||||
  rescue ActiveRecord::RecordNotFound
 | 
					  rescue ActiveRecord::RecordNotFound
 | 
				
			||||||
    nil
 | 
					    nil
 | 
				
			||||||
  end
 | 
					  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
 | 
					end
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,10 +30,7 @@ class ActivityPub::SynchronizeFollowersService < BaseService
 | 
				
			|||||||
    # Account record, and should we not do that, we should have sent a Delete.
 | 
					    # 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.
 | 
					    # In any case there is not much we can do if that occurs.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # TODO: this will need changes when switching to numeric IDs
 | 
					    ActivityPub::TagManager.instance.uris_to_local_accounts(items)
 | 
				
			||||||
 | 
					 | 
				
			||||||
    usernames = items.filter_map { |uri| ActivityPub::TagManager.instance.uri_to_local_id(uri, :username)&.downcase }
 | 
					 | 
				
			||||||
    Account.local.with_username(usernames)
 | 
					 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def remove_unexpected_local_followers!
 | 
					  def remove_unexpected_local_followers!
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -187,6 +187,23 @@ RSpec.describe ActivityPub::TagManager do
 | 
				
			|||||||
    end
 | 
					    end
 | 
				
			||||||
  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
 | 
					  describe '#uri_to_resource' do
 | 
				
			||||||
    it 'returns the local account' do
 | 
					    it 'returns the local account' do
 | 
				
			||||||
      account = Fabricate(:account)
 | 
					      account = Fabricate(:account)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user