Add federation support for the "hide network" preference (#11673)
* Change ActivityPub follower/following collections to not link first page * Add support for hiding followers and following of remote users * Switch to using a single `hide_collections` column * Address code style remarks
This commit is contained in:
		@@ -25,7 +25,7 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def hide_results?
 | 
			
		||||
    (@account.user_hides_network? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account))
 | 
			
		||||
    (@account.hides_followers? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account))
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def default_accounts
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def hide_results?
 | 
			
		||||
    (@account.user_hides_network? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account))
 | 
			
		||||
    (@account.hides_following? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account))
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def default_accounts
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,8 @@ class FollowerAccountsController < ApplicationController
 | 
			
		||||
        render json: collection_presenter,
 | 
			
		||||
               serializer: ActivityPub::CollectionSerializer,
 | 
			
		||||
               adapter: ActivityPub::Adapter,
 | 
			
		||||
               content_type: 'application/activity+json'
 | 
			
		||||
               content_type: 'application/activity+json',
 | 
			
		||||
               fields: restrict_fields_to
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
@@ -71,4 +72,12 @@ class FollowerAccountsController < ApplicationController
 | 
			
		||||
      )
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def restrict_fields_to
 | 
			
		||||
    if page_requested? || !@account.user_hides_network?
 | 
			
		||||
      # Return all fields
 | 
			
		||||
    else
 | 
			
		||||
      %i(id type totalItems)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,8 @@ class FollowingAccountsController < ApplicationController
 | 
			
		||||
        render json: collection_presenter,
 | 
			
		||||
               serializer: ActivityPub::CollectionSerializer,
 | 
			
		||||
               adapter: ActivityPub::Adapter,
 | 
			
		||||
               content_type: 'application/activity+json'
 | 
			
		||||
               content_type: 'application/activity+json',
 | 
			
		||||
               fields: restrict_fields_to
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
@@ -71,4 +72,12 @@ class FollowingAccountsController < ApplicationController
 | 
			
		||||
      )
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def restrict_fields_to
 | 
			
		||||
    if page_requested? || !@account.user_hides_network?
 | 
			
		||||
      # Return all fields
 | 
			
		||||
    else
 | 
			
		||||
      %i(id type totalItems)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -46,6 +46,7 @@
 | 
			
		||||
#  silenced_at             :datetime
 | 
			
		||||
#  suspended_at            :datetime
 | 
			
		||||
#  trust_level             :integer
 | 
			
		||||
#  hide_collections        :boolean
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
class Account < ApplicationRecord
 | 
			
		||||
@@ -323,6 +324,14 @@ class Account < ApplicationRecord
 | 
			
		||||
    save!
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def hides_followers?
 | 
			
		||||
    hide_collections? || user_hides_network?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def hides_following?
 | 
			
		||||
    hide_collections? || user_hides_network?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def object_type
 | 
			
		||||
    :person
 | 
			
		||||
  end
 | 
			
		||||
 
 | 
			
		||||
@@ -94,6 +94,7 @@ class ActivityPub::ProcessAccountService < BaseService
 | 
			
		||||
    @account.statuses_count    = outbox_total_items    if outbox_total_items.present?
 | 
			
		||||
    @account.following_count   = following_total_items if following_total_items.present?
 | 
			
		||||
    @account.followers_count   = followers_total_items if followers_total_items.present?
 | 
			
		||||
    @account.hide_collections  = following_private? || followers_private?
 | 
			
		||||
    @account.moved_to_account  = @json['movedTo'].present? ? moved_account : nil
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
@@ -166,26 +167,36 @@ class ActivityPub::ProcessAccountService < BaseService
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def outbox_total_items
 | 
			
		||||
    collection_total_items('outbox')
 | 
			
		||||
    collection_info('outbox').first
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def following_total_items
 | 
			
		||||
    collection_total_items('following')
 | 
			
		||||
    collection_info('following').first
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def followers_total_items
 | 
			
		||||
    collection_total_items('followers')
 | 
			
		||||
    collection_info('followers').first
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def collection_total_items(type)
 | 
			
		||||
    return if @json[type].blank?
 | 
			
		||||
  def following_private?
 | 
			
		||||
    !collection_info('following').last
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def followers_private?
 | 
			
		||||
    !collection_info('followers').last
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def collection_info(type)
 | 
			
		||||
    return [nil, nil] if @json[type].blank?
 | 
			
		||||
    return @collections[type] if @collections.key?(type)
 | 
			
		||||
 | 
			
		||||
    collection = fetch_resource_without_id_validation(@json[type])
 | 
			
		||||
 | 
			
		||||
    @collections[type] = collection.is_a?(Hash) && collection['totalItems'].present? && collection['totalItems'].is_a?(Numeric) ? collection['totalItems'] : nil
 | 
			
		||||
    total_items = collection.is_a?(Hash) && collection['totalItems'].present? && collection['totalItems'].is_a?(Numeric) ? collection['totalItems'] : nil
 | 
			
		||||
    has_first_page = collection.is_a?(Hash) && collection['first'].present?
 | 
			
		||||
    @collections[type] = [total_items, has_first_page]
 | 
			
		||||
  rescue HTTP::Error, OpenSSL::SSL::SSLError
 | 
			
		||||
    @collections[type] = nil
 | 
			
		||||
    @collections[type] = [nil, nil]
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def moved_account
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,5 @@
 | 
			
		||||
class AddHideCollectionsToAccounts < ActiveRecord::Migration[5.2]
 | 
			
		||||
  def change
 | 
			
		||||
    add_column :accounts, :hide_collections, :boolean
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@@ -170,6 +170,7 @@ ActiveRecord::Schema.define(version: 2020_03_06_035625) do
 | 
			
		||||
    t.datetime "silenced_at"
 | 
			
		||||
    t.datetime "suspended_at"
 | 
			
		||||
    t.integer "trust_level"
 | 
			
		||||
    t.boolean "hide_collections"
 | 
			
		||||
    t.index "(((setweight(to_tsvector('simple'::regconfig, (display_name)::text), 'A'::\"char\") || setweight(to_tsvector('simple'::regconfig, (username)::text), 'B'::\"char\")) || setweight(to_tsvector('simple'::regconfig, (COALESCE(domain, ''::character varying))::text), 'C'::\"char\")))", name: "search_index", using: :gin
 | 
			
		||||
    t.index "lower((username)::text), lower((domain)::text)", name: "index_accounts_on_username_and_domain_lower", unique: true
 | 
			
		||||
    t.index ["moved_to_account_id"], name: "index_accounts_on_moved_to_account_id"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user