diff options
Diffstat (limited to 'app/models/domain_block.rb')
-rw-r--r-- | app/models/domain_block.rb | 53 |
1 files changed, 42 insertions, 11 deletions
diff --git a/app/models/domain_block.rb b/app/models/domain_block.rb index 84c08c158..4e865b850 100644 --- a/app/models/domain_block.rb +++ b/app/models/domain_block.rb @@ -3,13 +3,15 @@ # # Table name: domain_blocks # -# id :bigint(8) not null, primary key -# domain :string default(""), not null -# created_at :datetime not null -# updated_at :datetime not null -# severity :integer default("silence") -# reject_media :boolean default(FALSE), not null -# reject_reports :boolean default(FALSE), not null +# id :bigint(8) not null, primary key +# domain :string default(""), not null +# created_at :datetime not null +# updated_at :datetime not null +# severity :integer default("silence") +# reject_media :boolean default(FALSE), not null +# reject_reports :boolean default(FALSE), not null +# private_comment :text +# public_comment :text # class DomainBlock < ApplicationRecord @@ -17,21 +19,50 @@ class DomainBlock < ApplicationRecord enum severity: [:silence, :suspend, :noop] - validates :domain, presence: true, uniqueness: true + validates :domain, presence: true, uniqueness: true, domain: true has_many :accounts, foreign_key: :domain, primary_key: :domain delegate :count, to: :accounts, prefix: true scope :matches_domain, ->(value) { where(arel_table[:domain].matches("%#{value}%")) } + scope :with_user_facing_limitations, -> { where(severity: [:silence, :suspend]).or(where(reject_media: true)) } + scope :by_severity, -> { order(Arel.sql('(CASE severity WHEN 0 THEN 1 WHEN 1 THEN 2 WHEN 2 THEN 0 END), reject_media, domain')) } - def self.blocked?(domain) - where(domain: domain, severity: :suspend).exists? + class << self + def suspend?(domain) + !!rule_for(domain)&.suspend? + end + + def silence?(domain) + !!rule_for(domain)&.silence? + end + + def reject_media?(domain) + !!rule_for(domain)&.reject_media? + end + + def reject_reports?(domain) + !!rule_for(domain)&.reject_reports? + end + + alias blocked? suspend? + + def rule_for(domain) + return if domain.blank? + + uri = Addressable::URI.new.tap { |u| u.host = domain.gsub(/[\/]/, '') } + segments = uri.normalized_host.split('.') + variants = segments.map.with_index { |_, i| segments[i..-1].join('.') } + + where(domain: variants[0..-2]).order(Arel.sql('char_length(domain) desc')).first + end end def stricter_than?(other_block) - return true if suspend? + return true if suspend? return false if other_block.suspend? && (silence? || noop?) return false if other_block.silence? && noop? + (reject_media || !other_block.reject_media) && (reject_reports || !other_block.reject_reports) end |