Add: #667 プレビューカード、参照のフェッチを行わないドメインの設定 (#690)

This commit is contained in:
KMY(雪あすか) 2024-04-03 12:37:18 +09:00 committed by GitHub
parent ff2860d0df
commit d89e1114bb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 123 additions and 2 deletions

View file

@ -0,0 +1,34 @@
# frozen_string_literal: true
module Admin
class SpecialDomainsController < BaseController
def show
authorize :instance, :show?
@admin_settings = Form::AdminSettings.new
end
def create
authorize :instance, :destroy?
@admin_settings = Form::AdminSettings.new(settings_params)
if @admin_settings.save
flash[:notice] = I18n.t('generic.changes_saved_msg')
redirect_to after_update_redirect_path
else
render :show
end
end
private
def after_update_redirect_path
admin_special_domains_path
end
def settings_params
params.require(:form_admin_settings).permit(*Form::AdminSettings::KEYS)
end
end
end

View file

@ -63,6 +63,8 @@ class Form::AdminSettings
emoji_reaction_disallow_domains
block_unfollow_account_mention
hold_remote_new_accounts
stop_fetch_activity_domains
stop_link_preview_domains
).freeze
INTEGER_KEYS = %i(
@ -120,6 +122,8 @@ class Form::AdminSettings
STRING_ARRAY_KEYS = %i(
emoji_reaction_disallow_domains
stop_fetch_activity_domains
stop_link_preview_domains
).freeze
attr_accessor(*KEYS)

View file

@ -106,7 +106,8 @@ class FetchLinkCardService < BaseService
def bad_url?(uri)
# Avoid local instance URLs and invalid URLs
uri.host.blank? || TagManager.instance.local_url?(uri.to_s) || !%w(http https).include?(uri.scheme)
uri.host.blank? || TagManager.instance.local_url?(uri.to_s) || !%w(http https).include?(uri.scheme) ||
referenced_urls.include?(uri.to_s) || Setting.stop_link_preview_domains&.include?(uri.host)
end
def mention_link?(anchor)

View file

@ -153,10 +153,16 @@ class ProcessReferencesService < BaseService
def url_to_status(url)
status = ActivityPub::TagManager.instance.uri_to_resource(url, Status, url: true)
status ||= ResolveURLService.new.call(url, on_behalf_of: @status.account) if @fetch_remote && @no_fetch_urls.exclude?(url)
status ||= ResolveURLService.new.call(url, on_behalf_of: @status.account) unless bad_url_to_fetch?(url)
referrable?(status) ? status : nil
end
def bad_url_to_fetch?(url)
uri = Addressable::URI.parse(url).normalize
!@fetch_remote || @no_fetch_urls.include?(url) || uri.host.blank? || Setting.stop_fetch_activity_domains&.include?(uri.host)
end
def referrable?(target_status)
return false if target_status.nil?
return @referrable if defined?(@referrable)

View file

@ -0,0 +1,17 @@
- content_for :page_title do
= t('admin.special_domains.title')
- content_for :header_tags do
= javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous'
= simple_form_for @admin_settings, url: admin_special_domains_path, html: { method: :post } do |f|
= render 'shared/error_messages', object: @admin_settings
.fields-group
= f.input :stop_fetch_activity_domains, wrapper: :with_label, as: :text, input_html: { rows: 6 }, label: t('admin.special_domains.stop_fetch_activity_domains.title'), hint: t('admin.special_domains.stop_fetch_activity_domains.preamble')
.fields-group
= f.input :stop_link_preview_domains, wrapper: :with_label, as: :text, input_html: { rows: 6 }, label: t('admin.special_domains.stop_link_preview_domains.title'), hint: t('admin.special_domains.stop_link_preview_domains.preamble')
.actions
= f.button :button, t('generic.save_changes'), type: :submit

View file

@ -1046,6 +1046,14 @@ en:
minor: Minor release
patch: Patch release — bugfixes and easy to apply changes
version: Version
special_domains:
stop_fetch_activity_domains:
preamble: WebとActivityでドメインの異なるサーバーでは、WebにアクセスしてもActivityが取得できない場合があります。参照において、投稿本文内でそのようなURLが指定された場合のフェッチを抑止します。多くの場合、この設定を利用する機会はほとんどありません。
title: Domains do not fetch for references
stop_link_preview_domains:
preamble: 多くのアクセスがあったIPアドレスからの接続を一時的に制限するサイトがある場合、自分のサーバーが不利に扱われる場合があります。そのようなサイトにアクセスしてリンクプレビューを生成する処理を抑制します。多くの場合、この設定を利用する機会はほとんどありません。
title: Domains do not fetch for link previews
title: Special domains
special_instances:
emoji_reaction_disallow_domains: Domains we are not permitted emoji reaction
emoji_reaction_disallow_domains_hint: If you need to be considerate to your coalition partners, set the domain with a new line separator. It is not possible to put an emoji reaction on a post from a set domain.

View file

@ -1042,6 +1042,14 @@ ja:
minor: マイナーリリース
patch: パッチ (バグ修正のみ)
version: バージョン
special_domains:
stop_fetch_activity_domains:
preamble: WebとActivityでドメインの異なるサーバーでは、WebにアクセスしてもActivityが取得できない場合があります。参照において、投稿本文内でそのようなURLが指定された場合のフェッチを抑止します。ドメインは改行区切りで複数指定できます。多くの場合、この設定を利用する機会はほとんどありません。
title: 参照でフェッチを行わないドメイン
stop_link_preview_domains:
preamble: 多くのアクセスがあったIPアドレスからの接続を一時的に制限するサイトがある場合、自分のサーバーが不利に扱われる場合があります。そのようなサイトにアクセスしてリンクプレビューを生成する処理を抑制します。ドメインは改行区切りで複数指定できます。多くの場合、この設定を利用する機会はほとんどありません。
title: リンクのプレビューを行わないドメイン
title: 特殊なドメイン
special_instances:
emoji_reaction_disallow_domains: 自分のサーバーが絵文字リアクションをすることを許可しないドメイン
emoji_reaction_disallow_domains_hint: 連合先に配慮する必要がある場合、ドメインを改行区切りで設定します。設定されたドメインの投稿に絵文字リアクションを付けることはできません。

View file

@ -60,6 +60,7 @@ SimpleNavigation::Configuration.run do |navigation|
s.item :follow_recommendations, safe_join([fa_icon('user-plus fw'), t('admin.follow_recommendations.title')]), admin_follow_recommendations_path, highlights_on: %r{/admin/follow_recommendations}, if: -> { current_user.can?(:manage_taxonomies) }
s.item :instances, safe_join([fa_icon('cloud fw'), t('admin.instances.title')]), admin_instances_path(limited: limited_federation_mode? ? nil : '1'), highlights_on: %r{/admin/instances|/admin/domain_blocks|/admin/domain_allows}, if: -> { current_user.can?(:manage_federation) }
s.item :special_instances, safe_join([fa_icon('list fw'), t('admin.special_instances.title')]), admin_special_instances_path, highlights_on: %r{/admin/special_instances}, if: -> { current_user.can?(:manage_federation) }
s.item :special_domains, safe_join([fa_icon('list fw'), t('admin.special_domains.title')]), admin_special_domains_path, highlights_on: %r{/admin/special_domains}, if: -> { current_user.can?(:manage_federation) }
s.item :email_domain_blocks, safe_join([fa_icon('envelope fw'), t('admin.email_domain_blocks.title')]), admin_email_domain_blocks_path, highlights_on: %r{/admin/email_domain_blocks}, if: -> { current_user.can?(:manage_blocks) }
s.item :ip_blocks, safe_join([fa_icon('ban fw'), t('admin.ip_blocks.title')]), admin_ip_blocks_path, highlights_on: %r{/admin/ip_blocks}, if: -> { current_user.can?(:manage_blocks) }
s.item :action_logs, safe_join([fa_icon('bars fw'), t('admin.action_logs.title')]), admin_action_logs_path, if: -> { current_user.can?(:view_audit_log) }

View file

@ -46,6 +46,7 @@ namespace :admin do
resources :ng_rule_histories, only: [:show]
resource :sensitive_words, only: [:show, :create]
resource :special_instances, only: [:show, :create]
resource :special_domains, only: [:show, :create]
resources :announcements, except: [:show] do
member do

View file

@ -284,6 +284,20 @@ RSpec.describe FetchLinkCardService do
expect(status.preview_card.title).to eq 'Hello world'
end
end
context 'when URL domain is blocked by admin' do
let(:status) { Fabricate(:status, text: 'http://example.com/html') }
let(:custom_before) { true }
before do
Setting.stop_link_preview_domains = ['example.com']
end
it 'creates preview card' do
subject.call(status)
expect(status.preview_card).to be_nil
end
end
end
context 'with a remote status' do

View file

@ -175,6 +175,33 @@ RSpec.describe ProcessReferencesService, type: :service do
end
end
context 'with fetch is blocked by admin' do
let(:text) { 'Hello RT https://web.example.com/note' }
before do
Setting.stop_fetch_activity_domains = ['web.example.com']
stub_request(:get, 'https://web.example.com/note').to_return(status: 404)
end
context 'when the post is known' do
let(:target_status) { Fabricate(:status, uri: 'https://example.com/note', url: 'https://web.example.com/note') }
it 'post status', :sidekiq_inline do
expect(subject.size).to eq 1
expect(subject.pluck(0)).to include target_status.id
expect(subject.pluck(1)).to include 'RT'
expect(notify?).to be true
end
end
context 'when the post is unknown' do
it 'post status', :sidekiq_inline do
expect(subject.size).to eq 0
expect(a_request(:get, 'https://web.example.com/note')).to_not have_been_made
end
end
end
context 'when unfetched remote post' do
let(:account) { Fabricate(:account, followers_url: 'http://example.com/followers', domain: 'example.com', uri: 'https://example.com/actor') }
let(:object_json) do