From 2da143ab9019e70db46ebdb098e2424966084cbe Mon Sep 17 00:00:00 2001 From: Eashwar Ranganathan Date: Tue, 29 Apr 2025 22:16:59 -0400 Subject: [PATCH] Make tootctl aware of new 'require approval' for email domains --- AUTHORS.md | 2 +- lib/mastodon/cli/email_domain_blocks.rb | 39 +++++++++++++-- .../mastodon/cli/email_domain_blocks_spec.rb | 48 +++++++++++++++++-- spec/support/command_line_helpers.rb | 6 +++ 4 files changed, 86 insertions(+), 9 deletions(-) diff --git a/AUTHORS.md b/AUTHORS.md index 78cc37a17b..5d243ed43b 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -538,7 +538,7 @@ and provided thanks to the work of the following contributors: * [Drew Schuster](mailto:dtschust@gmail.com) * [Dryusdan](mailto:dryusdan@dryusdan.fr) * [Eai](mailto:eai@mizle.net) -* [Eashwar Ranganathan](mailto:eranganathan@lyft.com) +* [Eashwar Ranganathan](mailto:eashwar@eashwar.com) * [Ed Knutson](mailto:knutsoned@gmail.com) * [Elizabeth Martín Campos](mailto:me@elizabeth.sh) * [Elizabeth Myers](mailto:elizabeth@interlinked.me) diff --git a/lib/mastodon/cli/email_domain_blocks.rb b/lib/mastodon/cli/email_domain_blocks.rb index 0cc9ccb705..e39579362b 100644 --- a/lib/mastodon/cli/email_domain_blocks.rb +++ b/lib/mastodon/cli/email_domain_blocks.rb @@ -5,10 +5,36 @@ require_relative 'base' module Mastodon::CLI class EmailDomainBlocks < Base + option :only_blocked, type: boolean, defaut: false + option :only_with_approval, type: boolean, default: false desc 'list', 'List blocked e-mail domains' + long_desc <<-LONG_DESC + By default this command lists all domains in the email domain block list + and their associated MX records (if included). + + If the --only-blocked option is provided, this command will list only email + domains that are fully blocked from signup. + + If the --only-with-approval option is provided, this command will list only + email domains that are allowed to be used but require manual approval. + + The --only-blocked and --only-with-approval options are mutually exclusive. + LONG_DESC def list - EmailDomainBlock.parents.find_each do |parent| - say(parent.domain.to_s, :white) + if options[:only_blocked] && options[:only_with_approval] + fail_with_message 'Cannot specify both --only-blocked and --only-with-approval' + end + + base_query = EmailDomainBlock.where(parent_id: nil) + + if options[:only_blocked] + base_query = base_query.where(allow_with_approval: false) + elsif options[:only_with_approval] + base_query = base_query.where(allow_with_approval: true) + end + + base_query.find_each do |entry| + say(entry.domain.to_s, :white) shell.indent do EmailDomainBlock.where(parent_id: parent.id).find_each do |child| @@ -19,6 +45,7 @@ module Mastodon::CLI end option :with_dns_records, type: :boolean + option :allow_with_approval, type: :boolean, defaut: false desc 'add DOMAIN...', 'Block e-mail domain(s)' long_desc <<-LONG_DESC Blocking an e-mail domain prevents users from signing up @@ -30,6 +57,9 @@ module Mastodon::CLI This can be helpful if you are blocking an e-mail server that has many different domains pointing to it as it allows you to essentially block it at the root. + + When the --allow-with-approval option is set, the email domains provided will + have to be manually approved for signup. LONG_DESC def add(*domains) fail_with_message 'No domain(s) given' if domains.empty? @@ -47,19 +77,18 @@ module Mastodon::CLI other_domains = [] other_domains = DomainResource.new(domain).mx if options[:with_dns_records] - email_domain_block = EmailDomainBlock.new(domain: domain, other_domains: other_domains) + email_domain_block = EmailDomainBlock.new(domain: domain, other_domains: other_domains, allow_with_approval: options[:allow_with_approval]) email_domain_block.save! processed += 1 (email_domain_block.other_domains || []).uniq.each do |hostname| - another_email_domain_block = EmailDomainBlock.new(domain: hostname, parent: email_domain_block) - if EmailDomainBlock.exists?(domain: hostname) say("#{hostname} is already blocked.", :yellow) skipped += 1 next end + another_email_domain_block = EmailDomainBlock.new(domain: hostname, parent: email_domain_block, allow_with_approval: options[:allow_with_approval]) another_email_domain_block.save! processed += 1 end diff --git a/spec/lib/mastodon/cli/email_domain_blocks_spec.rb b/spec/lib/mastodon/cli/email_domain_blocks_spec.rb index 6ce1a7c5f3..338fa38452 100644 --- a/spec/lib/mastodon/cli/email_domain_blocks_spec.rb +++ b/spec/lib/mastodon/cli/email_domain_blocks_spec.rb @@ -7,7 +7,6 @@ RSpec.describe Mastodon::CLI::EmailDomainBlocks do subject { cli.invoke(action, arguments, options) } let(:cli) { described_class.new } - let(:arguments) { [] } let(:options) { {} } it_behaves_like 'CLI Command' @@ -15,15 +14,58 @@ RSpec.describe Mastodon::CLI::EmailDomainBlocks do describe '#list' do let(:action) { :list } + context 'with both --only-blocked and --only-with-approval' do + let(:arguments) { ['--only-blocked', '--only-with-approval'] } + + it 'warns about usage and exits' do + expect { subject } + .to raise_error(Thor::Error, 'Cannot specify both --only-blocked and --only-with-approval') + end + end + context 'with email domain block records' do let!(:parent_block) { Fabricate(:email_domain_block) } let!(:child_block) { Fabricate(:email_domain_block, parent: parent_block) } + let!(:parent_allow_block) { Fabricate(:email_domain_block, allow_with_approval: true)} + let!(:child_allow_block) { Fabricate(:email_domain_block, parent: parent_allow_block, allow_with_approval: true)} + + it 'lists all the blocks by default' do + let(:arguments) { [] } - it 'lists the blocks' do expect { subject } .to output_results( parent_block.domain, - child_block.domain + child_block.domain, + parent_allow_block.domain, + child_allow_block.domain, + ) + end + + it 'lists only blocked domains with --only-blocked' do + let(:arguments) { ['--only-blocked'] } + + expect { subject } + .to output_results( + parent_block.domain, + child_block.domain, + ) + .and not_output_results( + parent_allow_block.domain, + child_allow_block.domain, + ) + end + + it 'lists only manually approvable domains with --only-with-approval' do + let(:arguments) { ['--only-with-approval'] } + + expect { subject } + .to output_results( + parent_allow_block.domain, + child_allow_block.domain, + ) + .and not_output_results( + parent_block.domain, + child_block.domain, ) end end diff --git a/spec/support/command_line_helpers.rb b/spec/support/command_line_helpers.rb index 09b2b70ba1..430dd5e3ce 100644 --- a/spec/support/command_line_helpers.rb +++ b/spec/support/command_line_helpers.rb @@ -6,4 +6,10 @@ module CommandLineHelpers include(*) ).to_stdout end + + def not_output_results(*args) + output( + not_include(*args) + ).to_stdout + end end