Fix already-followed accounts in follow imports contributing to max follows limit

Fixes #28232
This commit is contained in:
Claire 2023-12-08 16:40:39 +01:00
parent 54db2006a9
commit 85abad2a86
2 changed files with 39 additions and 8 deletions

View File

@ -110,7 +110,7 @@ class Form::Import
when 'Languages'
field&.split(',')&.map(&:strip)&.presence
when 'Account address'
field.strip.gsub(/\A@/, '')
field.strip.delete_prefix('@')
when '#domain', '#uri', 'List name'
field.strip
else
@ -151,14 +151,29 @@ class Form::Import
errors.add(:data, I18n.t('imports.errors.over_rows_processing_limit', count: ROWS_PROCESSING_LIMIT)) if csv_row_count > ROWS_PROCESSING_LIMIT
if type.to_sym == :following
base_limit = FollowLimitValidator.limit_for_account(current_account)
limit = base_limit
limit -= current_account.following_count unless overwrite
errors.add(:data, I18n.t('users.follow_limit_reached', limit: base_limit)) if csv_row_count > limit
follows_limit = FollowLimitValidator.limit_for_account(current_account)
errors.add(:data, I18n.t('users.follow_limit_reached', limit: follows_limit)) if follows_count_after_import > follows_limit
end
rescue CSV::MalformedCSVError => e
errors.add(:data, I18n.t('imports.errors.invalid_csv_file', error: e.message))
rescue EmptyFileError
errors.add(:data, I18n.t('imports.errors.empty'))
end
def follows_count_after_import
return csv_row_count if overwrite
accts = parsed_rows.pluck('acct').compact.map(&:downcase).uniq.map do |acct|
username, domain = acct.split('@')
if domain.nil? || TagManager.instance.local_domain?(domain)
username.downcase
else
"#{username.downcase}@#{TagManager.instance.normalize_domain(domain)}"
end
end
current_follows = current_account.following.select(:username, :domain).map { |account| account.acct.downcase }
(current_follows + accts).uniq.size
end
end

View File

@ -67,17 +67,33 @@ RSpec.describe Form::Import do
end
end
context 'when importing more follows than allowed' do
context 'when the combination of existing follows and imported follows goes above the limit' do
let(:import_type) { 'following' }
let(:import_file) { 'imports.txt' }
before do
allow(FollowLimitValidator).to receive(:limit_for_account).with(account).and_return(1)
account.follow!(Fabricate(:account))
allow(FollowLimitValidator).to receive(:limit_for_account).with(account).and_return(2)
end
it 'has errors' do
subject.validate
expect(subject.errors[:data]).to include(I18n.t('users.follow_limit_reached', limit: 1))
expect(subject.errors[:data]).to include(I18n.t('users.follow_limit_reached', limit: 2))
end
end
context 'when the combination of existing follows and imported follows falls within the limit' do
let(:import_type) { 'following' }
let(:import_file) { 'imports.txt' }
before do
account.follow!(Fabricate(:account, username: 'user', domain: 'example.com'))
allow(FollowLimitValidator).to receive(:limit_for_account).with(account).and_return(2)
end
it 'is valid' do
subject.validate
expect(subject).to be_valid
end
end