From 7b8fedb3cd5e75832e31c1ad7f119c8657d5e8e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?KMY=EF=BC=88=E9=9B=AA=E3=81=82=E3=81=99=E3=81=8B=EF=BC=89?= Date: Tue, 19 Dec 2023 08:33:06 +0900 Subject: [PATCH] =?UTF-8?q?Add:=20#363=20=E7=89=B9=E5=AE=9A=E3=82=B5?= =?UTF-8?q?=E3=83=BC=E3=83=90=E3=83=BC=E3=81=AE=E6=8A=95=E7=A8=BF=E3=81=AB?= =?UTF-8?q?=E3=82=B9=E3=82=BF=E3=83=B3=E3=83=97=E3=82=92=E4=BB=98=E3=81=91?= =?UTF-8?q?=E3=82=8B=E3=81=93=E3=81=A8=E3=82=92=E7=A6=81=E6=AD=A2=E3=81=99?= =?UTF-8?q?=E3=82=8B=E7=AE=A1=E7=90=86=E8=80=85=E8=A8=AD=E5=AE=9A=20(#364)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add: #363 特定サーバーの投稿にスタンプを付けることを禁止する管理者設定 * Fix test --- .../admin/special_instances_controller.rb | 34 +++++++ app/models/concerns/account/other_settings.rb | 33 ++++--- app/models/form/admin_settings.rb | 2 + .../admin/special_instances/show.html.haml | 14 +++ config/locales/en.yml | 4 + config/locales/ja.yml | 4 + config/navigation.rb | 1 + config/routes/admin.rb | 1 + config/settings.yml | 1 + spec/models/account_spec.rb | 89 ++++++++++++++++--- 10 files changed, 157 insertions(+), 26 deletions(-) create mode 100644 app/controllers/admin/special_instances_controller.rb create mode 100644 app/views/admin/special_instances/show.html.haml diff --git a/app/controllers/admin/special_instances_controller.rb b/app/controllers/admin/special_instances_controller.rb new file mode 100644 index 0000000000..3fd35d474e --- /dev/null +++ b/app/controllers/admin/special_instances_controller.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module Admin + class SpecialInstancesController < 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_instances_path + end + + def settings_params + params.require(:form_admin_settings).permit(*Form::AdminSettings::KEYS) + end + end +end diff --git a/app/models/concerns/account/other_settings.rb b/app/models/concerns/account/other_settings.rb index 72f52ba979..c98ba1dc02 100644 --- a/app/models/concerns/account/other_settings.rb +++ b/app/models/concerns/account/other_settings.rb @@ -9,11 +9,17 @@ module Account::OtherSettings end def noai? - user&.setting_noai || (settings.present? && settings['noai']) || false + return user.setting_noai if local? && user.present? + return settings['noai'] if settings.present? && settings.key?('noai') + + false end def translatable_private? - user&.setting_translatable_private || (settings.present? && settings['translatable_private']) || false + return user.setting_translatable_private if local? && user.present? + return settings['translatable_private'] if settings.present? && settings.key?('translatable_private') + + false end def link_preview? @@ -31,30 +37,31 @@ module Account::OtherSettings end def hide_statuses_count? - return user&.setting_hide_statuses_count unless user&.setting_hide_statuses_count.nil? - return settings['hide_statuses_count'] if settings.present? + return user&.setting_hide_statuses_count if local? && user.present? + return settings['hide_statuses_count'] if settings.present? && settings.key?('hide_statuses_count') false end def hide_following_count? - return user&.setting_hide_following_count unless user&.setting_hide_following_count.nil? - return settings['hide_following_count'] if settings.present? + return user&.setting_hide_following_count if local? && user.present? + return settings['hide_following_count'] if settings.present? && settings.key?('hide_following_count') false end def hide_followers_count? - return user&.setting_hide_followers_count unless user&.setting_hide_followers_count.nil? - return settings['hide_followers_count'] if settings.present? + return user&.setting_hide_followers_count if local? && user.present? + return settings['hide_followers_count'] if settings.present? && settings.key?('hide_followers_count') false end def emoji_reaction_policy - return settings['emoji_reaction_policy']&.to_sym || :allow if settings.present? && user.nil? + return :block if !local? && Setting.emoji_reaction_disallow_domains&.include?(domain) + return settings['emoji_reaction_policy']&.to_sym || :allow if settings.present? && !local? return :allow if user.nil? - return :block if local? && !Setting.enable_emoji_reaction + return :block if local? && !Setting.enable_emoji_reaction # for federation user.setting_emoji_reaction_policy&.to_sym end @@ -88,7 +95,7 @@ module Account::OtherSettings def public_settings # Please update `app/javascript/mastodon/api_types/accounts.ts` when making changes to the attributes - config = { + { 'noindex' => noindex?, 'noai' => noai?, 'hide_network' => hide_collections, @@ -98,10 +105,8 @@ module Account::OtherSettings 'translatable_private' => translatable_private?, 'link_preview' => link_preview?, 'allow_quote' => allow_quote?, - 'emoji_reaction_policy' => Setting.enable_emoji_reaction ? emoji_reaction_policy : :block, + 'emoji_reaction_policy' => Setting.enable_emoji_reaction ? emoji_reaction_policy.to_s : 'block', } - config = config.merge(settings) if settings.present? - config end def public_settings_for_local diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb index bec1d4c869..d36586ccd0 100644 --- a/app/models/form/admin_settings.rb +++ b/app/models/form/admin_settings.rb @@ -52,6 +52,7 @@ class Form::AdminSettings enable_public_unlisted_visibility unlocked_friend enable_local_timeline + emoji_reaction_disallow_domains ).freeze INTEGER_KEYS = %i( @@ -99,6 +100,7 @@ class Form::AdminSettings ng_words_for_stranger_mention sensitive_words sensitive_words_for_full + emoji_reaction_disallow_domains ).freeze attr_accessor(*KEYS) diff --git a/app/views/admin/special_instances/show.html.haml b/app/views/admin/special_instances/show.html.haml new file mode 100644 index 0000000000..0805932240 --- /dev/null +++ b/app/views/admin/special_instances/show.html.haml @@ -0,0 +1,14 @@ +- content_for :page_title do + = t('admin.special_instances.title') + +- content_for :header_tags do + = javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous' + += simple_form_for @admin_settings, url: admin_special_instances_path, html: { method: :post } do |f| + = render 'shared/error_messages', object: @admin_settings + + .fields-group + = f.input :emoji_reaction_disallow_domains, wrapper: :with_label, as: :text, input_html: { rows: 6 }, label: t('admin.special_instances.emoji_reaction_disallow_domains'), hint: t('admin.special_instances.emoji_reaction_disallow_domains_hint') + + .actions + = f.button :button, t('generic.save_changes'), type: :submit diff --git a/config/locales/en.yml b/config/locales/en.yml index 1902ef2af9..0415465f84 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -911,6 +911,10 @@ en: minor: Minor release patch: Patch release — bugfixes and easy to apply changes version: Version + special_instances: + emoji_reaction_disallow_domains: Domains we are not permitted stamp + 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 a stamp on a post from a set domain. + title: Special servers statuses: account: Author application: Application diff --git a/config/locales/ja.yml b/config/locales/ja.yml index dee1b5b2f8..9b5cdaf215 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -909,6 +909,10 @@ ja: minor: マイナーリリース patch: パッチ (バグ修正のみ) version: バージョン + special_instances: + emoji_reaction_disallow_domains: 自分がスタンプをつけることを許可しないドメイン + emoji_reaction_disallow_domains_hint: 連合先に配慮する必要がある場合、ドメインを改行区切りで設定します。設定されたドメインの投稿にスタンプを付けることはできません。 + title: 特殊なサーバー statuses: account: 作成者 application: アプリ diff --git a/config/navigation.rb b/config/navigation.rb index d305c34ae2..2fa9a6b4f9 100644 --- a/config/navigation.rb +++ b/config/navigation.rb @@ -54,6 +54,7 @@ SimpleNavigation::Configuration.run do |navigation| s.item :invites, safe_join([fa_icon('user-plus fw'), t('admin.invites.title')]), admin_invites_path, if: -> { current_user.can?(:manage_invites) } 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 :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) } diff --git a/config/routes/admin.rb b/config/routes/admin.rb index f4bcf5766f..48dd4395e5 100644 --- a/config/routes/admin.rb +++ b/config/routes/admin.rb @@ -34,6 +34,7 @@ namespace :admin do resources :warning_presets, except: [:new, :show] resource :ng_words, only: [:show, :create] resource :sensitive_words, only: [:show, :create] + resource :special_instances, only: [:show, :create] resources :announcements, except: [:show] do member do diff --git a/config/settings.yml b/config/settings.yml index 1c27e1f542..20bb622c52 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -46,6 +46,7 @@ defaults: &defaults unlocked_friend: false stranger_mention_from_local_ng: true enable_local_timeline: true + emoji_reaction_disallow_domains: [] development: <<: *defaults diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb index 60c964fee4..eb84b9bfd6 100644 --- a/spec/models/account_spec.rb +++ b/spec/models/account_spec.rb @@ -270,38 +270,38 @@ RSpec.describe Account do reactioned.follow!(mutual) end - shared_examples 'with policy' do |override_policy, anyone_r, followee_r, follower_r, mutual_r, self_r| # rubocop:disable Metrics/ParameterLists + shared_examples 'with policy' do |override_policy, permitted| context "when policy is #{override_policy}" do let(:policy) { override_policy } it 'allows anyone' do - expect(reactioned.allow_emoji_reaction?(anyone)).to be anyone_r + expect(reactioned.allow_emoji_reaction?(anyone)).to be permitted.include?(:anyone) end it 'allows followee' do - expect(reactioned.allow_emoji_reaction?(followee)).to be followee_r + expect(reactioned.allow_emoji_reaction?(followee)).to be permitted.include?(:following) end it 'allows follower' do - expect(reactioned.allow_emoji_reaction?(follower)).to be follower_r + expect(reactioned.allow_emoji_reaction?(follower)).to be permitted.include?(:followers) end it 'allows mutual' do - expect(reactioned.allow_emoji_reaction?(mutual)).to be mutual_r + expect(reactioned.allow_emoji_reaction?(mutual)).to be permitted.include?(:mutuals) end it 'allows self' do - expect(reactioned.allow_emoji_reaction?(reactioned)).to be self_r + expect(reactioned.allow_emoji_reaction?(reactioned)).to be permitted.include?(:self) end end end - it_behaves_like 'with policy', :allow, true, true, true, true, true - it_behaves_like 'with policy', :outside_only, false, true, true, true, true - it_behaves_like 'with policy', :following_only, false, true, false, true, true - it_behaves_like 'with policy', :followers_only, false, false, true, true, true - it_behaves_like 'with policy', :mutuals_only, false, false, false, true, true - it_behaves_like 'with policy', :block, false, false, false, false, false + it_behaves_like 'with policy', :allow, %i(anyone following followers mutuals self) + it_behaves_like 'with policy', :outside_only, %i(following followers mutuals self) + it_behaves_like 'with policy', :following_only, %i(following mutuals self) + it_behaves_like 'with policy', :followers_only, %i(followers mutuals self) + it_behaves_like 'with policy', :mutuals_only, %i(mutuals self) + it_behaves_like 'with policy', :block, %i() shared_examples 'allow local only' do |override_policy| context "when policy is #{override_policy} but allow local only" do @@ -371,6 +371,71 @@ RSpec.describe Account do end end + describe '#emoji_reaction_policy' do + subject { account.emoji_reaction_policy } + + let(:domains) { 'example.com' } + let(:account) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/actor') } + + before do + Form::AdminSettings.new(emoji_reaction_disallow_domains: domains).save + end + + it 'blocked if target domain' do + expect(subject).to eq :block + end + + context 'when other domain' do + let(:account) { Fabricate(:account, domain: 'allow.example.com', uri: 'https://allow.example.com/actor') } + + it 'allowed if target domain' do + expect(subject).to_not eq :block + end + end + end + + describe '#public_settings_for_local' do + subject { account.public_settings_for_local } + + let(:account) { Fabricate(:user, settings: { link_preview: false, allow_quote: true, hide_statuses_count: true, emoji_reaction_policy: :followers_only }).account } + + shared_examples 'some settings' do |permitted, emoji_reaction_policy| + it 'link_preview is disallowed' do + expect(subject['link_preview']).to be permitted.include?(:link_preview) + end + + it 'allow_quote is allowed' do + expect(subject['allow_quote']).to be permitted.include?(:allow_quote) + end + + it 'hide_statuses_count is allowed' do + expect(subject['hide_statuses_count']).to be permitted.include?(:hide_statuses_count) + end + + it 'hide_following_count is disallowed' do + expect(subject['hide_following_count']).to be permitted.include?(:hide_following_count) + end + + it 'emoji_reaction is allowed followers' do + expect(subject['emoji_reaction_policy']).to eq emoji_reaction_policy + end + end + + it_behaves_like 'some settings', %i(allow_quote hide_statuses_count), 'followers_only' + + context 'when remote user' do + let(:account) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/actor', settings: { 'link_preview' => false, 'allow_quote' => true, 'hide_statuses_count' => true, 'emoji_reaction_policy' => 'followers_only' }) } + + it_behaves_like 'some settings', %i(allow_quote hide_statuses_count), 'followers_only' + end + + context 'when remote user by server other_settings is not supported' do + let(:account) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/actor') } + + it_behaves_like 'some settings', %i(link_preview allow_quote), 'allow' + end + end + describe '#favourited?' do subject { Fabricate(:account) }