diff --git a/app/controllers/admin/domain_blocks_controller.rb b/app/controllers/admin/domain_blocks_controller.rb index a4818aa2f2..2294388b15 100644 --- a/app/controllers/admin/domain_blocks_controller.rb +++ b/app/controllers/admin/domain_blocks_controller.rb @@ -78,15 +78,15 @@ module Admin end def update_params - params.require(:domain_block).permit(:severity, :reject_media, :reject_favourite, :reject_reply, :reject_send_not_public_searchability, :reject_send_unlisted_dissubscribable, :reject_send_public_unlisted, :reject_send_dissubscribable, :reject_send_media, :reject_send_sensitive, :reject_reports, :private_comment, :public_comment, :obfuscate) + params.require(:domain_block).permit(:severity, :reject_media, :reject_favourite, :reject_reply, :reject_send_not_public_searchability, :reject_send_unlisted_dissubscribable, :reject_send_public_unlisted, :reject_send_dissubscribable, :reject_send_media, :reject_send_sensitive, :reject_hashtag, :reject_straight_follow, :reject_new_follow, :reject_reports, :private_comment, :public_comment, :obfuscate) end def resource_params - params.require(:domain_block).permit(:domain, :severity, :reject_media, :reject_favourite, :reject_reply, :reject_send_not_public_searchability, :reject_send_unlisted_dissubscribable, :reject_send_public_unlisted, :reject_send_dissubscribable, :reject_send_media, :reject_send_sensitive, :reject_reports, :private_comment, :public_comment, :obfuscate) + params.require(:domain_block).permit(:domain, :severity, :reject_media, :reject_favourite, :reject_reply, :reject_send_not_public_searchability, :reject_send_unlisted_dissubscribable, :reject_send_public_unlisted, :reject_send_dissubscribable, :reject_send_media, :reject_send_sensitive, :reject_hashtag, :reject_straight_follow, :reject_new_follow, :reject_reports, :private_comment, :public_comment, :obfuscate) end def form_domain_block_batch_params - params.require(:form_domain_block_batch).permit(domain_blocks_attributes: [:enabled, :domain, :severity, :reject_media, :reject_favourite, :reject_reply, :reject_send_not_public_searchability, :reject_send_unlisted_dissubscribable, :reject_send_public_unlisted, :reject_send_dissubscribable, :reject_send_media, :reject_send_sensitive, :reject_reports, :private_comment, :public_comment, :obfuscate]) + params.require(:form_domain_block_batch).permit(domain_blocks_attributes: [:enabled, :domain, :severity, :reject_media, :reject_favourite, :reject_reply, :reject_send_not_public_searchability, :reject_send_unlisted_dissubscribable, :reject_send_public_unlisted, :reject_send_dissubscribable, :reject_send_media, :reject_send_sensitive, :reject_hashtag, :reject_straight_follow, :reject_new_follow, :reject_reports, :private_comment, :public_comment, :obfuscate]) end def action_from_button diff --git a/app/controllers/api/v1/admin/domain_blocks_controller.rb b/app/controllers/api/v1/admin/domain_blocks_controller.rb index bbb7e2ad58..add327ff92 100644 --- a/app/controllers/api/v1/admin/domain_blocks_controller.rb +++ b/app/controllers/api/v1/admin/domain_blocks_controller.rb @@ -69,7 +69,7 @@ class Api::V1::Admin::DomainBlocksController < Api::BaseController end def domain_block_params - params.permit(:severity, :reject_media, :reject_favourite, :reject_reply, :reject_reports, :reject_send_not_public_searchability, :reject_send_unlisted_dissubscribable, :reject_send_public_unlisted, :reject_send_dissubscribable, :reject_send_media, :reject_send_sensitive, :private_comment, :public_comment, :obfuscate) + params.permit(:severity, :reject_media, :reject_favourite, :reject_reply, :reject_reports, :reject_send_not_public_searchability, :reject_send_unlisted_dissubscribable, :reject_send_public_unlisted, :reject_send_dissubscribable, :reject_send_media, :reject_send_sensitive, :reject_hashtag, :reject_straight_follow, :reject_new_follow, :private_comment, :public_comment, :obfuscate) end def insert_pagination_headers @@ -101,6 +101,6 @@ class Api::V1::Admin::DomainBlocksController < Api::BaseController end def resource_params - params.permit(:domain, :severity, :reject_media, :reject_favourite, :reject_reply, :reject_send_not_public_searchability, :reject_send_unlisted_dissubscribable, :reject_send_public_unlisted, :reject_send_dissubscribable, :reject_send_media, :reject_send_sensitive, :reject_reports, :private_comment, :public_comment, :obfuscate) + params.permit(:domain, :severity, :reject_media, :reject_favourite, :reject_reply, :reject_send_not_public_searchability, :reject_send_unlisted_dissubscribable, :reject_send_public_unlisted, :reject_send_dissubscribable, :reject_send_media, :reject_send_sensitive, :reject_hashtag, :reject_straight_follow, :reject_new_follow, :reject_reports, :private_comment, :public_comment, :obfuscate) end end diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 67f4ab4df9..db1b7fb7a5 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -216,7 +216,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity end def process_hashtag(tag) - return if tag['name'].blank? + return if tag['name'].blank? || ignore_hashtags? Tag.find_or_create_by_names(tag['name']) do |hashtag| @tags << hashtag unless @tags.include?(hashtag) || !hashtag.valid? @@ -397,6 +397,10 @@ class ActivityPub::Activity::Create < ActivityPub::Activity @reject_reply_to_local ||= DomainBlock.reject_reply?(@account.domain) end + def ignore_hashtags? + @ignore_hashtags ||= DomainBlock.reject_hashtag?(@account.domain) + end + def related_to_local_activity? fetch? || followed_by_local_accounts? || requested_through_relay? || responds_to_followed_account? || addresses_local_accounts? diff --git a/app/lib/activitypub/activity/follow.rb b/app/lib/activitypub/activity/follow.rb index 97e41ab789..3714648c01 100644 --- a/app/lib/activitypub/activity/follow.rb +++ b/app/lib/activitypub/activity/follow.rb @@ -15,7 +15,7 @@ class ActivityPub::Activity::Follow < ActivityPub::Activity return end - if target_account.blocking?(@account) || target_account.domain_blocking?(@account.domain) || target_account.moved? || target_account.instance_actor? + if target_account.blocking?(@account) || target_account.domain_blocking?(@account.domain) || target_account.moved? || target_account.instance_actor? || block_new_follow? reject_follow_request!(target_account) return end @@ -30,7 +30,7 @@ class ActivityPub::Activity::Follow < ActivityPub::Activity follow_request = FollowRequest.create!(account: @account, target_account: target_account, uri: @json['id']) - if target_account.locked? || @account.silenced? + if target_account.locked? || @account.silenced? || block_straight_follow? LocalNotificationWorker.perform_async(target_account.id, follow_request.id, 'FollowRequest', 'follow_request') else AuthorizeFollowService.new.call(@account, target_account) @@ -42,4 +42,12 @@ class ActivityPub::Activity::Follow < ActivityPub::Activity json = Oj.dump(serialize_payload(FollowRequest.new(account: @account, target_account: target_account, uri: @json['id']), ActivityPub::RejectFollowSerializer)) ActivityPub::DeliveryWorker.perform_async(json, target_account.id, @account.inbox_url) end + + def block_straight_follow? + @block_straight_follow ||= DomainBlock.reject_straight_follow?(@account.domain) + end + + def block_new_follow? + @block_new_follow ||= DomainBlock.reject_new_follow?(@account.domain) + end end diff --git a/app/models/domain_block.rb b/app/models/domain_block.rb index 9b34ecc5a1..cc34f2ab99 100644 --- a/app/models/domain_block.rb +++ b/app/models/domain_block.rb @@ -22,6 +22,9 @@ # reject_send_dissubscribable :boolean default(FALSE), not null # reject_send_media :boolean default(FALSE), not null # reject_send_sensitive :boolean default(FALSE), not null +# reject_hashtag :boolean default(FALSE), not null +# reject_straight_follow :boolean default(FALSE), not null +# reject_new_follow :boolean default(FALSE), not null # class DomainBlock < ApplicationRecord @@ -37,8 +40,8 @@ class DomainBlock < ApplicationRecord delegate :count, to: :accounts, prefix: true scope :matches_domain, ->(value) { where(arel_table[:domain].matches("%#{value}%")) } - scope :with_user_facing_limitations, -> { where(severity: [:silence, :suspend]) } - scope :with_limitations, -> { where(severity: [:silence, :suspend]).or(where(reject_media: true)).or(where(reject_favourite: true)).or(where(reject_reply: true)) } + scope :with_user_facing_limitations, -> { where(severity: [:silence, :suspend]).or(where(reject_media: true)) } + scope :with_limitations, -> { where(severity: [:silence, :suspend]).or(where(reject_media: true)).or(where(reject_favourite: true)).or(where(reject_reply: true)).or(where(reject_new_follow: true)).or(where(reject_straight_follow: true)) } scope :by_severity, -> { order(Arel.sql('(CASE severity WHEN 0 THEN 1 WHEN 1 THEN 2 WHEN 2 THEN 0 END), domain')) } def to_log_human_identifier @@ -59,6 +62,9 @@ class DomainBlock < ApplicationRecord reject_send_dissubscribable? ? :reject_send_dissubscribable : nil, reject_send_media? ? :reject_send_media : nil, reject_send_sensitive? ? :reject_send_sensitive : nil, + reject_hashtag? ? :reject_hashtag : nil, + reject_straight_follow? ? :reject_straight_follow : nil, + reject_new_follow? ? :reject_new_follow : nil, reject_reports? ? :reject_reports : nil ].reject { |policy| policy == :noop || policy.nil? } end @@ -85,6 +91,18 @@ class DomainBlock < ApplicationRecord !!rule_for(domain)&.reject_reply? end + def reject_hashtag?(domain) + !!rule_for(domain)&.reject_hashtag? + end + + def reject_straight_follow?(domain) + !!rule_for(domain)&.reject_straight_follow? + end + + def reject_new_follow?(domain) + !!rule_for(domain)&.reject_new_follow? + end + def reject_reports?(domain) !!rule_for(domain)&.reject_reports? end diff --git a/app/serializers/rest/admin/domain_block_serializer.rb b/app/serializers/rest/admin/domain_block_serializer.rb index bcc8246d99..df167cec70 100644 --- a/app/serializers/rest/admin/domain_block_serializer.rb +++ b/app/serializers/rest/admin/domain_block_serializer.rb @@ -4,7 +4,8 @@ class REST::Admin::DomainBlockSerializer < ActiveModel::Serializer attributes :id, :domain, :created_at, :severity, :reject_media, :reject_favourite, :reject_reply, :reject_reports, :reject_send_not_public_searchability, :reject_send_unlisted_dissubscribable, - :reject_send_public_unlisted, :reject_send_dissubscribable, :reject_send_media, :reject_send_sensitive, + :reject_send_public_unlisted, :reject_send_dissubscribable, :reject_send_media, :reject_send_sensitive, + :reject_hashtag, :reject_straight_follow, :reject_new_follow, :private_comment, :public_comment, :obfuscate def id diff --git a/app/services/update_account_service.rb b/app/services/update_account_service.rb index 4604d71b2b..ee5e567292 100644 --- a/app/services/update_account_service.rb +++ b/app/services/update_account_service.rb @@ -21,12 +21,16 @@ class UpdateAccountService < BaseService def authorize_all_follow_requests(account) follow_requests = FollowRequest.where(target_account: account) - follow_requests = follow_requests.preload(:account).select { |req| !req.account.silenced? } + follow_requests = follow_requests.preload(:account).select { |req| !req.account.silenced? && !reject_straight_follow_domains.include?(req.account.domain) } AuthorizeFollowWorker.push_bulk(follow_requests, limit: 1_000) do |req| [req.account_id, req.target_account_id] end end + def reject_straight_follow_domains + DomainBlock.where(reject_straight_follow: true).pluck(:domain) + end + def check_links(account) VerifyAccountLinksWorker.perform_async(account.id) if account.fields.any?(&:requires_verification?) end diff --git a/app/views/admin/domain_blocks/edit.html.haml b/app/views/admin/domain_blocks/edit.html.haml index b433d88ee5..da37cea2c2 100644 --- a/app/views/admin/domain_blocks/edit.html.haml +++ b/app/views/admin/domain_blocks/edit.html.haml @@ -30,10 +30,10 @@ = f.input :reject_send_unlisted_dissubscribable, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_send_unlisted_dissubscribable'), hint: I18n.t('admin.domain_blocks.reject_send_unlisted_dissubscribable_hint') .fields-group - = f.input :reject_send_public_unlisted, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_send_public_unlisted'), hint: I18n.t('admin.domain_blocks.reject_send_public_unlisted_hint') + = f.input :reject_send_dissubscribable, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_send_dissubscribable'), hint: I18n.t('admin.domain_blocks.reject_send_dissubscribable_hint') .fields-group - = f.input :reject_send_dissubscribable, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_send_dissubscribable'), hint: I18n.t('admin.domain_blocks.reject_send_dissubscribable_hint') + = f.input :reject_send_public_unlisted, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_send_public_unlisted'), hint: I18n.t('admin.domain_blocks.reject_send_public_unlisted_hint') .fields-group = f.input :reject_send_media, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_send_media'), hint: I18n.t('admin.domain_blocks.reject_send_media_hint') @@ -41,6 +41,15 @@ .fields-group = f.input :reject_send_sensitive, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_send_sensitive'), hint: I18n.t('admin.domain_blocks.reject_send_sensitive_hint') + .fields-group + = f.input :reject_hashtag, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_hashtag'), hint: I18n.t('admin.domain_blocks.reject_hashtag_hint') + + .fields-group + = f.input :reject_straight_follow, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_straight_follow'), hint: I18n.t('admin.domain_blocks.reject_straight_follow_hint') + + .fields-group + = f.input :reject_new_follow, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_new_follow'), hint: I18n.t('admin.domain_blocks.reject_new_follow_hint') + .fields-group = f.input :reject_reports, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_reports'), hint: I18n.t('admin.domain_blocks.reject_reports_hint') diff --git a/app/views/admin/domain_blocks/new.html.haml b/app/views/admin/domain_blocks/new.html.haml index 68be819bb7..8f7f31ebe9 100644 --- a/app/views/admin/domain_blocks/new.html.haml +++ b/app/views/admin/domain_blocks/new.html.haml @@ -30,10 +30,10 @@ = f.input :reject_send_unlisted_dissubscribable, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_send_unlisted_dissubscribable'), hint: I18n.t('admin.domain_blocks.reject_send_unlisted_dissubscribable_hint') .fields-group - = f.input :reject_send_public_unlisted, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_send_public_unlisted'), hint: I18n.t('admin.domain_blocks.reject_send_public_unlisted_hint') + = f.input :reject_send_dissubscribable, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_send_dissubscribable'), hint: I18n.t('admin.domain_blocks.reject_send_dissubscribable_hint') .fields-group - = f.input :reject_send_dissubscribable, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_send_dissubscribable'), hint: I18n.t('admin.domain_blocks.reject_send_dissubscribable_hint') + = f.input :reject_send_public_unlisted, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_send_public_unlisted'), hint: I18n.t('admin.domain_blocks.reject_send_public_unlisted_hint') .fields-group = f.input :reject_send_media, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_send_media'), hint: I18n.t('admin.domain_blocks.reject_send_media_hint') @@ -41,6 +41,15 @@ .fields-group = f.input :reject_send_sensitive, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_send_sensitive'), hint: I18n.t('admin.domain_blocks.reject_send_sensitive_hint') + .fields-group + = f.input :reject_hashtag, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_hashtag'), hint: I18n.t('admin.domain_blocks.reject_hashtag_hint') + + .fields-group + = f.input :reject_straight_follow, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_straight_follow'), hint: I18n.t('admin.domain_blocks.reject_straight_follow_hint') + + .fields-group + = f.input :reject_new_follow, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_new_follow'), hint: I18n.t('admin.domain_blocks.reject_new_follow_hint') + .fields-group = f.input :reject_reports, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_reports'), hint: I18n.t('admin.domain_blocks.reject_reports_hint') diff --git a/app/views/admin/export_domain_blocks/_domain_block.html.haml b/app/views/admin/export_domain_blocks/_domain_block.html.haml index 9919ce29ab..8054b5ab2a 100644 --- a/app/views/admin/export_domain_blocks/_domain_block.html.haml +++ b/app/views/admin/export_domain_blocks/_domain_block.html.haml @@ -18,6 +18,9 @@ = f.hidden_field :reject_send_dissubscribable = f.hidden_field :reject_send_media = f.hidden_field :reject_send_sensitive + = f.hidden_field :reject_hashtag + = f.hidden_field :reject_straight_follow + = f.hidden_field :reject_new_follow = f.hidden_field :reject_reports = f.hidden_field :obfuscate = f.hidden_field :private_comment diff --git a/config/locales/en.yml b/config/locales/en.yml index 7cbd8761fd..2a6f7249e8 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -414,8 +414,12 @@ en: public_comment_hint: Comment about this domain limitation for the general public, if advertising the list of domain limitations is enabled. reject_favourite: Reject favourites reject_favourite_hint: Reject favourites or emoji-reaction in the future + reject_hashtag: Reject hashtags + reject_hashtag_hint: Reject hashtags in the future reject_media: Reject media files reject_media_hint: Removes locally stored media files and refuses to download any in the future. Irrelevant for suspensions + reject_new_follow: Reject follows + reject_new_follow_hint: Reject follows in the future reject_reply: Reject replies reject_reply_hint: Reject replies in the future reject_reports: Reject reports @@ -432,6 +436,8 @@ en: reject_send_sensitive_hint: 相手サーバーからのフェッチは防げません。停止とは無関係です reject_send_unlisted_dissubscribable: 購読拒否アカウントの未収載投稿を配送しない reject_send_unlisted_dissubscribable_hint: 相手サーバーからのフェッチは防げません。停止とは無関係です + reject_straight_follow: Reject straight follow + reject_straight_follow_hint: The server accounts must be authenticated when follow our accounts undo: Undo domain block view: View domain block email_domain_blocks: @@ -500,7 +506,10 @@ en: limited_federation_mode_description_html: You can chose whether to allow federation with this domain. policies: reject_favourite: Reject favourite + reject_hashtag: Reject hashtags reject_media: Reject media + reject_new_follow: Reject follows + reject_straight_follow: Reject straight follow reject_reply: Reject reply reject_reports: Reject reports silence: Limit diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 970f9c0d71..9b706a4d45 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -407,8 +407,12 @@ ja: public_comment_hint: ドメインブロックの公開を有効にしている場合、このコメントも公開されます。 reject_favourite: お気に入り、絵文字リアクションを拒否 reject_favourite_hint: 今後のお気に入り、絵文字リアクションを拒否します。停止とは無関係です + reject_hashtag: ハッシュタグを拒否 + reject_hashtag_hint: ハッシュタグで検索できなくなり、トレンドにも影響しなくなります。停止とは無関係です reject_media: メディアファイルを拒否 reject_media_hint: ローカルに保存されたメディアファイルを削除し、今後のダウンロードを拒否します。停止とは無関係です + reject_new_follow: 新規フォローを拒否 + reject_new_follow_hint: 今後の新規フォローを拒否します。停止とは無関係です reject_reply: リプライを拒否 reject_reply_hint: 今後のリプライを拒否します。停止とは無関係です reject_reports: 通報を拒否 @@ -425,6 +429,8 @@ ja: reject_send_sensitive_hint: 相手サーバーからのフェッチは防げません。停止とは無関係です reject_send_unlisted_dissubscribable: 購読拒否アカウントの未収載投稿を配送しない reject_send_unlisted_dissubscribable_hint: 相手サーバーからのフェッチは防げません。停止とは無関係です + reject_straight_follow: フォローを強制的に審査制にする + reject_straight_follow_hint: 相手からのフォローは当サーバーのアカウントの承認が必須になります undo: ドメインブロックを戻す view: ドメインブロックを表示 email_domain_blocks: @@ -490,7 +496,9 @@ ja: limited_federation_mode_description_html: このドメインとの連合を許可するかどうかを選択できます。 policies: reject_favourite: お気に入りを拒否 + reject_hashtag: ハッシュタグを拒否 reject_media: メディアを拒否する + reject_new_follow: 新規フォローを拒否 reject_reply: リプライを拒否 reject_reports: 通報を拒否 reject_send_dissubscribable: 購読拒否投稿配送なし @@ -499,6 +507,7 @@ ja: reject_send_public_unlisted: ローカル公開投稿配送なし reject_send_sensitive: センシティブ投稿配送なし reject_send_unlisted_dissubscribable: 購読拒否未収載投稿配送なし + reject_straight_follow: フォローを制限 silence: 制限 suspend: サスペンド policy: ポリシー diff --git a/db/migrate/20230427122753_add_some_to_domain_blocks.rb b/db/migrate/20230427122753_add_some_to_domain_blocks.rb new file mode 100644 index 0000000000..b553af4cca --- /dev/null +++ b/db/migrate/20230427122753_add_some_to_domain_blocks.rb @@ -0,0 +1,7 @@ +class AddSomeToDomainBlocks < ActiveRecord::Migration[6.1] + def change + add_column :domain_blocks, :reject_hashtag, :boolean, null: false, default: false + add_column :domain_blocks, :reject_straight_follow, :boolean, null: false, default: false + add_column :domain_blocks, :reject_new_follow, :boolean, null: false, default: false + end +end diff --git a/db/schema.rb b/db/schema.rb index df5bd58832..b12919be4e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2023_04_27_072650) do +ActiveRecord::Schema.define(version: 2023_04_27_122753) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -476,6 +476,9 @@ ActiveRecord::Schema.define(version: 2023_04_27_072650) do t.boolean "reject_send_dissubscribable", default: false, null: false t.boolean "reject_send_media", default: false, null: false t.boolean "reject_send_sensitive", default: false, null: false + t.boolean "reject_hashtag", default: false, null: false + t.boolean "reject_straight_follow", default: false, null: false + t.boolean "reject_new_follow", default: false, null: false t.index ["domain"], name: "index_domain_blocks_on_domain", unique: true end