Add option to include resolved DNS records when blacklisting e-mail domains in admin UI (#13254)

* Add shortcuts to blacklist a user's e-mail domain in admin UI

* Add option to blacklist resolved MX and IP records for e-mail domains
This commit is contained in:
Eugen Rochko
2020-03-12 22:35:20 +01:00
committed by GitHub
parent f556f79b77
commit bea0bb39d6
9 changed files with 79 additions and 8 deletions

View File

@ -6,12 +6,12 @@ module Admin
def index
authorize :email_domain_block, :index?
@email_domain_blocks = EmailDomainBlock.page(params[:page])
@email_domain_blocks = EmailDomainBlock.where(parent_id: nil).includes(:children).order(id: :desc).page(params[:page])
end
def new
authorize :email_domain_block, :create?
@email_domain_block = EmailDomainBlock.new
@email_domain_block = EmailDomainBlock.new(domain: params[:_domain])
end
def create
@ -21,6 +21,28 @@ module Admin
if @email_domain_block.save
log_action :create, @email_domain_block
if @email_domain_block.with_dns_records?
hostnames = []
ips = []
Resolv::DNS.open do |dns|
dns.timeouts = 1
hostnames = dns.getresources(@email_domain_block.domain, Resolv::DNS::Resource::IN::MX).to_a.map { |e| e.exchange.to_s }
([@email_domain_block.domain] + hostnames).uniq.each do |hostname|
ips.concat(dns.getresources(hostname, Resolv::DNS::Resource::IN::A).to_a.map { |e| e.address.to_s })
ips.concat(dns.getresources(hostname, Resolv::DNS::Resource::IN::AAAA).to_a.map { |e| e.address.to_s })
end
end
(hostnames + ips).each do |hostname|
another_email_domain_block = EmailDomainBlock.new(domain: hostname, parent: @email_domain_block)
log_action :create, another_email_domain_block if another_email_domain_block.save
end
end
redirect_to admin_email_domain_blocks_path, notice: I18n.t('admin.email_domain_blocks.created_msg')
else
render :new
@ -41,7 +63,7 @@ module Admin
end
def resource_params
params.require(:email_domain_block).permit(:domain)
params.require(:email_domain_block).permit(:domain, :with_dns_records)
end
end
end

View File

@ -7,13 +7,27 @@
# domain :string default(""), not null
# created_at :datetime not null
# updated_at :datetime not null
# parent_id :bigint(8)
#
class EmailDomainBlock < ApplicationRecord
include DomainNormalizable
belongs_to :parent, class_name: 'EmailDomainBlock', optional: true
has_many :children, class_name: 'EmailDomainBlock', foreign_key: :parent_id, inverse_of: :parent, dependent: :destroy
validates :domain, presence: true, uniqueness: true, domain: true
def with_dns_records=(val)
@with_dns_records = ActiveModel::Type::Boolean.new.cast(val)
end
def with_dns_records?
@with_dns_records
end
alias with_dns_records with_dns_records?
def self.block?(email)
_, domain = email.split('@', 2)

View File

@ -96,10 +96,17 @@
= table_link_to 'angle-double-down', t('admin.accounts.demote'), demote_admin_account_role_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') } if can?(:demote, @account.user)
%tr
%th= t('admin.accounts.email')
%td= @account.user_email
%th{ rowspan: can?(:create, :email_domain_block) ? 3 : 2 }= t('admin.accounts.email')
%td{ rowspan: can?(:create, :email_domain_block) ? 3 : 2 }= @account.user_email
%td= table_link_to 'edit', t('admin.accounts.change_email.label'), admin_account_change_email_path(@account.id) if can?(:change_email, @account.user)
%tr
%td= table_link_to 'search', t('admin.accounts.search_same_email_domain'), admin_accounts_path(email: "%@#{@account.user_email.split('@').last}")
- if can?(:create, :email_domain_block)
%tr
%td= table_link_to 'ban', t('admin.accounts.add_email_domain_block'), new_admin_email_domain_block_path(_domain: @account.user_email.split('@').last)
- if @account.user_unconfirmed_email.present?
%tr
%th= t('admin.accounts.unconfirmed_email')
@ -204,7 +211,7 @@
= link_to t('admin.accounts.perform_full_suspension'), new_admin_account_action_path(@account.id, type: 'suspend'), class: 'button button--destructive' if can?(:suspend, @account)
- unless @account.local?
- if DomainBlock.where(domain: @account.domain).exists?
- if DomainBlock.rule_for(@account.domain)
= link_to t('admin.domain_blocks.view'), admin_instance_path(@account.domain), class: 'button'
- else
= link_to t('admin.domain_blocks.add_new'), new_admin_domain_block_path(_domain: @account.domain), class: 'button button--destructive'

View File

@ -3,3 +3,13 @@
%samp= email_domain_block.domain
%td
= table_link_to 'trash', t('admin.email_domain_blocks.delete'), admin_email_domain_block_path(email_domain_block), method: :delete
- email_domain_block.children.each do |child_email_domain_block|
%tr
%td
%samp= child_email_domain_block.domain
%span.muted-hint
= surround '(', ')' do
= t('admin.email_domain_blocks.from_html', domain: content_tag(:samp, email_domain_block.domain))
%td
= table_link_to 'trash', t('admin.email_domain_blocks.delete'), admin_email_domain_block_path(child_email_domain_block), method: :delete

View File

@ -5,7 +5,10 @@
= render 'shared/error_messages', object: @email_domain_block
.fields-group
= f.input :domain, wrapper: :with_label, label: t('admin.email_domain_blocks.domain')
= f.input :domain, wrapper: :with_block_label, label: t('admin.email_domain_blocks.domain')
.fields-group
= f.input :with_dns_records, as: :boolean, wrapper: :with_label
.actions
= f.button :button, t('.create'), type: :submit