about summary refs log tree commit diff
path: root/app/lib/activitypub/dereferencer.rb
diff options
context:
space:
mode:
authorThibG <thib@sitedethib.com>2020-08-30 18:34:51 +0200
committerGitHub <noreply@github.com>2020-08-30 18:34:51 +0200
commitf715e8b51612820a18fa307e4465eb0c1a088f86 (patch)
tree8137b48a716e05424ca544210d86e91818085ba7 /app/lib/activitypub/dereferencer.rb
parent30632adf9eda6d83a9b4269f23f11ced5e09cd93 (diff)
parenta68ec50e4e38898e88a7dcc33bd0032adc946dda (diff)
Merge pull request #1411 from ThibG/glitch-soc/merge-upstream
Merge upstream changes
Diffstat (limited to 'app/lib/activitypub/dereferencer.rb')
-rw-r--r--app/lib/activitypub/dereferencer.rb69
1 files changed, 69 insertions, 0 deletions
diff --git a/app/lib/activitypub/dereferencer.rb b/app/lib/activitypub/dereferencer.rb
new file mode 100644
index 000000000..bea69608f
--- /dev/null
+++ b/app/lib/activitypub/dereferencer.rb
@@ -0,0 +1,69 @@
+# 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