From 85abad2a86688870dc7ecc8a6f321be56949da2a Mon Sep 17 00:00:00 2001 From: Claire Date: Fri, 8 Dec 2023 16:40:39 +0100 Subject: Fix already-followed accounts in follow imports contributing to max follows limit Fixes #28232 --- app/models/form/import.rb | 25 ++++++++++++++++++++----- spec/models/form/import_spec.rb | 22 +++++++++++++++++++--- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/app/models/form/import.rb b/app/models/form/import.rb index 29a2975c7be..b59d535fe3c 100644 --- a/app/models/form/import.rb +++ b/app/models/form/import.rb @@ -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 diff --git a/spec/models/form/import_spec.rb b/spec/models/form/import_spec.rb index 872697485ed..bb95cf97809 100644 --- a/spec/models/form/import_spec.rb +++ b/spec/models/form/import_spec.rb @@ -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 -- cgit v1.2.3