123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- # frozen_string_literal: true
- require 'concurrent'
- require_relative '../../config/boot'
- require_relative '../../config/environment'
- require_relative 'cli_helper'
- module Mastodon
- class EmailDomainBlocksCLI < Thor
- include CLIHelper
- def self.exit_on_failure?
- true
- end
- desc 'list', 'List blocked e-mail domains'
- def list
- EmailDomainBlock.where(parent_id: nil).order(id: 'DESC').find_each do |entry|
- say(entry.domain.to_s, :white)
- EmailDomainBlock.where(parent_id: entry.id).order(id: 'DESC').find_each do |child|
- say(" #{child.domain}", :cyan)
- end
- end
- end
- option :with_dns_records, type: :boolean
- desc 'add DOMAIN...', 'Block e-mail domain(s)'
- long_desc <<-LONG_DESC
- Blocking an e-mail domain prevents users from signing up
- with e-mail addresses from that domain. You can provide one or
- multiple domains to the command.
- When the --with-dns-records option is given, an attempt to resolve the
- given domains' MX records will be made and the results will also be blocked.
- 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.
- LONG_DESC
- def add(*domains)
- if domains.empty?
- say('No domain(s) given', :red)
- exit(1)
- end
- skipped = 0
- processed = 0
- domains.each do |domain|
- if EmailDomainBlock.where(domain: domain).exists?
- say("#{domain} is already blocked.", :yellow)
- skipped += 1
- next
- end
- other_domains = []
- if options[:with_dns_records]
- Resolv::DNS.open do |dns|
- dns.timeouts = 5
- other_domains = dns.getresources(@email_domain_block.domain, Resolv::DNS::Resource::IN::MX).to_a
- end
- end
- email_domain_block = EmailDomainBlock.new(domain: domain, other_domains: other_domains)
- 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.where(domain: hostname).exists?
- say("#{hostname} is already blocked.", :yellow)
- skipped += 1
- next
- end
- another_email_domain_block.save!
- processed += 1
- end
- end
- say("Added #{processed}, skipped #{skipped}", color(processed, 0))
- end
- desc 'remove DOMAIN...', 'Remove e-mail domain blocks'
- def remove(*domains)
- if domains.empty?
- say('No domain(s) given', :red)
- exit(1)
- end
- skipped = 0
- processed = 0
- failed = 0
- domains.each do |domain|
- entry = EmailDomainBlock.find_by(domain: domain)
- if entry.nil?
- say("#{domain} is not yet blocked.", :yellow)
- skipped += 1
- next
- end
- children_count = EmailDomainBlock.where(parent_id: entry.id).count
- result = entry.destroy
- if result
- processed += children_count + 1
- else
- say("#{domain} could not be unblocked.", :red)
- failed += 1
- end
- end
- say("Removed #{processed}, skipped #{skipped}, failed #{failed}", color(processed, failed))
- end
- private
- def color(processed, failed)
- if !processed.zero? && failed.zero?
- :green
- elsif failed.zero?
- :yellow
- else
- :red
- end
- end
- end
- end
|