Add API parameter to safeguard unexpect mentions in new posts (#18350)

This commit is contained in:
Claire 2023-02-13 16:36:29 +01:00 committed by GitHub
parent c84f38abc4
commit d6930b3847
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 94 additions and 12 deletions

View file

@ -6,6 +6,15 @@ class PostStatusService < BaseService
MIN_SCHEDULE_OFFSET = 5.minutes.freeze
class UnexpectedMentionsError < StandardError
attr_reader :accounts
def initialize(message, accounts)
super(message)
@accounts = accounts
end
end
# Post a text status update, fetch and notify remote users mentioned
# @param [Account] account Account from which to post
# @param [Hash] options
@ -21,6 +30,7 @@ class PostStatusService < BaseService
# @option [Doorkeeper::Application] :application
# @option [String] :idempotency Optional idempotency key
# @option [Boolean] :with_rate_limit
# @option [Enumerable] :allowed_mentions Optional array of expected mentioned account IDs, raises `UnexpectedMentionsError` if unexpected accounts end up in mentions
# @return [Status]
def call(account, options = {})
@account = account
@ -63,14 +73,27 @@ class PostStatusService < BaseService
end
def process_status!
@status = @account.statuses.new(status_attributes)
process_mentions_service.call(@status, save_records: false)
safeguard_mentions!(@status)
# The following transaction block is needed to wrap the UPDATEs to
# the media attachments when the status is created
ApplicationRecord.transaction do
@status = @account.statuses.create!(status_attributes)
@status.save!
end
end
def safeguard_mentions!(status)
return if @options[:allowed_mentions].nil?
expected_account_ids = @options[:allowed_mentions].map(&:to_i)
unexpected_accounts = status.mentions.map(&:account).to_a.reject { |mentioned_account| expected_account_ids.include?(mentioned_account.id) }
return if unexpected_accounts.empty?
raise UnexpectedMentionsError.new('Post would be sent to unexpected accounts', unexpected_accounts)
end
def schedule_status!
status_for_validation = @account.statuses.build(status_attributes)
@ -93,7 +116,6 @@ class PostStatusService < BaseService
def postprocess_status!
process_hashtags_service.call(@status)
process_mentions_service.call(@status)
Trends.tags.register(@status)
LinkCrawlWorker.perform_async(@status.id)
DistributionWorker.perform_async(@status.id)