about summary refs log tree commit diff
path: root/app/lib/activitypub/dereferencer.rb
diff options
context:
space:
mode:
authorThibaut Girka <thib@sitedethib.com>2020-08-30 16:13:08 +0200
committerThibaut Girka <thib@sitedethib.com>2020-08-30 16:13:08 +0200
commit8c3c27bf063d648823da39a206be3efd285611ad (patch)
treec78c0bed2bab5ed64a7dfd546b91b21600947112 /app/lib/activitypub/dereferencer.rb
parent30632adf9eda6d83a9b4269f23f11ced5e09cd93 (diff)
parent52157fdcba0837c782edbfd240be07cabc551de9 (diff)
Merge branch 'master' into glitch-soc/merge-upstream
Conflicts:
- `app/controllers/accounts_controller.rb`:
  Upstream change too close to a glitch-soc change related to
  instance-local toots. Merged upstream changes.
- `app/services/fan_out_on_write_service.rb`:
  Minor conflict due to glitch-soc's handling of Direct Messages,
  merged upstream changes.
- `yarn.lock`:
  Not really a conflict, caused by glitch-soc-only dependencies
  being textually too close to updated upstream dependencies.
  Merged 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