Merge branch 'master' into glitch-soc/merge-upstream
Conflicts: - `app/models/form/admin_settings.rb`: New setting added upstream. Ported it. - `app/views/statuses/_simple_status.html.haml`: Upstream removed RTL classes. Did the same. - `config/settings.yml`: New setting added upstream. Ported it.
This commit is contained in:
		@@ -67,6 +67,7 @@ class Account < ApplicationRecord
 | 
			
		||||
  include Paginable
 | 
			
		||||
  include AccountCounters
 | 
			
		||||
  include DomainNormalizable
 | 
			
		||||
  include DomainMaterializable
 | 
			
		||||
  include AccountMerging
 | 
			
		||||
 | 
			
		||||
  MAX_DISPLAY_NAME_LENGTH = (ENV['MAX_DISPLAY_NAME_CHARS'] || 30).to_i
 | 
			
		||||
@@ -107,7 +108,6 @@ class Account < ApplicationRecord
 | 
			
		||||
  scope :bots, -> { where(actor_type: %w(Application Service)) }
 | 
			
		||||
  scope :groups, -> { where(actor_type: 'Group') }
 | 
			
		||||
  scope :alphabetic, -> { order(domain: :asc, username: :asc) }
 | 
			
		||||
  scope :by_domain_accounts, -> { group(:domain).select(:domain, 'COUNT(*) AS accounts_count').order('accounts_count desc') }
 | 
			
		||||
  scope :matches_username, ->(value) { where(arel_table[:username].matches("#{value}%")) }
 | 
			
		||||
  scope :matches_display_name, ->(value) { where(arel_table[:display_name].matches("#{value}%")) }
 | 
			
		||||
  scope :matches_domain, ->(value) { where(arel_table[:domain].matches("%#{value}%")) }
 | 
			
		||||
@@ -440,10 +440,6 @@ class Account < ApplicationRecord
 | 
			
		||||
      super - %w(statuses_count following_count followers_count)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def domains
 | 
			
		||||
      reorder(nil).pluck(Arel.sql('distinct accounts.domain'))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def inboxes
 | 
			
		||||
      urls = reorder(nil).where(protocol: :activitypub).group(:preferred_inbox_url).pluck(Arel.sql("coalesce(nullif(accounts.shared_inbox_url, ''), accounts.inbox_url) AS preferred_inbox_url"))
 | 
			
		||||
      DeliveryFailureTracker.without_unavailable(urls)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								app/models/concerns/domain_materializable.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								app/models/concerns/domain_materializable.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module DomainMaterializable
 | 
			
		||||
  extend ActiveSupport::Concern
 | 
			
		||||
 | 
			
		||||
  included do
 | 
			
		||||
    after_create_commit :refresh_instances_view
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def refresh_instances_view
 | 
			
		||||
    Instance.refresh unless domain.nil? || Instance.where(domain: domain).exists?
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@@ -12,6 +12,7 @@
 | 
			
		||||
 | 
			
		||||
class DomainAllow < ApplicationRecord
 | 
			
		||||
  include DomainNormalizable
 | 
			
		||||
  include DomainMaterializable
 | 
			
		||||
 | 
			
		||||
  validates :domain, presence: true, uniqueness: true, domain: true
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,7 @@
 | 
			
		||||
 | 
			
		||||
class DomainBlock < ApplicationRecord
 | 
			
		||||
  include DomainNormalizable
 | 
			
		||||
  include DomainMaterializable
 | 
			
		||||
 | 
			
		||||
  enum severity: [:silence, :suspend, :noop]
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -42,6 +42,7 @@ class Form::AdminSettings
 | 
			
		||||
    show_domain_blocks_rationale
 | 
			
		||||
    noindex
 | 
			
		||||
    outgoing_spoilers
 | 
			
		||||
    require_invite_text
 | 
			
		||||
  ).freeze
 | 
			
		||||
 | 
			
		||||
  BOOLEAN_KEYS = %i(
 | 
			
		||||
@@ -62,6 +63,7 @@ class Form::AdminSettings
 | 
			
		||||
    trends
 | 
			
		||||
    trendable_by_default
 | 
			
		||||
    noindex
 | 
			
		||||
    require_invite_text
 | 
			
		||||
  ).freeze
 | 
			
		||||
 | 
			
		||||
  UPLOAD_KEYS = %i(
 | 
			
		||||
 
 | 
			
		||||
@@ -1,26 +1,63 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
# == Schema Information
 | 
			
		||||
#
 | 
			
		||||
# Table name: instances
 | 
			
		||||
#
 | 
			
		||||
#  domain         :string           primary key
 | 
			
		||||
#  accounts_count :bigint(8)
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
class Instance
 | 
			
		||||
  include ActiveModel::Model
 | 
			
		||||
class Instance < ApplicationRecord
 | 
			
		||||
  self.primary_key = :domain
 | 
			
		||||
 | 
			
		||||
  attr_accessor :domain, :accounts_count, :domain_block
 | 
			
		||||
  has_many :accounts, foreign_key: :domain, primary_key: :domain
 | 
			
		||||
 | 
			
		||||
  def initialize(resource)
 | 
			
		||||
    @domain         = resource.domain
 | 
			
		||||
    @accounts_count = resource.respond_to?(:accounts_count) ? resource.accounts_count : nil
 | 
			
		||||
    @domain_block   = resource.is_a?(DomainBlock) ? resource : DomainBlock.rule_for(domain)
 | 
			
		||||
    @domain_allow   = resource.is_a?(DomainAllow) ? resource : DomainAllow.rule_for(domain)
 | 
			
		||||
  belongs_to :domain_block, foreign_key: :domain, primary_key: :domain
 | 
			
		||||
  belongs_to :domain_allow, foreign_key: :domain, primary_key: :domain
 | 
			
		||||
 | 
			
		||||
  scope :matches_domain, ->(value) { where(arel_table[:domain].matches("%#{value}%")) }
 | 
			
		||||
 | 
			
		||||
  def self.refresh
 | 
			
		||||
    Scenic.database.refresh_materialized_view(table_name, concurrently: true, cascade: false)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def countable?
 | 
			
		||||
    @accounts_count.present?
 | 
			
		||||
  def readonly?
 | 
			
		||||
    true
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def delivery_failure_tracker
 | 
			
		||||
    @delivery_failure_tracker ||= DeliveryFailureTracker.new(domain)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def following_count
 | 
			
		||||
    @following_count ||= Follow.where(account: accounts).count
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def followers_count
 | 
			
		||||
    @followers_count ||= Follow.where(target_account: accounts).count
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def reports_count
 | 
			
		||||
    @reports_count ||= Report.where(target_account: accounts).count
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def blocks_count
 | 
			
		||||
    @blocks_count ||= Block.where(target_account: accounts).count
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def public_comment
 | 
			
		||||
    domain_block&.public_comment
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def private_comment
 | 
			
		||||
    domain_block&.private_comment
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def media_storage
 | 
			
		||||
    @media_storage ||= MediaAttachment.where(account: accounts).sum(:file_file_size)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def to_param
 | 
			
		||||
    domain
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def cache_key
 | 
			
		||||
    domain
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -13,18 +13,27 @@ class InstanceFilter
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def results
 | 
			
		||||
    if params[:limited].present?
 | 
			
		||||
      scope = DomainBlock
 | 
			
		||||
      scope = scope.matches_domain(params[:by_domain]) if params[:by_domain].present?
 | 
			
		||||
      scope.order(id: :desc)
 | 
			
		||||
    elsif params[:allowed].present?
 | 
			
		||||
      scope = DomainAllow
 | 
			
		||||
      scope = scope.matches_domain(params[:by_domain]) if params[:by_domain].present?
 | 
			
		||||
      scope.order(id: :desc)
 | 
			
		||||
    scope = Instance.includes(:domain_block, :domain_allow).order(accounts_count: :desc)
 | 
			
		||||
 | 
			
		||||
    params.each do |key, value|
 | 
			
		||||
      scope.merge!(scope_for(key, value.to_s.strip)) if value.present?
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    scope
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
 | 
			
		||||
  def scope_for(key, value)
 | 
			
		||||
    case key.to_s
 | 
			
		||||
    when 'limited'
 | 
			
		||||
      Instance.joins(:domain_block).reorder(Arel.sql('domain_blocks.id desc'))
 | 
			
		||||
    when 'allowed'
 | 
			
		||||
      Instance.joins(:domain_allow).reorder(Arel.sql('domain_allows.id desc'))
 | 
			
		||||
    when 'by_domain'
 | 
			
		||||
      Instance.matches_domain(value)
 | 
			
		||||
    else
 | 
			
		||||
      scope = Account.remote
 | 
			
		||||
      scope = scope.matches_domain(params[:by_domain]) if params[:by_domain].present?
 | 
			
		||||
      scope.by_domain_accounts
 | 
			
		||||
      raise "Unknown filter: #{key}"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@
 | 
			
		||||
#  target_account_id          :bigint(8)        not null
 | 
			
		||||
#  assigned_account_id        :bigint(8)
 | 
			
		||||
#  uri                        :string
 | 
			
		||||
#  forwarded                  :boolean
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
class Report < ApplicationRecord
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,8 @@
 | 
			
		||||
class UnavailableDomain < ApplicationRecord
 | 
			
		||||
  include DomainNormalizable
 | 
			
		||||
 | 
			
		||||
  validates :domain, presence: true, uniqueness: true
 | 
			
		||||
 | 
			
		||||
  after_commit :reset_cache!
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
 
 | 
			
		||||
@@ -82,7 +82,8 @@ class User < ApplicationRecord
 | 
			
		||||
  has_many :webauthn_credentials, dependent: :destroy
 | 
			
		||||
 | 
			
		||||
  has_one :invite_request, class_name: 'UserInviteRequest', inverse_of: :user, dependent: :destroy
 | 
			
		||||
  accepts_nested_attributes_for :invite_request, reject_if: ->(attributes) { attributes['text'].blank? }
 | 
			
		||||
  accepts_nested_attributes_for :invite_request, reject_if: ->(attributes) { attributes['text'].blank? && !Setting.require_invite_text }
 | 
			
		||||
  validates :invite_request, presence: true, on: :create, if: -> { Setting.require_invite_text }
 | 
			
		||||
 | 
			
		||||
  validates :locale, inclusion: I18n.available_locales.map(&:to_s), if: :locale?
 | 
			
		||||
  validates_with BlacklistedEmailValidator, on: :create
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user