You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

69 lines
1.6 KiB

  1. # frozen_string_literal: true
  2. class ActivityPub::Dereferencer
  3. include JsonLdHelper
  4. def initialize(uri, permitted_origin: nil, signature_account: nil)
  5. @uri = uri
  6. @permitted_origin = permitted_origin
  7. @signature_account = signature_account
  8. end
  9. def object
  10. @object ||= fetch_object!
  11. end
  12. private
  13. def bear_cap?
  14. @uri.start_with?('bear:')
  15. end
  16. def fetch_object!
  17. if bear_cap?
  18. fetch_with_token!
  19. else
  20. fetch_with_signature!
  21. end
  22. end
  23. def fetch_with_token!
  24. perform_request(bear_cap['u'], headers: { 'Authorization' => "Bearer #{bear_cap['t']}" })
  25. end
  26. def fetch_with_signature!
  27. perform_request(@uri)
  28. end
  29. def bear_cap
  30. @bear_cap ||= Addressable::URI.parse(@uri).query_values
  31. end
  32. def perform_request(uri, headers: nil)
  33. return if invalid_origin?(uri)
  34. req = Request.new(:get, uri)
  35. req.add_headers('Accept' => 'application/activity+json, application/ld+json')
  36. req.add_headers(headers) if headers
  37. req.on_behalf_of(@signature_account) if @signature_account
  38. req.perform do |res|
  39. if res.code == 200
  40. json = body_to_json(res.body_with_limit)
  41. json if json.present? && json['id'] == uri
  42. else
  43. raise Mastodon::UnexpectedResponseError, res unless response_successful?(res) || response_error_unsalvageable?(res)
  44. end
  45. end
  46. end
  47. def invalid_origin?(uri)
  48. return true if unsupported_uri_scheme?(uri)
  49. needle = Addressable::URI.parse(uri).host
  50. haystack = Addressable::URI.parse(@permitted_origin).host
  51. !haystack.casecmp(needle).zero?
  52. end
  53. end