move autoreject check to own module & check for reject before pulling resources

staging
multiple creatures 2019-07-22 21:12:54 -05:00
parent 86f29a68fb
commit 2822fbc443
5 changed files with 75 additions and 34 deletions

View File

@ -0,0 +1,53 @@
module AutorejectHelper
def should_reject?(uri = nil)
if @json
oid = @json['id']
return true if ENV.fetch('REJECT_IF_ID_STARTS_WITH', '').split.any? { |r| oid.start_with?(r) }
return true if ENV.fetch('REJECT_IF_ID_CONTAINS', '').split.any? { |r| r.in?(oid) }
end
if uri.nil?
if @object
uri = object_uri.start_with?('http') ? object_uri : @object['url']
elsif @json
uri = @json['id']
end
end
return if uri.nil?
domain = uri.scan(/[\w\-]+\.[\w\-]+(?:\.[\w\-]+)*/).first
blocks = DomainBlock.suspend
return true if blocks.where(domain: domain).or(blocks.where('domain LIKE ?', "%.#{domain}")).exists?
if @object
context = @object['@context']
elsif @json
context = @json['@context']
else
return
end
return unless context
if context.is_a?(Array)
inline_context = context.find { |item| item.is_a?(Hash) }
if inline_context
keys = inline_context.keys
return true if ENV.fetch('REJECT_IF_CONTEXT_EQUALS', '').split.any? { |r| r.in?(keys) }
return true if ENV.fetch('REJECT_IF_CONTEXT_STARTS_WITH', '').split.any? { |r| keys.any? { |k| k.start_with?(r) } }
return true if ENV.fetch('REJECT_IF_CONTEXT_CONTAINS', '').split.any? { |r| keys.any? { |k| r.in?(k) } }
end
end
false
end
def autoreject?(uri = nil)
if (@options && @options[:imported]) || should_reject?(uri)
Rails.logger.info("Auto-rejected #{@json['type']} activity #{@json['id']}")
return true
end
false
end
end

View File

@ -2,6 +2,7 @@
class ActivityPub::Activity
include JsonLdHelper
include AutorejectHelper
include Redisable
SUPPORTED_TYPES = %w(Note Question).freeze
@ -185,37 +186,4 @@ class ActivityPub::Activity
Rails.logger.info("Rejected #{@json['type']} activity #{@json['id']} from #{@account.uri}#{@options[:relayed_through_account] && "via #{@options[:relayed_through_account].uri}"}")
nil
end
def should_reject?
return unless @object
oid = @json['id']
return true if ENV.fetch('REJECT_IF_ID_STARTS_WITH', '').split.any? { |r| oid.start_with?(r) }
return true if ENV.fetch('REJECT_IF_ID_CONTAINS', '').split.any? { |r| r.in?(oid) }
url = object_uri.start_with?('http') ? object_uri : @object['url']
return if url.nil?
domain = url.scan(/[\w\-]+\.[\w\-]+(?:\.[\w\-]+)*/).first
blocks = DomainBlock.suspend
return true if blocks.where(domain: domain).or(blocks.where('domain LIKE ?', "%.#{domain}")).exists?
if @object['@context'].is_a?(Array)
inline_context = @object['@context'].find { |item| item.is_a?(Hash) }
if inline_context
keys = inline_context.keys
return true if ENV.fetch('REJECT_IF_CONTEXT_EQUALS', '').split.any? { |r| r.in?(keys) }
return true if ENV.fetch('REJECT_IF_CONTEXT_STARTS_WITH', '').split.any? { |r| keys.any? { |k| k.start_with?(r) } }
return true if ENV.fetch('REJECT_IF_CONTEXT_CONTAINS', '').split.any? { |r| keys.any? { |k| r.in?(k) } }
end
end
end
def autoreject?
if @options[:imported] || should_reject?
Rails.logger.info("Auto-rejected #{@json['type']} activity #{@json['id']}")
return true
end
false
end
end

View File

@ -2,6 +2,7 @@
class ActivityPub::FetchRemoteAccountService < BaseService
include JsonLdHelper
include AutorejectHelper
SUPPORTED_TYPES = %w(Application Group Organization Person Service).freeze
@ -9,12 +10,14 @@ class ActivityPub::FetchRemoteAccountService < BaseService
def call(uri, id: true, prefetched_body: nil, break_on_redirect: false, only_key: false)
return ActivityPub::TagManager.instance.uri_to_resource(uri, Account) if ActivityPub::TagManager.instance.local_uri?(uri)
return if autoreject?(uri)
@json = if prefetched_body.nil?
fetch_resource(uri, id)
else
body_to_json(prefetched_body, compare_id: id ? uri : nil)
end
return if autoreject?
return if !supported_context? || !expected_type? || (break_on_redirect && @json['movedTo'].present?)
@uri = @json['id']
@ -59,4 +62,8 @@ class ActivityPub::FetchRemoteAccountService < BaseService
def expected_type?
equals_or_includes_any?(@json['type'], SUPPORTED_TYPES)
end
def object_uri
nil
end
end

View File

@ -2,15 +2,19 @@
class ActivityPub::FetchRemoteStatusService < BaseService
include JsonLdHelper
include AutorejectHelper
# Should be called when uri has already been checked for locality
def call(uri, id: true, prefetched_body: nil, on_behalf_of: nil)
return if autoreject?(uri)
@json = if prefetched_body.nil?
fetch_resource(uri, id, on_behalf_of)
else
body_to_json(prefetched_body, compare_id: id ? uri : nil)
end
return if autoreject?
return unless supported_context? && expected_type?
return if actor_id.nil? || !trustworthy_attribution?(@json['id'], actor_id)
@ -49,4 +53,8 @@ class ActivityPub::FetchRemoteStatusService < BaseService
def needs_update(actor)
actor.possibly_stale?
end
def object_uri
nil
end
end

View File

@ -2,6 +2,7 @@
class ActivityPub::FetchRepliesService < BaseService
include JsonLdHelper
include AutorejectHelper
def call(parent_status, collection_or_uri, allow_synchronous_requests = true)
@account = parent_status.account
@ -44,6 +45,10 @@ class ActivityPub::FetchRepliesService < BaseService
# amplification attacks.
# Also limit to 5 fetched replies to limit potential for DoS.
@items.map { |item| value_or_id(item) }.reject { |uri| invalid_origin?(uri) }.take(5)
@items.map { |item| value_or_id(item) }.reject { |uri| autoreject?(uri) || invalid_origin?(uri) }.take(5)
end
def object_uri
nil
end
end