Change e-mail domain blocks to block IPs dynamically (#17635)
* Change e-mail domain blocks to block IPs dynamically * Update app/workers/scheduler/email_domain_block_refresh_scheduler.rb Co-authored-by: Yamagishi Kazutoshi <ykzts@desire.sh> * Update app/workers/scheduler/email_domain_block_refresh_scheduler.rb Co-authored-by: Yamagishi Kazutoshi <ykzts@desire.sh> Co-authored-by: Yamagishi Kazutoshi <ykzts@desire.sh>local
parent
91cc8d1e63
commit
a29a982eaa
20 changed files with 325 additions and 160 deletions
@ -0,0 +1,30 @@ |
||||
# frozen_string_literal: true |
||||
|
||||
class Form::EmailDomainBlockBatch |
||||
include ActiveModel::Model |
||||
include Authorization |
||||
include AccountableConcern |
||||
|
||||
attr_accessor :email_domain_block_ids, :action, :current_account |
||||
|
||||
def save |
||||
case action |
||||
when 'delete' |
||||
delete! |
||||
end |
||||
end |
||||
|
||||
private |
||||
|
||||
def email_domain_blocks |
||||
@email_domain_blocks ||= EmailDomainBlock.where(id: email_domain_block_ids) |
||||
end |
||||
|
||||
def delete! |
||||
email_domain_blocks.each do |email_domain_block| |
||||
authorize(email_domain_block, :destroy?) |
||||
email_domain_block.destroy! |
||||
log_action :destroy, email_domain_block |
||||
end |
||||
end |
||||
end |
@ -1,15 +1,14 @@ |
||||
%tr |
||||
%td |
||||
%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 |
||||
.batch-table__row |
||||
%label.batch-table__row__select.batch-table__row__select--aligned.batch-checkbox |
||||
= f.check_box :email_domain_block_ids, { multiple: true, include_hidden: false }, email_domain_block.id |
||||
.batch-table__row__content.pending-account |
||||
.pending-account__header |
||||
%samp= link_to email_domain_block.domain, admin_accounts_path(email: "%@#{email_domain_block.domain}") |
||||
|
||||
- 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 |
||||
%br/ |
||||
|
||||
- if email_domain_block.parent.present? |
||||
= t('admin.email_domain_blocks.resolved_through_html', domain: content_tag(:samp, email_domain_block.parent.domain)) |
||||
• |
||||
|
||||
= t('admin.email_domain_blocks.attempts_over_week', count: email_domain_block.history.reduce(0) { |sum, day| sum + day.accounts }) |
||||
|
@ -1,14 +1,38 @@ |
||||
- content_for :page_title do |
||||
= t('.title') |
||||
|
||||
- content_for :header_tags do |
||||
= javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous' |
||||
|
||||
= simple_form_for @email_domain_block, url: admin_email_domain_blocks_path do |f| |
||||
= render 'shared/error_messages', object: @email_domain_block |
||||
|
||||
.fields-group |
||||
= f.input :domain, wrapper: :with_block_label, label: t('admin.email_domain_blocks.domain') |
||||
= f.input :domain, wrapper: :with_block_label, label: t('admin.email_domain_blocks.domain'), input_html: { readonly: defined?(@resolved_records) } |
||||
|
||||
.fields-group |
||||
= f.input :with_dns_records, as: :boolean, wrapper: :with_label |
||||
- if defined?(@resolved_records) |
||||
%p.hint= t('admin.email_domain_blocks.resolved_dns_records_hint_html') |
||||
|
||||
.batch-table |
||||
.batch-table__toolbar |
||||
%label.batch-table__toolbar__select.batch-checkbox-all |
||||
= check_box_tag :batch_checkbox_all, nil, false |
||||
.batch-table__toolbar__actions |
||||
.batch-table__body |
||||
- @resolved_records.each do |record| |
||||
.batch-table__row |
||||
%label.batch-table__row__select.batch-table__row__select--aligned.batch-checkbox |
||||
= f.input_field :other_domains, as: :boolean, checked_value: record.exchange.to_s, include_hidden: false, multiple: true |
||||
.batch-table__row__content.pending-account |
||||
.pending-account__header |
||||
%samp= record.exchange.to_s |
||||
%br |
||||
= t('admin.email_domain_blocks.dns.types.mx') |
||||
|
||||
%hr.spacer/ |
||||
|
||||
.actions |
||||
= f.button :button, t('.create'), type: :submit |
||||
- if defined?(@resolved_records) |
||||
= f.button :button, t('.create'), type: :submit, name: :save |
||||
- else |
||||
= f.button :button, t('.resolve'), type: :submit, name: :resolve |
||||
|
@ -0,0 +1,30 @@ |
||||
# frozen_string_literal: true |
||||
|
||||
class Scheduler::EmailDomainBlockRefreshScheduler |
||||
include Sidekiq::Worker |
||||
include Redisable |
||||
|
||||
sidekiq_options retry: 0 |
||||
|
||||
def perform |
||||
Resolv::DNS.open do |dns| |
||||
dns.timeouts = 5 |
||||
|
||||
EmailDomainBlock.find_each do |email_domain_block| |
||||
ips = begin |
||||
if ip?(email_domain_block.domain) |
||||
[email_domain_block.domain] |
||||
else |
||||
dns.getresources(email_domain_block.domain, Resolv::DNS::Resource::IN::A).to_a + dns.getresources(email_domain_block.domain, Resolv::DNS::Resource::IN::AAAA).to_a.map { |resource| resource.address.to_s } |
||||
end |
||||
end |
||||
|
||||
email_domain_block.update(ips: ips, last_refresh_at: Time.now.utc) |
||||
end |
||||
end |
||||
end |
||||
|
||||
def ip?(str) |
||||
str =~ Regexp.union([Resolv::IPv4::Regex, Resolv::IPv6::Regex]) |
||||
end |
||||
end |
@ -0,0 +1,6 @@ |
||||
class AddIpsToEmailDomainBlocks < ActiveRecord::Migration[6.1] |
||||
def change |
||||
add_column :email_domain_blocks, :ips, :inet, array: true |
||||
add_column :email_domain_blocks, :last_refresh_at, :datetime |
||||
end |
||||
end |
Loading…
Reference in new issue