69 lines
		
	
	
	
		
			1.6 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			69 lines
		
	
	
	
		
			1.6 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
# frozen_string_literal: true
 | 
						|
 | 
						|
class ActivityPub::Dereferencer
 | 
						|
  include JsonLdHelper
 | 
						|
 | 
						|
  def initialize(uri, permitted_origin: nil, signature_account: nil)
 | 
						|
    @uri               = uri
 | 
						|
    @permitted_origin  = permitted_origin
 | 
						|
    @signature_account = signature_account
 | 
						|
  end
 | 
						|
 | 
						|
  def object
 | 
						|
    @object ||= fetch_object!
 | 
						|
  end
 | 
						|
 | 
						|
  private
 | 
						|
 | 
						|
  def bear_cap?
 | 
						|
    @uri.start_with?('bear:')
 | 
						|
  end
 | 
						|
 | 
						|
  def fetch_object!
 | 
						|
    if bear_cap?
 | 
						|
      fetch_with_token!
 | 
						|
    else
 | 
						|
      fetch_with_signature!
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  def fetch_with_token!
 | 
						|
    perform_request(bear_cap['u'], headers: { 'Authorization' => "Bearer #{bear_cap['t']}" })
 | 
						|
  end
 | 
						|
 | 
						|
  def fetch_with_signature!
 | 
						|
    perform_request(@uri)
 | 
						|
  end
 | 
						|
 | 
						|
  def bear_cap
 | 
						|
    @bear_cap ||= Addressable::URI.parse(@uri).query_values
 | 
						|
  end
 | 
						|
 | 
						|
  def perform_request(uri, headers: nil)
 | 
						|
    return if invalid_origin?(uri)
 | 
						|
 | 
						|
    req = Request.new(:get, uri)
 | 
						|
 | 
						|
    req.add_headers('Accept' => 'application/activity+json, application/ld+json')
 | 
						|
    req.add_headers(headers) if headers
 | 
						|
    req.on_behalf_of(@signature_account) if @signature_account
 | 
						|
 | 
						|
    req.perform do |res|
 | 
						|
      if res.code == 200
 | 
						|
        json = body_to_json(res.body_with_limit)
 | 
						|
        json if json.present? && json['id'] == uri
 | 
						|
      else
 | 
						|
        raise Mastodon::UnexpectedResponseError, res unless response_successful?(res) || response_error_unsalvageable?(res)
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  def invalid_origin?(uri)
 | 
						|
    return true if unsupported_uri_scheme?(uri)
 | 
						|
 | 
						|
    needle   = Addressable::URI.parse(uri).host
 | 
						|
    haystack = Addressable::URI.parse(@permitted_origin).host
 | 
						|
 | 
						|
    !haystack.casecmp(needle).zero?
 | 
						|
  end
 | 
						|
end
 |