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:
ThibG 2020-03-09 00:10:29 +01:00 committed by GitHub
parent 9660aa4543
commit b154428e14
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 55 additions and 11 deletions

View File

@ -25,7 +25,7 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController
end end
def hide_results? 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 end
def default_accounts def default_accounts

View File

@ -25,7 +25,7 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController
end end
def hide_results? 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 end
def default_accounts def default_accounts

View File

@ -28,7 +28,8 @@ class FollowerAccountsController < ApplicationController
render json: collection_presenter, render json: collection_presenter,
serializer: ActivityPub::CollectionSerializer, serializer: ActivityPub::CollectionSerializer,
adapter: ActivityPub::Adapter, adapter: ActivityPub::Adapter,
content_type: 'application/activity+json' content_type: 'application/activity+json',
fields: restrict_fields_to
end end
end end
end end
@ -71,4 +72,12 @@ class FollowerAccountsController < ApplicationController
) )
end end
end end
def restrict_fields_to
if page_requested? || !@account.user_hides_network?
# Return all fields
else
%i(id type totalItems)
end
end
end end

View File

@ -28,7 +28,8 @@ class FollowingAccountsController < ApplicationController
render json: collection_presenter, render json: collection_presenter,
serializer: ActivityPub::CollectionSerializer, serializer: ActivityPub::CollectionSerializer,
adapter: ActivityPub::Adapter, adapter: ActivityPub::Adapter,
content_type: 'application/activity+json' content_type: 'application/activity+json',
fields: restrict_fields_to
end end
end end
end end
@ -71,4 +72,12 @@ class FollowingAccountsController < ApplicationController
) )
end end
end end
def restrict_fields_to
if page_requested? || !@account.user_hides_network?
# Return all fields
else
%i(id type totalItems)
end
end
end end

View File

@ -46,6 +46,7 @@
# silenced_at :datetime # silenced_at :datetime
# suspended_at :datetime # suspended_at :datetime
# trust_level :integer # trust_level :integer
# hide_collections :boolean
# #
class Account < ApplicationRecord class Account < ApplicationRecord
@ -323,6 +324,14 @@ class Account < ApplicationRecord
save! save!
end end
def hides_followers?
hide_collections? || user_hides_network?
end
def hides_following?
hide_collections? || user_hides_network?
end
def object_type def object_type
:person :person
end end

View File

@ -94,6 +94,7 @@ class ActivityPub::ProcessAccountService < BaseService
@account.statuses_count = outbox_total_items if outbox_total_items.present? @account.statuses_count = outbox_total_items if outbox_total_items.present?
@account.following_count = following_total_items if following_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.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 @account.moved_to_account = @json['movedTo'].present? ? moved_account : nil
end end
@ -166,26 +167,36 @@ class ActivityPub::ProcessAccountService < BaseService
end end
def outbox_total_items def outbox_total_items
collection_total_items('outbox') collection_info('outbox').first
end end
def following_total_items def following_total_items
collection_total_items('following') collection_info('following').first
end end
def followers_total_items def followers_total_items
collection_total_items('followers') collection_info('followers').first
end end
def collection_total_items(type) def following_private?
return if @json[type].blank? !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) return @collections[type] if @collections.key?(type)
collection = fetch_resource_without_id_validation(@json[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 rescue HTTP::Error, OpenSSL::SSL::SSLError
@collections[type] = nil @collections[type] = [nil, nil]
end end
def moved_account def moved_account

View File

@ -0,0 +1,5 @@
class AddHideCollectionsToAccounts < ActiveRecord::Migration[5.2]
def change
add_column :accounts, :hide_collections, :boolean
end
end

View File

@ -170,6 +170,7 @@ ActiveRecord::Schema.define(version: 2020_03_06_035625) do
t.datetime "silenced_at" t.datetime "silenced_at"
t.datetime "suspended_at" t.datetime "suspended_at"
t.integer "trust_level" 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 "(((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 "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" t.index ["moved_to_account_id"], name: "index_accounts_on_moved_to_account_id"