From 772fef7d30271d1451e11f4037ec7fdfbd44ccdd Mon Sep 17 00:00:00 2001 From: Fire Demon Date: Mon, 17 Aug 2020 13:06:21 -0500 Subject: [Federation] Allow passive federation from allowlisted servers --- app/lib/activitypub/activity/announce.rb | 14 +------- app/lib/activitypub/activity/create.rb | 60 +++++++++++++------------------- app/lib/activitypub/activity/delete.rb | 7 ++-- 3 files changed, 28 insertions(+), 53 deletions(-) diff --git a/app/lib/activitypub/activity/announce.rb b/app/lib/activitypub/activity/announce.rb index 9e108985a..c636d233d 100644 --- a/app/lib/activitypub/activity/announce.rb +++ b/app/lib/activitypub/activity/announce.rb @@ -2,7 +2,7 @@ class ActivityPub::Activity::Announce < ActivityPub::Activity def perform - return reject_payload! if delete_arrived_first?(@json['id']) || !related_to_local_activity? + return reject_payload! if delete_arrived_first?(@json['id']) RedisLock.acquire(lock_options) do |lock| if lock.acquired? @@ -50,18 +50,6 @@ class ActivityPub::Activity::Announce < ActivityPub::Activity status.account_id == @account.id || status.distributable? end - def related_to_local_activity? - followed_by_local_accounts? || requested_through_relay? || reblog_of_local_status? - end - - def requested_through_relay? - super || Relay.find_by(inbox_url: @account.inbox_url)&.enabled? - end - - def reblog_of_local_status? - status_from_uri(object_uri)&.account&.local? - end - def lock_options { redis: Redis.current, key: "announce:#{@object['id']}" } end diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 91f0ab146..d37203c40 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +# rubocop:disable Metrics/ClassLength class ActivityPub::Activity::Create < ActivityPub::Activity include ImgProxyHelper @@ -17,7 +18,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity private def create_encrypted_message - return reject_payload! if invalid_origin?(@object['id']) || @options[:delivered_to_account_id].blank? + return reject_payload! if invalid_origin?(object_uri) || @options[:delivered_to_account_id].blank? target_account = Account.find(@options[:delivered_to_account_id]) target_device = target_account.devices.find_by(device_id: @object.dig('to', 'deviceId')) @@ -45,7 +46,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity end def create_status - return reject_payload! if unsupported_object_type? || invalid_origin?(@object['id']) || Tombstone.exists?(uri: @object['id']) || !related_to_local_activity? + return reject_payload! if unsupported_object_type? || invalid_origin?(object_uri) || Tombstone.exists?(uri: object_uri) RedisLock.acquire(lock_options) do |lock| if lock.acquired? @@ -74,6 +75,10 @@ class ActivityPub::Activity::Create < ActivityPub::Activity @object['cc'] || @json['cc'] end + def object_uri + @object['id'] || super + end + def process_status @tags = [] @mentions = [] @@ -116,8 +121,8 @@ class ActivityPub::Activity::Create < ActivityPub::Activity def process_status_params @params = begin { - uri: @object['id'], - url: object_url || @object['id'], + uri: object_uri, + url: object_url || object_uri, account: @account, text: text_from_content || '', language: detected_language, @@ -356,7 +361,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity RedisLock.acquire(poll_lock_options) do |lock| if lock.acquired? already_voted = poll.votes.where(account: @account).exists? - poll.votes.create!(account: @account, choice: poll.options.index(@object['name']), uri: @object['id']) + poll.votes.create!(account: @account, choice: poll.options.index(@object['name']), uri: object_uri) else raise Mastodon::RaceConditionError end @@ -373,7 +378,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity end def fetch_replies(status) - FetchReplyWorker.perform_async(@object['root']) unless @object['root'].blank? || [@object['id'], @object['url']].include?(@object['root']) || status_from_uri(@object['root']) + FetchReplyWorker.perform_async(@object['root']) unless @object['root'].blank? || [object_uri, @object['url']].include?(@object['root']) || status_from_uri(@object['root']) collection = @object['replies'] return if collection.nil? @@ -387,16 +392,23 @@ class ActivityPub::Activity::Create < ActivityPub::Activity def conversation_from_uri(uri) return nil if uri.nil? + conversation = OStatus::TagManager.instance.local_id?(uri) ? Conversation.find_by(id: OStatus::TagManager.instance.unique_tag_to_local_id(uri, 'Conversation')) : nil begin conversation = Conversation.find_by(uri: uri) if conversation.blank? if @object['inReplyTo'].blank? && replied_to_status.blank? + params = { + uri: uri, + root: object_uri, + account: @account, + public: %i(public unlisted).include?(visibility_from_audience), + }.freeze if conversation.blank? - conversation = Conversation.create!(uri: uri, root: @object['id'], account: @account, public: %i(public unlisted).include?(visibility_from_audience)) + conversation = Conversation.create!(params) elsif conversation.root.blank? - conversation.update!(root: @object['id'], account: @account, public: %i(public unlisted).include?(visibility_from_audience)) + conversation.update!(params) end elsif conversation.blank? conversation = Conversation.create!(uri: uri, account_id: nil, public: false) @@ -434,7 +446,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity def replied_to_status return @replied_to_status if defined?(@replied_to_status) - if in_reply_to_uri.blank? + if in_reply_to_uri.blank? || in_reply_to_uri == object_uri @replied_to_status = nil else @replied_to_status = status_from_uri(in_reply_to_uri) @@ -448,7 +460,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity end def text_from_content - return Formatter.instance.linkify([[text_from_name, text_from_summary.presence].compact.join("\n\n"), object_url || @object['id']].join(' ')) if converted_object_type? + return Formatter.instance.linkify([[text_from_name, text_from_summary.presence].compact.join("\n\n"), object_url || object_uri].join(' ')) if converted_object_type? if @object['content'].present? @object['type'] == 'Article' ? Formatter.instance.format_article(@object['content']) : @object['content'] @@ -536,35 +548,12 @@ class ActivityPub::Activity::Create < ActivityPub::Activity @skip_download ||= DomainBlock.reject_media?(@account.domain) end - def reply_to_local? - !replied_to_status.nil? && replied_to_status.account.local? - end - - def related_to_local_activity? - fetch? || followed_by_local_accounts? || requested_through_relay? || - responds_to_followed_account? || addresses_local_accounts? - end - - def responds_to_followed_account? - !replied_to_status.nil? && (replied_to_status.account.local? || replied_to_status.account.passive_relationships.exists?) - end - - def addresses_local_accounts? - return true if @options[:delivered_to_account_id] - - local_usernames = (as_array(audience_to) + as_array(audience_cc)).uniq.select { |uri| ActivityPub::TagManager.instance.local_uri?(uri) }.map { |uri| ActivityPub::TagManager.instance.uri_to_local_id(uri, :username) } - - return false if local_usernames.empty? - - Account.local.where(username: local_usernames).exists? - end - def check_for_spam SpamCheck.perform(@status) end def forward_for_reply - return unless @json['signature'].present? && reply_to_local? + return if @json['signature'].blank? || replied_to_status.blank? ActivityPub::RawDistributionWorker.perform_async(Oj.dump(@json), replied_to_status.account_id, [@account.preferred_inbox_url]) end @@ -582,10 +571,11 @@ class ActivityPub::Activity::Create < ActivityPub::Activity end def lock_options - { redis: Redis.current, key: "create:#{@object['id']}" } + { redis: Redis.current, key: "create:#{object_uri}" } end def poll_lock_options { redis: Redis.current, key: "vote:#{replied_to_status.poll_id}:#{@account.id}" } end end +# rubocop:enable Metrics/ClassLength diff --git a/app/lib/activitypub/activity/delete.rb b/app/lib/activitypub/activity/delete.rb index dc9ff580c..1420c6aff 100644 --- a/app/lib/activitypub/activity/delete.rb +++ b/app/lib/activitypub/activity/delete.rb @@ -51,15 +51,12 @@ class ActivityPub::Activity::Delete < ActivityPub::Activity def replied_to_status return @replied_to_status if defined?(@replied_to_status) - @replied_to_status = @status.thread - end - def reply_to_local? - !replied_to_status.nil? && replied_to_status.account.local? + @replied_to_status = @status.thread end def forward_for_reply - return unless @json['signature'].present? && reply_to_local? + return if @json['signature'].blank? || replied_to_status.blank? inboxes = replied_to_status.account.followers.inboxes - [@account.preferred_inbox_url] -- cgit