forked from cybrespace/mastodon
		
	Fix some ActivityPub JSON bugs (#4796)
- Fix assumption that `url` is always a string. Handle it if it's an array of strings, array of objects, object, or string, both for accounts and for objects - `sharedInbox` is actually supposed to be under `endpoints`, handle both cases and adjust the serializer
This commit is contained in:
		
							parent
							
								
									2293466edd
								
							
						
					
					
						commit
						9b50a9dd83
					
				
					 3 changed files with 40 additions and 8 deletions
				
			
		| 
						 | 
					@ -33,7 +33,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
 | 
				
			||||||
  def status_params
 | 
					  def status_params
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      uri: @object['id'],
 | 
					      uri: @object['id'],
 | 
				
			||||||
      url: @object['url'] || @object['id'],
 | 
					      url: object_url || @object['id'],
 | 
				
			||||||
      account: @account,
 | 
					      account: @account,
 | 
				
			||||||
      text: text_from_content || '',
 | 
					      text: text_from_content || '',
 | 
				
			||||||
      language: language_from_content,
 | 
					      language: language_from_content,
 | 
				
			||||||
| 
						 | 
					@ -147,6 +147,16 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
 | 
				
			||||||
    @object['contentMap'].keys.first
 | 
					    @object['contentMap'].keys.first
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def object_url
 | 
				
			||||||
 | 
					    return if @object['url'].blank?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    value = first_of_value(@object['url'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return value if value.is_a?(String)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    value['href']
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def language_map?
 | 
					  def language_map?
 | 
				
			||||||
    @object['contentMap'].is_a?(Hash) && !@object['contentMap'].empty?
 | 
					    @object['contentMap'].is_a?(Hash) && !@object['contentMap'].empty?
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,7 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer
 | 
				
			||||||
  include RoutingHelper
 | 
					  include RoutingHelper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  attributes :id, :type, :following, :followers,
 | 
					  attributes :id, :type, :following, :followers,
 | 
				
			||||||
             :inbox, :outbox, :shared_inbox,
 | 
					             :inbox, :outbox,
 | 
				
			||||||
             :preferred_username, :name, :summary,
 | 
					             :preferred_username, :name, :summary,
 | 
				
			||||||
             :url, :manually_approves_followers
 | 
					             :url, :manually_approves_followers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,18 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  class EndpointsSerializer < ActiveModel::Serializer
 | 
				
			||||||
 | 
					    include RoutingHelper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    attributes :shared_inbox
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def shared_inbox
 | 
				
			||||||
 | 
					      inbox_url
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  has_one :endpoints, serializer: EndpointsSerializer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  has_one :icon,  serializer: ImageSerializer, if: :avatar_exists?
 | 
					  has_one :icon,  serializer: ImageSerializer, if: :avatar_exists?
 | 
				
			||||||
  has_one :image, serializer: ImageSerializer, if: :header_exists?
 | 
					  has_one :image, serializer: ImageSerializer, if: :header_exists?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,8 +63,8 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer
 | 
				
			||||||
    account_outbox_url(object)
 | 
					    account_outbox_url(object)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def shared_inbox
 | 
					  def endpoints
 | 
				
			||||||
    inbox_url
 | 
					    object
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def preferred_username
 | 
					  def preferred_username
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,7 +6,7 @@ class ActivityPub::ProcessAccountService < BaseService
 | 
				
			||||||
  # Should be called with confirmed valid JSON
 | 
					  # Should be called with confirmed valid JSON
 | 
				
			||||||
  # and WebFinger-resolved username and domain
 | 
					  # and WebFinger-resolved username and domain
 | 
				
			||||||
  def call(username, domain, json)
 | 
					  def call(username, domain, json)
 | 
				
			||||||
    return unless json['inbox'].present?
 | 
					    return if json['inbox'].blank?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @json     = json
 | 
					    @json     = json
 | 
				
			||||||
    @uri      = @json['id']
 | 
					    @uri      = @json['id']
 | 
				
			||||||
| 
						 | 
					@ -42,9 +42,9 @@ class ActivityPub::ProcessAccountService < BaseService
 | 
				
			||||||
    @account.protocol            = :activitypub
 | 
					    @account.protocol            = :activitypub
 | 
				
			||||||
    @account.inbox_url           = @json['inbox'] || ''
 | 
					    @account.inbox_url           = @json['inbox'] || ''
 | 
				
			||||||
    @account.outbox_url          = @json['outbox'] || ''
 | 
					    @account.outbox_url          = @json['outbox'] || ''
 | 
				
			||||||
    @account.shared_inbox_url    = @json['sharedInbox'] || ''
 | 
					    @account.shared_inbox_url    = (@json['endpoints'].is_a?(Hash) ? @json['endpoints']['sharedInbox'] : @json['sharedInbox']) || ''
 | 
				
			||||||
    @account.followers_url       = @json['followers'] || ''
 | 
					    @account.followers_url       = @json['followers'] || ''
 | 
				
			||||||
    @account.url                 = @json['url'] || @uri
 | 
					    @account.url                 = url || @uri
 | 
				
			||||||
    @account.display_name        = @json['name'] || ''
 | 
					    @account.display_name        = @json['name'] || ''
 | 
				
			||||||
    @account.note                = @json['summary'] || ''
 | 
					    @account.note                = @json['summary'] || ''
 | 
				
			||||||
    @account.avatar_remote_url   = image_url('icon')
 | 
					    @account.avatar_remote_url   = image_url('icon')
 | 
				
			||||||
| 
						 | 
					@ -62,7 +62,7 @@ class ActivityPub::ProcessAccountService < BaseService
 | 
				
			||||||
    value = first_of_value(@json[key])
 | 
					    value = first_of_value(@json[key])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return if value.nil?
 | 
					    return if value.nil?
 | 
				
			||||||
    return @json[key]['url'] if @json[key].is_a?(Hash)
 | 
					    return value['url'] if value.is_a?(Hash)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    image = fetch_resource(value)
 | 
					    image = fetch_resource(value)
 | 
				
			||||||
    image['url'] if image
 | 
					    image['url'] if image
 | 
				
			||||||
| 
						 | 
					@ -78,6 +78,16 @@ class ActivityPub::ProcessAccountService < BaseService
 | 
				
			||||||
    key['publicKeyPem'] if key
 | 
					    key['publicKeyPem'] if key
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def url
 | 
				
			||||||
 | 
					    return if @json['url'].blank?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    value = first_of_value(@json['url'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return value if value.is_a?(String)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    value['href']
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def auto_suspend?
 | 
					  def auto_suspend?
 | 
				
			||||||
    domain_block && domain_block.suspend?
 | 
					    domain_block && domain_block.suspend?
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue