about summary refs log tree commit diff
path: root/app/models
diff options
context:
space:
mode:
authorEugen Rochko <eugen@zeonfederated.com>2022-02-24 17:28:23 +0100
committerGitHub <noreply@github.com>2022-02-24 17:28:23 +0100
commita29a982eaa0536a741b43ffb3397c74e3abe7196 (patch)
tree12d9852def5f0ac7f1fe03e51113a65bafa68e8e /app/models
parent91cc8d1e636a3515b15758d0ad449a0477ea8c4c (diff)
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>
Diffstat (limited to 'app/models')
-rw-r--r--app/models/email_domain_block.rb55
-rw-r--r--app/models/form/email_domain_block_batch.rb30
-rw-r--r--app/models/status.rb1
3 files changed, 67 insertions, 19 deletions
diff --git a/app/models/email_domain_block.rb b/app/models/email_domain_block.rb
index f50fa46ba..36e7e62ab 100644
--- a/app/models/email_domain_block.rb
+++ b/app/models/email_domain_block.rb
@@ -3,11 +3,13 @@
 #
 # Table name: email_domain_blocks
 #
-#  id         :bigint(8)        not null, primary key
-#  domain     :string           default(""), not null
-#  created_at :datetime         not null
-#  updated_at :datetime         not null
-#  parent_id  :bigint(8)
+#  id              :bigint(8)        not null, primary key
+#  domain          :string           default(""), not null
+#  created_at      :datetime         not null
+#  updated_at      :datetime         not null
+#  parent_id       :bigint(8)
+#  ips             :inet             is an Array
+#  last_refresh_at :datetime
 #
 
 class EmailDomainBlock < ApplicationRecord
@@ -18,27 +20,42 @@ class EmailDomainBlock < ApplicationRecord
 
   validates :domain, presence: true, uniqueness: true, domain: true
 
-  def with_dns_records=(val)
-    @with_dns_records = ActiveModel::Type::Boolean.new.cast(val)
-  end
+  # Used for adding multiple blocks at once
+  attr_accessor :other_domains
 
-  def with_dns_records?
-    @with_dns_records
+  def history
+    @history ||= Trends::History.new('email_domain_blocks', id)
   end
 
-  alias with_dns_records with_dns_records?
+  def self.block?(domain_or_domains, ips: [], attempt_ip: nil)
+    domains = Array(domain_or_domains).map do |str|
+      domain = begin
+        if str.include?('@')
+          str.split('@', 2).last
+        else
+          str
+        end
+      end
+
+      TagManager.instance.normalize_domain(domain) if domain.present?
+    rescue Addressable::URI::InvalidURIError
+      nil
+    end
 
-  def self.block?(email)
-    _, domain = email.split('@', 2)
+    # If some of the inputs passed in are invalid, we definitely want to
+    # block the attempt, but we also want to register hits against any
+    # other valid matches
 
-    return true if domain.nil?
+    blocked = domains.any?(&:nil?)
 
-    begin
-      domain = TagManager.instance.normalize_domain(domain)
-    rescue Addressable::URI::InvalidURIError
-      return true
+    scope = where(domain: domains)
+    scope = scope.or(where('ips && ARRAY[?]::inet[]', ips)) if ips.any?
+
+    scope.find_each do |block|
+      blocked = true
+      block.history.add(attempt_ip) if attempt_ip.present?
     end
 
-    where(domain: domain).exists?
+    blocked
   end
 end
diff --git a/app/models/form/email_domain_block_batch.rb b/app/models/form/email_domain_block_batch.rb
new file mode 100644
index 000000000..df120182b
--- /dev/null
+++ b/app/models/form/email_domain_block_batch.rb
@@ -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
diff --git a/app/models/status.rb b/app/models/status.rb
index 2e3df98a1..96e41b1d3 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -24,6 +24,7 @@
 #  poll_id                :bigint(8)
 #  deleted_at             :datetime
 #  edited_at              :datetime
+#  trendable              :boolean
 #
 
 class Status < ApplicationRecord