From 3ffc470a031010abfae782cae614571781a122fb Mon Sep 17 00:00:00 2001 From: KMY Date: Fri, 28 Apr 2023 21:37:01 +0900 Subject: [PATCH 01/10] Fix more better sql of domainblock --- app/lib/status_reach_finder.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/lib/status_reach_finder.rb b/app/lib/status_reach_finder.rb index 63a4f23740..924879ccdc 100644 --- a/app/lib/status_reach_finder.rb +++ b/app/lib/status_reach_finder.rb @@ -96,13 +96,13 @@ class StatusReachFinder def banned_domains return @banned_domains if @banned_domains - blocks = [] - blocks << DomainBlock.where(reject_send_not_public_searchability: true).pluck(:domain) if @status.compute_searchability != 'public' - blocks << DomainBlock.where(reject_send_unlisted_dissubscribable: true).pluck(:domain) if @status.unlisted_visibility? && @status.account.dissubscribable - blocks << DomainBlock.where(reject_send_public_unlisted: true).pluck(:domain) if @status.public_unlisted_visibility? - blocks << DomainBlock.where(reject_send_dissubscribable: true).pluck(:domain) if @status.account.dissubscribable - blocks << DomainBlock.where(reject_send_media: true).pluck(:domain) if @status.with_media? - blocks << DomainBlock.where(reject_send_sensitive: true).pluck(:domain) if (@status.with_media? && @status.sensitive) || @status.spoiler_text - return @banned_domains = blocks.uniq + blocks = DomainBlock.where(domain: nil) + blocks = blocks.or(DomainBlock.where(reject_send_not_public_searchability: true)) if @status.compute_searchability != 'public' + blocks = blocks.or(DomainBlock.where(reject_send_unlisted_dissubscribable: true)) if @status.unlisted_visibility? && @status.account.dissubscribable + blocks = blocks.or(DomainBlock.where(reject_send_public_unlisted: true)) if @status.public_unlisted_visibility? + blocks = blocks.or(DomainBlock.where(reject_send_dissubscribable: true)) if @status.account.dissubscribable + blocks = blocks.or(DomainBlock.where(reject_send_media: true)) if @status.with_media? + blocks = blocks.or(DomainBlock.where(reject_send_sensitive: true)) if (@status.with_media? && @status.sensitive) || @status.spoiler_text + return @banned_domains = blocks.pluck(:domain).uniq end end From ae4da450540d9f0aa9ea13574bfedc9ecb484d1e Mon Sep 17 00:00:00 2001 From: KMY Date: Sun, 30 Apr 2023 19:57:05 +0900 Subject: [PATCH 02/10] Add considering reblogged status domain block --- app/lib/status_reach_finder.rb | 21 ++++++++++++++------- app/policies/status_policy.rb | 22 +++++++++++++++------- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/app/lib/status_reach_finder.rb b/app/lib/status_reach_finder.rb index 924879ccdc..be537896d3 100644 --- a/app/lib/status_reach_finder.rb +++ b/app/lib/status_reach_finder.rb @@ -96,13 +96,20 @@ class StatusReachFinder def banned_domains return @banned_domains if @banned_domains + + domains = banned_domains_of_status(@status) + domains = domains + banned_domains_of_status(@status.reblog) if @status.reblog? + return @banned_domains = domains + end + + def banned_domains_of_status(status) blocks = DomainBlock.where(domain: nil) - blocks = blocks.or(DomainBlock.where(reject_send_not_public_searchability: true)) if @status.compute_searchability != 'public' - blocks = blocks.or(DomainBlock.where(reject_send_unlisted_dissubscribable: true)) if @status.unlisted_visibility? && @status.account.dissubscribable - blocks = blocks.or(DomainBlock.where(reject_send_public_unlisted: true)) if @status.public_unlisted_visibility? - blocks = blocks.or(DomainBlock.where(reject_send_dissubscribable: true)) if @status.account.dissubscribable - blocks = blocks.or(DomainBlock.where(reject_send_media: true)) if @status.with_media? - blocks = blocks.or(DomainBlock.where(reject_send_sensitive: true)) if (@status.with_media? && @status.sensitive) || @status.spoiler_text - return @banned_domains = blocks.pluck(:domain).uniq + blocks = blocks.or(DomainBlock.where(reject_send_not_public_searchability: true)) if status.compute_searchability != 'public' + blocks = blocks.or(DomainBlock.where(reject_send_unlisted_dissubscribable: true)) if status.unlisted_visibility? && status.account.dissubscribable + blocks = blocks.or(DomainBlock.where(reject_send_public_unlisted: true)) if status.public_unlisted_visibility? + blocks = blocks.or(DomainBlock.where(reject_send_dissubscribable: true)) if status.account.dissubscribable + blocks = blocks.or(DomainBlock.where(reject_send_media: true)) if status.with_media? + blocks = blocks.or(DomainBlock.where(reject_send_sensitive: true)) if (status.with_media? && status.sensitive) || status.spoiler_text? + blocks.pluck(:domain).uniq end end diff --git a/app/policies/status_policy.rb b/app/policies/status_policy.rb index 5d2bf17da6..75b9b28eff 100644 --- a/app/policies/status_policy.rb +++ b/app/policies/status_policy.rb @@ -101,14 +101,22 @@ class StatusPolicy < ApplicationPolicy end def server_blocking_domain? - @domain_block = DomainBlock.find_by(domain: current_account&.domain) + if record.reblog? + server_blocking_domain_of_status(record) || server_blocking_domain_of_status(record.reblog) + else + server_blocking_domain_of_status(record) + end + end + + def server_blocking_domain_of_status?(status) + @domain_block ||= DomainBlock.find_by(domain: current_account&.domain) if @domain_block - (@domain_block.reject_send_not_public_searchability && record.compute_searchability != 'public') || - (@domain_block.reject_send_unlisted_dissubscribable && record.unlisted_visibility? && record.account.dissubscribable) || - (@domain_block.reject_send_public_unlisted && record.public_unlisted_visibility?) || - (@domain_block.reject_send_dissubscribable && record.account.dissubscribable) || - (@domain_block.reject_send_media && record.with_media?) || - (@domain_block.reject_send_sensitive && ((record.with_media? && record.sensitive) || record.spoiler_text)) + (@domain_block.reject_send_not_public_searchability && status.compute_searchability != 'public') || + (@domain_block.reject_send_unlisted_dissubscribable && status.unlisted_visibility? && status.account.dissubscribable) || + (@domain_block.reject_send_public_unlisted && status.public_unlisted_visibility?) || + (@domain_block.reject_send_dissubscribable && status.account.dissubscribable) || + (@domain_block.reject_send_media && status.with_media?) || + (@domain_block.reject_send_sensitive && ((status.with_media? && status.sensitive) || status.spoiler_text?)) else false end From 7d3d93e9a41657ce8f98c46efc2a2f34de3f96a9 Mon Sep 17 00:00:00 2001 From: KMY Date: Sun, 30 Apr 2023 21:36:49 +0900 Subject: [PATCH 03/10] Add reject public unlisted subscription configs --- app/controllers/admin/domain_blocks_controller.rb | 6 +++--- .../api/v1/admin/domain_blocks_controller.rb | 4 ++-- app/controllers/settings/preferences_controller.rb | 2 ++ app/lib/status_reach_finder.rb | 3 ++- app/lib/user_settings_decorator.rb | 10 ++++++++++ app/models/account.rb | 1 + app/models/account_statuses_filter.rb | 4 ++-- app/models/domain_block.rb | 4 ++-- app/models/user.rb | 1 + app/policies/status_policy.rb | 3 ++- app/serializers/rest/admin/domain_block_serializer.rb | 4 ++-- app/views/admin/domain_blocks/edit.html.haml | 6 +++--- app/views/admin/domain_blocks/new.html.haml | 6 +++--- .../admin/export_domain_blocks/_domain_block.html.haml | 2 +- app/views/settings/preferences/other/show.html.haml | 6 ++++++ config/locales/en.yml | 2 ++ config/locales/ja.yml | 3 +++ config/locales/simple_form.en.yml | 2 ++ config/locales/simple_form.ja.yml | 3 +++ ...add_reject_invalid_subscription_to_domain_blocks.rb | 8 ++++++++ db/schema.rb | 5 +++-- 21 files changed, 63 insertions(+), 22 deletions(-) create mode 100644 db/migrate/20230430110057_add_reject_invalid_subscription_to_domain_blocks.rb diff --git a/app/controllers/admin/domain_blocks_controller.rb b/app/controllers/admin/domain_blocks_controller.rb index 557ad57bef..8a28410230 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_hashtag, :reject_straight_follow, :reject_new_follow, :reject_reports, :private_comment, :public_comment, :obfuscate, :hidden, :hidden_anonymous) + params.require(:domain_block).permit(:severity, :reject_media, :reject_favourite, :reject_reply, :reject_send_not_public_searchability, :reject_send_public_unlisted, :reject_send_dissubscribable, :reject_send_media, :reject_send_sensitive, :reject_hashtag, :reject_straight_follow, :reject_new_follow, :detect_invalid_subscription, :reject_reports, :private_comment, :public_comment, :obfuscate, :hidden, :hidden_anonymous) 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_hashtag, :reject_straight_follow, :reject_new_follow, :reject_reports, :private_comment, :public_comment, :obfuscate, :hidden, :hidden_anonymous) + params.require(:domain_block).permit(:domain, :severity, :reject_media, :reject_favourite, :reject_reply, :reject_send_not_public_searchability, :reject_send_public_unlisted, :reject_send_dissubscribable, :reject_send_media, :reject_send_sensitive, :reject_hashtag, :reject_straight_follow, :reject_new_follow, :detect_invalid_subscription, :reject_reports, :private_comment, :public_comment, :obfuscate, :hidden, :hidden_anonymous) 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_hashtag, :reject_straight_follow, :reject_new_follow, :reject_reports, :private_comment, :public_comment, :obfuscate, :hidden, :hidden_anonymous]) + 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_public_unlisted, :reject_send_dissubscribable, :reject_send_media, :reject_send_sensitive, :reject_hashtag, :reject_straight_follow, :reject_new_follow, :detect_invalid_subscription, :reject_reports, :private_comment, :public_comment, :obfuscate, :hidden, :hidden_anonymous]) 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 a981fba005..c2995902b9 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, :reject_hashtag, :reject_straight_follow, :reject_new_follow, :private_comment, :public_comment, :obfuscate, :hidden, :hidden_anonymous) + params.permit(:severity, :reject_media, :reject_favourite, :reject_reply, :reject_reports, :reject_send_not_public_searchability, :reject_send_public_unlisted, :reject_send_dissubscribable, :reject_send_media, :reject_send_sensitive, :reject_hashtag, :reject_straight_follow, :reject_new_follow, :detect_invalid_subscription, :private_comment, :public_comment, :obfuscate, :hidden, :hidden_anonymous) 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_hashtag, :reject_straight_follow, :reject_new_follow, :reject_reports, :private_comment, :public_comment, :obfuscate, :hidden, :hidden_anonymous) + params.permit(:domain, :severity, :reject_media, :reject_favourite, :reject_reply, :reject_send_not_public_searchability, :reject_send_public_unlisted, :reject_send_dissubscribable, :reject_send_media, :reject_send_sensitive, :reject_hashtag, :reject_straight_follow, :reject_new_follow, :detect_invalid_subscription, :reject_reports, :private_comment, :public_comment, :obfuscate, :hidden, :hidden_anonymous) end end diff --git a/app/controllers/settings/preferences_controller.rb b/app/controllers/settings/preferences_controller.rb index f6e14ba853..e7a047369c 100644 --- a/app/controllers/settings/preferences_controller.rb +++ b/app/controllers/settings/preferences_controller.rb @@ -37,6 +37,8 @@ class Settings::PreferencesController < Settings::BaseController :setting_default_searchability, :setting_default_sensitive, :setting_public_post_to_unlisted, + :setting_reject_public_unlisted_subscription, + :setting_reject_unlisted_subscription, :setting_default_language, :setting_unfollow_modal, :setting_boost_modal, diff --git a/app/lib/status_reach_finder.rb b/app/lib/status_reach_finder.rb index be537896d3..56c3f6e49b 100644 --- a/app/lib/status_reach_finder.rb +++ b/app/lib/status_reach_finder.rb @@ -105,9 +105,10 @@ class StatusReachFinder def banned_domains_of_status(status) blocks = DomainBlock.where(domain: nil) blocks = blocks.or(DomainBlock.where(reject_send_not_public_searchability: true)) if status.compute_searchability != 'public' - blocks = blocks.or(DomainBlock.where(reject_send_unlisted_dissubscribable: true)) if status.unlisted_visibility? && status.account.dissubscribable blocks = blocks.or(DomainBlock.where(reject_send_public_unlisted: true)) if status.public_unlisted_visibility? blocks = blocks.or(DomainBlock.where(reject_send_dissubscribable: true)) if status.account.dissubscribable + blocks = blocks.or(DomainBlock.where(detect_invalid_subscription: true)) if status.public_unlisted_visibility? && status.account.user&.setting_reject_public_unlisted_subscription + blocks = blocks.or(DomainBlock.where(detect_invalid_subscription: true)) if status.unlisted_visibility? && status.account.user&.setting_reject_unlisted_subscription blocks = blocks.or(DomainBlock.where(reject_send_media: true)) if status.with_media? blocks = blocks.or(DomainBlock.where(reject_send_sensitive: true)) if (status.with_media? && status.sensitive) || status.spoiler_text? blocks.pluck(:domain).uniq diff --git a/app/lib/user_settings_decorator.rb b/app/lib/user_settings_decorator.rb index 28784b8857..3354c5fa23 100644 --- a/app/lib/user_settings_decorator.rb +++ b/app/lib/user_settings_decorator.rb @@ -21,6 +21,8 @@ class UserSettingsDecorator user.settings['default_searchability']=default_searchability_preference if change?('setting_default_searchability') user.settings['default_sensitive'] = default_sensitive_preference if change?('setting_default_sensitive') user.settings['public_post_to_unlisted']=public_post_to_unlisted_preference if change?('setting_public_post_to_unlisted') + user.settings['reject_public_unlisted_subscription'] = reject_public_unlisted_subscription_preference if change?('setting_reject_public_unlisted_subscription') + user.settings['reject_unlisted_subscription'] = reject_unlisted_subscription_preference if change?('setting_reject_unlisted_subscription') user.settings['default_language'] = default_language_preference if change?('setting_default_language') user.settings['unfollow_modal'] = unfollow_modal_preference if change?('setting_unfollow_modal') user.settings['boost_modal'] = boost_modal_preference if change?('setting_boost_modal') @@ -68,6 +70,14 @@ class UserSettingsDecorator boolean_cast_setting 'setting_public_post_to_unlisted' end + def reject_public_unlisted_subscription_preference + boolean_cast_setting 'setting_reject_public_unlisted_subscription_preference' + end + + def reject_unlisted_subscription_preference + boolean_cast_setting 'setting_reject_unlisted_subscription_preference' + end + def unfollow_modal_preference boolean_cast_setting 'setting_unfollow_modal' end diff --git a/app/models/account.rb b/app/models/account.rb index c6a7cdd708..a6a65e2ae7 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -53,6 +53,7 @@ # group_allow_private_message :boolean # searchability :integer default("private"), not null # dissubscribable :boolean default(FALSE), not null +# stop_emoji_reaction_streaming :boolean default(FALSE) # class Account < ApplicationRecord diff --git a/app/models/account_statuses_filter.rb b/app/models/account_statuses_filter.rb index d0a1cc5518..11750b8606 100644 --- a/app/models/account_statuses_filter.rb +++ b/app/models/account_statuses_filter.rb @@ -27,8 +27,8 @@ class AccountStatusesFilter scope.merge!(hashtag_scope) if tagged? scope.merge!(scope.where(searchability: :public)) if domain_block&.reject_send_not_public_searchability - scope.merge!(scope.where.not(visibility: :unlisted)) if domain_block&.reject_send_unlisted_dissubscribable && @account.dissubscribable - scope.merge!(scope.where.not(visibility: :public_unlisted)) if domain_block&.reject_send_public_unlisted + scope.merge!(scope.where.not(visibility: :public_unlisted)) if domain_block&.reject_send_public_unlisted || (domain_block&.detect_invalid_subscription && @account.user&.setting_reject_public_unlisted_subscription) + scope.merge!(scope.where.not(visibility: :unlisted)) if domain_block&.detect_invalid_subscription && @account.user&.setting_unlisted_subscription scope.merge!(scope.where(spoiler_text: ['', nil])) if domain_block&.reject_send_sensitive scope diff --git a/app/models/domain_block.rb b/app/models/domain_block.rb index f0cb28feec..512885ef27 100644 --- a/app/models/domain_block.rb +++ b/app/models/domain_block.rb @@ -17,7 +17,6 @@ # reject_favourite :boolean default(FALSE), not null # reject_reply :boolean default(FALSE), not null # reject_send_not_public_searchability :boolean default(FALSE), not null -# reject_send_unlisted_dissubscribable :boolean default(FALSE), not null # reject_send_public_unlisted :boolean default(FALSE), not null # reject_send_dissubscribable :boolean default(FALSE), not null # reject_send_media :boolean default(FALSE), not null @@ -27,6 +26,7 @@ # reject_new_follow :boolean default(FALSE), not null # hidden :boolean default(FALSE), not null # hidden_anonymous :boolean default(FALSE), not null +# detect_invalid_subscription :boolean default(FALSE), not null # class DomainBlock < ApplicationRecord @@ -59,7 +59,6 @@ class DomainBlock < ApplicationRecord reject_favourite? ? :reject_favourite : nil, reject_reply? ? :reject_reply : nil, reject_send_not_public_searchability? ? :reject_send_not_public_searchability : nil, - reject_send_unlisted_dissubscribable? ? :reject_send_unlisted_dissubscribable : nil, reject_send_public_unlisted? ? :reject_send_public_unlisted : nil, reject_send_dissubscribable? ? :reject_send_dissubscribable : nil, reject_send_media? ? :reject_send_media : nil, @@ -67,6 +66,7 @@ class DomainBlock < ApplicationRecord reject_hashtag? ? :reject_hashtag : nil, reject_straight_follow? ? :reject_straight_follow : nil, reject_new_follow? ? :reject_new_follow : nil, + detect_invalid_subscription? ? :detect_invalid_subscription : nil, reject_reports? ? :reject_reports : nil ].reject { |policy| policy == :noop || policy.nil? } end diff --git a/app/models/user.rb b/app/models/user.rb index b782a13fa1..0f945c7805 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -138,6 +138,7 @@ class User < ApplicationRecord :expand_spoilers, :default_language, :aggregate_reblogs, :show_application, :advanced_layout, :use_blurhash, :use_pending_items, :trends, :crop_images, :disable_swiping, :always_send_emails, :public_post_to_unlisted, + :reject_public_unlisted_subscription, :reject_unlisted_subscription, to: :settings, prefix: :setting, allow_nil: false delegate :can?, to: :role diff --git a/app/policies/status_policy.rb b/app/policies/status_policy.rb index 75b9b28eff..c67739eb5d 100644 --- a/app/policies/status_policy.rb +++ b/app/policies/status_policy.rb @@ -112,9 +112,10 @@ class StatusPolicy < ApplicationPolicy @domain_block ||= DomainBlock.find_by(domain: current_account&.domain) if @domain_block (@domain_block.reject_send_not_public_searchability && status.compute_searchability != 'public') || - (@domain_block.reject_send_unlisted_dissubscribable && status.unlisted_visibility? && status.account.dissubscribable) || (@domain_block.reject_send_public_unlisted && status.public_unlisted_visibility?) || (@domain_block.reject_send_dissubscribable && status.account.dissubscribable) || + (@domain_block.detect_invalid_subscription && status.public_unlisted_visibility? && status.account.user&.setting_reject_public_unlisted_subscription) || + (@domain_block.detect_invalid_subscription && status.public_visibility? && status.account.user&.setting_reject_unlisted_subscription) || (@domain_block.reject_send_media && status.with_media?) || (@domain_block.reject_send_sensitive && ((status.with_media? && status.sensitive) || status.spoiler_text?)) else diff --git a/app/serializers/rest/admin/domain_block_serializer.rb b/app/serializers/rest/admin/domain_block_serializer.rb index df167cec70..1177a23404 100644 --- a/app/serializers/rest/admin/domain_block_serializer.rb +++ b/app/serializers/rest/admin/domain_block_serializer.rb @@ -3,9 +3,9 @@ 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_not_public_searchability, :reject_send_public_unlisted, :reject_send_dissubscribable, :reject_send_media, :reject_send_sensitive, - :reject_hashtag, :reject_straight_follow, :reject_new_follow, + :reject_hashtag, :reject_straight_follow, :reject_new_follow, :detect_invalid_subscription, :private_comment, :public_comment, :obfuscate def id diff --git a/app/views/admin/domain_blocks/edit.html.haml b/app/views/admin/domain_blocks/edit.html.haml index aea62d51c8..b56237f618 100644 --- a/app/views/admin/domain_blocks/edit.html.haml +++ b/app/views/admin/domain_blocks/edit.html.haml @@ -26,9 +26,6 @@ .fields-group = f.input :reject_send_not_public_searchability, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_send_not_public_searchability'), hint: I18n.t('admin.domain_blocks.reject_send_not_public_searchability_hint') - .fields-group - = 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_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') @@ -50,6 +47,9 @@ .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 :detect_invalid_subscription, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.detect_invalid_subscription'), hint: I18n.t('admin.domain_blocks.detect_invalid_subscription_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 470cf52cea..b34038d10d 100644 --- a/app/views/admin/domain_blocks/new.html.haml +++ b/app/views/admin/domain_blocks/new.html.haml @@ -26,9 +26,6 @@ .fields-group = f.input :reject_send_not_public_searchability, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_send_not_public_searchability'), hint: I18n.t('admin.domain_blocks.reject_send_not_public_searchability_hint') - .fields-group - = 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_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') @@ -50,6 +47,9 @@ .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 :detect_invalid_subscription, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.detect_invalid_subscription'), hint: I18n.t('admin.domain_blocks.detect_invalid_subscription_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 8054b5ab2a..f38353aae5 100644 --- a/app/views/admin/export_domain_blocks/_domain_block.html.haml +++ b/app/views/admin/export_domain_blocks/_domain_block.html.haml @@ -13,7 +13,6 @@ = f.hidden_field :reject_favourite = f.hidden_field :reject_reply = f.hidden_field :reject_send_not_public_searchability - = f.hidden_field :reject_send_unlisted_dissubscribable = f.hidden_field :reject_send_public_unlisted = f.hidden_field :reject_send_dissubscribable = f.hidden_field :reject_send_media @@ -21,6 +20,7 @@ = f.hidden_field :reject_hashtag = f.hidden_field :reject_straight_follow = f.hidden_field :reject_new_follow + = f.hidden_field :detect_invalid_subscription = f.hidden_field :reject_reports = f.hidden_field :obfuscate = f.hidden_field :private_comment diff --git a/app/views/settings/preferences/other/show.html.haml b/app/views/settings/preferences/other/show.html.haml index 8edcfb0b7f..69330e83cf 100644 --- a/app/views/settings/preferences/other/show.html.haml +++ b/app/views/settings/preferences/other/show.html.haml @@ -34,6 +34,12 @@ .fields-group = f.input :setting_show_application, as: :boolean, wrapper: :with_label, recommended: true + .fields-group + = f.input :setting_reject_public_unlisted_subscription, as: :boolean, wrapper: :with_label + + .fields-group + = f.input :setting_reject_unlisted_subscription, as: :boolean, wrapper: :with_label + %h4= t 'preferences.public_timelines' .fields-group diff --git a/config/locales/en.yml b/config/locales/en.yml index 527189dfa9..c74cad58b3 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -389,6 +389,8 @@ en: add_new: Add new domain block created_msg: Domain block is now being processed destroyed_msg: Domain block has been undone + detect_invalid_subscription: 不正な購読を行うサーバーとしてマークする + detect_invalid_subscription_hint: Misskey、Calckeyなどは購読機能で未フォローユーザーの未収載投稿を拾います。これをマークしたサーバーは、ユーザーが任意で配送を拒否できます。停止とは無関係です domain: Domain edit: Edit domain block existing_domain_block: You have already imposed stricter limits on %{name}. diff --git a/config/locales/ja.yml b/config/locales/ja.yml index b861230170..e79ba26023 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -382,6 +382,8 @@ ja: add_new: ドメインブロックを追加 created_msg: ドメインブロック処理を完了しました destroyed_msg: ドメインブロックを外しました + detect_invalid_subscription: 不正な購読を行うサーバーとしてマークする + detect_invalid_subscription_hint: Misskey、Calckeyなどは購読機能で未フォローユーザーの未収載投稿を拾います。これをマークしたサーバーは、ユーザーが任意で配送を拒否できます。停止とは無関係です domain: ドメイン edit: ドメインブロックを編集 existing_domain_block: あなたは既に%{name}さんに厳しい制限を課しています。 @@ -499,6 +501,7 @@ ja: description_html: このドメインとそのサブドメインのすべてのアカウントに適用されるコンテンツポリシーを定義できます。 limited_federation_mode_description_html: このドメインとの連合を許可するかどうかを選択できます。 policies: + detect_invalid_subscription: 購読のプライバシーなし reject_favourite: お気に入りを拒否 reject_hashtag: ハッシュタグを拒否 reject_media: メディアを拒否する diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml index 73b780a478..4d5fd1dbc0 100644 --- a/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -222,6 +222,8 @@ en: setting_noindex: Opt-out of search engine indexing setting_public_post_to_unlisted: Convert public post to public unlisted if not using Web app setting_reduce_motion: Reduce motion in animations + setting_reject_public_unlisted_subscription: Reject sending public unlisted posts to Misskey, Calckey + setting_reject_unlisted_subscription: Reject sending unlisted posts to Misskey, Calckey setting_show_application: Disclose application used to send posts setting_system_font_ui: Use system's default font setting_theme: Site theme diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml index 608f8cf458..545c0145b2 100644 --- a/config/locales/simple_form.ja.yml +++ b/config/locales/simple_form.ja.yml @@ -62,6 +62,7 @@ ja: setting_display_media_expand: Misskeyなどは4個を超えて投稿可能です。その追加分を最大8個まで表示します。kmyblueからアップロードはできません setting_noindex: 公開プロフィールおよび各投稿ページに影響します setting_public_post_to_unlisted: 未対応のサードパーティアプリからもローカル公開で投稿できますが、公開投稿はWeb以外できなくなります + setting_reject_unlisted_subscription: Misskeyやそのフォーク(Calckeyなど)は、フォローしていないアカウントの「未収載」投稿を **購読・検索** することができます。これはMastodonにおける「未収載」投稿の基本的な考え方、扱い方と矛盾します。そのようなサーバーのうち管理人が指定したものに、指定した公開範囲の投稿を配送しません。ただし構造上、完璧な配送停止は困難であること、ご理解ください setting_show_application: 投稿するのに使用したアプリが投稿の詳細ビューに表示されるようになります setting_use_blurhash: ぼかしはメディアの色を元に生成されますが、細部は見えにくくなっています setting_use_pending_items: 新着があってもタイムラインを自動的にスクロールしないようにします @@ -224,6 +225,8 @@ ja: setting_noindex: 検索エンジンによるインデックスを拒否する setting_public_post_to_unlisted: サードパーティアプリから投稿するとき、公開投稿をローカル公開に変更する setting_reduce_motion: アニメーションの動きを減らす + setting_reject_public_unlisted_subscription: 管理者の指定したサーバーに「ローカル公開」投稿を配送しない + setting_reject_unlisted_subscription: 管理者の指定したサーバーに「未収載」投稿を配送しない setting_show_application: 送信したアプリを開示する setting_system_font_ui: システムのデフォルトフォントを使う setting_theme: サイトテーマ diff --git a/db/migrate/20230430110057_add_reject_invalid_subscription_to_domain_blocks.rb b/db/migrate/20230430110057_add_reject_invalid_subscription_to_domain_blocks.rb new file mode 100644 index 0000000000..b4c1458743 --- /dev/null +++ b/db/migrate/20230430110057_add_reject_invalid_subscription_to_domain_blocks.rb @@ -0,0 +1,8 @@ +class AddRejectInvalidSubscriptionToDomainBlocks < ActiveRecord::Migration[6.1] + def change + safety_assured do + remove_column :domain_blocks, :reject_send_unlisted_dissubscribable, :boolean, null: false, default: false + end + add_column :domain_blocks, :detect_invalid_subscription, :boolean, null: false, default: false + end +end diff --git a/db/schema.rb b/db/schema.rb index 5779eaac91..cb06360258 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_233749) do +ActiveRecord::Schema.define(version: 2023_04_30_110057) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -192,6 +192,7 @@ ActiveRecord::Schema.define(version: 2023_04_27_233749) do t.boolean "group_allow_private_message" t.integer "searchability", default: 2, null: false t.boolean "dissubscribable", default: false, null: false + t.boolean "stop_emoji_reaction_streaming", default: false 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), COALESCE(lower((domain)::text), ''::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", where: "(moved_to_account_id IS NOT NULL)" @@ -471,7 +472,6 @@ ActiveRecord::Schema.define(version: 2023_04_27_233749) do t.boolean "reject_favourite", default: false, null: false t.boolean "reject_reply", default: false, null: false t.boolean "reject_send_not_public_searchability", default: false, null: false - t.boolean "reject_send_unlisted_dissubscribable", default: false, null: false t.boolean "reject_send_public_unlisted", default: false, null: false t.boolean "reject_send_dissubscribable", default: false, null: false t.boolean "reject_send_media", default: false, null: false @@ -481,6 +481,7 @@ ActiveRecord::Schema.define(version: 2023_04_27_233749) do t.boolean "reject_new_follow", default: false, null: false t.boolean "hidden", default: false, null: false t.boolean "hidden_anonymous", default: false, null: false + t.boolean "detect_invalid_subscription", default: false, null: false t.index ["domain"], name: "index_domain_blocks_on_domain", unique: true end From 5e97866438ae486770be206bc82f219a5636bf40 Mon Sep 17 00:00:00 2001 From: KMY Date: Sun, 30 Apr 2023 21:39:09 +0900 Subject: [PATCH 04/10] Add checking reblog status local --- app/lib/status_reach_finder.rb | 2 +- app/policies/status_policy.rb | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/lib/status_reach_finder.rb b/app/lib/status_reach_finder.rb index 56c3f6e49b..2e3a5f7fac 100644 --- a/app/lib/status_reach_finder.rb +++ b/app/lib/status_reach_finder.rb @@ -98,7 +98,7 @@ class StatusReachFinder return @banned_domains if @banned_domains domains = banned_domains_of_status(@status) - domains = domains + banned_domains_of_status(@status.reblog) if @status.reblog? + domains = domains + banned_domains_of_status(@status.reblog) if @status.reblog? && @status.reblog.status.local? return @banned_domains = domains end diff --git a/app/policies/status_policy.rb b/app/policies/status_policy.rb index c67739eb5d..58784cd48f 100644 --- a/app/policies/status_policy.rb +++ b/app/policies/status_policy.rb @@ -101,10 +101,10 @@ class StatusPolicy < ApplicationPolicy end def server_blocking_domain? - if record.reblog? - server_blocking_domain_of_status(record) || server_blocking_domain_of_status(record.reblog) + if record.reblog? && record.reblog.local? + server_blocking_domain_of_status?(record) || server_blocking_domain_of_status?(record.reblog) else - server_blocking_domain_of_status(record) + server_blocking_domain_of_status?(record) end end From 29180de672d719a3580f0c36ed898b3ec5c7c3d9 Mon Sep 17 00:00:00 2001 From: KMY Date: Mon, 1 May 2023 12:14:36 +0900 Subject: [PATCH 05/10] Change comment for dissubscribable fedibird working --- config/locales/simple_form.ja.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml index 545c0145b2..0f6c9d4747 100644 --- a/config/locales/simple_form.ja.yml +++ b/config/locales/simple_form.ja.yml @@ -38,7 +38,7 @@ ja: current_username: 確認のため、現在のアカウントのユーザー名を入力してください digest: 長期間使用していない場合と不在時に返信を受けた場合のみ送信されます discoverable: レコメンド、トレンド、その他の機能により、あなたのアカウントを他の人から見つけられるようにします - dissubscribable: あなたの投稿はすべてのアンテナに掲載されなくなります。Fedibirdからの購読やMisskeyのアンテナを拒否することはできません + dissubscribable: あなたの投稿はすべてのアンテナに掲載されなくなります。Misskeyのアンテナを拒否することはできません。Mastodonの一部のサーバーもこの設定に対応しますが、挙動が一部kmyblueと異なる場合があります email: 確認のメールが送信されます fields: プロフィールに表として4つまでの項目を表示することができます group: このアカウントに送られたメンションは自動でBTされ、フォローしている全てのアカウントに配信されます From a4332babb583e5a20512fe3b70b7092b5d869eb3 Mon Sep 17 00:00:00 2001 From: KMY Date: Mon, 1 May 2023 12:16:16 +0900 Subject: [PATCH 06/10] Change delivering to misskey setting to send as private --- app/lib/activitypub/tag_manager.rb | 19 ++++++++ app/lib/status_reach_finder.rb | 47 +++++++++++++++++-- app/models/account_statuses_filter.rb | 4 +- app/models/user.rb | 8 ++++ app/policies/status_policy.rb | 4 +- .../activity_for_misskey_serializer.rb | 22 +++++++++ .../note_for_misskey_serializer.rb | 9 ++++ .../activitypub/distribution_worker.rb | 14 +++++- .../activitypub/raw_distribution_worker.rb | 16 ++++++- config/locales/simple_form.ja.yml | 2 +- 10 files changed, 133 insertions(+), 12 deletions(-) create mode 100644 app/serializers/activitypub/activity_for_misskey_serializer.rb create mode 100644 app/serializers/activitypub/note_for_misskey_serializer.rb diff --git a/app/lib/activitypub/tag_manager.rb b/app/lib/activitypub/tag_manager.rb index 5268b18b91..35d143356f 100644 --- a/app/lib/activitypub/tag_manager.rb +++ b/app/lib/activitypub/tag_manager.rb @@ -124,6 +124,25 @@ class ActivityPub::TagManager cc << COLLECTIONS[:public] end + cc = cc + cc_private_visibility(status) + + cc + end + + def cc_for_misskey(status) + case status.visibility + when 'unlisted' + status.account.user&.reject_unlisted_subscription? ? cc_private_visibility(status) : cc(status) + when 'public_unlisted' + status.account.user&.reject_public_unlisted_subscription? ? cc_private_visibility(status) : cc(status) + else + cc(status) + end + end + + def cc_private_visibility(status) + cc = [] + unless status.direct_visibility? || status.limited_visibility? if status.account.silenced? # Only notify followers if the account is locally silenced diff --git a/app/lib/status_reach_finder.rb b/app/lib/status_reach_finder.rb index 2e3a5f7fac..475d41fa1c 100644 --- a/app/lib/status_reach_finder.rb +++ b/app/lib/status_reach_finder.rb @@ -13,6 +13,10 @@ class StatusReachFinder (reached_account_inboxes + followers_inboxes + relay_inboxes).uniq end + def inboxes_for_misskey + (reached_account_inboxes_for_misskey + followers_inboxes_for_misskey).uniq + end + private def reached_account_inboxes @@ -26,6 +30,14 @@ class StatusReachFinder end end + def reached_account_inboxes_for_misskey + if @status.reblog? + [] + else + Account.where(id: reached_account_ids).where(domain: banned_domains_for_misskey).inboxes + end + end + def reached_account_ids [ replied_to_account_id, @@ -70,7 +82,7 @@ class StatusReachFinder def followers_inboxes if @status.in_reply_to_local_account? && distributable? - @status.account.followers.or(@status.thread.account.followers.not_domain_blocked_by_account(@status.account)).inboxes + @status.account.followers.or(@status.thread.account.followers.not_domain_blocked_by_account(@status.account)).where.not(domain: banned_domains).inboxes elsif @status.direct_visibility? || @status.limited_visibility? [] else @@ -78,6 +90,16 @@ class StatusReachFinder end end + def followers_inboxes_for_misskey + if @status.in_reply_to_local_account? && distributable? + @status.account.followers.or(@status.thread.account.followers.not_domain_blocked_by_account(@status.account)).where(domain: banned_domains_for_misskey).inboxes + elsif @status.direct_visibility? || @status.limited_visibility? + [] + else + @status.account.followers.where(domain: banned_domains_for_misskey).inboxes + end + end + def relay_inboxes if @status.public_visibility? Relay.enabled.pluck(:inbox_url) @@ -98,8 +120,8 @@ class StatusReachFinder return @banned_domains if @banned_domains domains = banned_domains_of_status(@status) - domains = domains + banned_domains_of_status(@status.reblog) if @status.reblog? && @status.reblog.status.local? - return @banned_domains = domains + domains = domains + banned_domains_of_status(@status.reblog) if @status.reblog? && @status.reblog.local? + return @banned_domains = domains.uniq end def banned_domains_of_status(status) @@ -107,10 +129,25 @@ class StatusReachFinder blocks = blocks.or(DomainBlock.where(reject_send_not_public_searchability: true)) if status.compute_searchability != 'public' blocks = blocks.or(DomainBlock.where(reject_send_public_unlisted: true)) if status.public_unlisted_visibility? blocks = blocks.or(DomainBlock.where(reject_send_dissubscribable: true)) if status.account.dissubscribable - blocks = blocks.or(DomainBlock.where(detect_invalid_subscription: true)) if status.public_unlisted_visibility? && status.account.user&.setting_reject_public_unlisted_subscription - blocks = blocks.or(DomainBlock.where(detect_invalid_subscription: true)) if status.unlisted_visibility? && status.account.user&.setting_reject_unlisted_subscription + blocks = blocks.or(DomainBlock.where(detect_invalid_subscription: true)) if status.public_unlisted_visibility? && status.account.user&.reject_public_unlisted_subscription? + blocks = blocks.or(DomainBlock.where(detect_invalid_subscription: true)) if status.unlisted_visibility? && status.account.user&.reject_unlisted_subscription? blocks = blocks.or(DomainBlock.where(reject_send_media: true)) if status.with_media? blocks = blocks.or(DomainBlock.where(reject_send_sensitive: true)) if (status.with_media? && status.sensitive) || status.spoiler_text? blocks.pluck(:domain).uniq end + + def banned_domains_for_misskey + return @banned_domains_for_misskey if @banned_domains_for_misskey + + domains = banned_domains_for_misskey_of_status(@status) + domains = domains + banned_domains_for_misskey_of_status(@status.reblog) if @status.reblog? && @status.reblog.local? + return @banned_domains_for_misskey = domains.uniq + end + + def banned_domains_for_misskey_of_status(status) + blocks = DomainBlock.where(domain: nil) + blocks = blocks.or(DomainBlock.where(detect_invalid_subscription: true)) if status.public_unlisted_visibility? && status.account.user&.reject_public_unlisted_subscription? + blocks = blocks.or(DomainBlock.where(detect_invalid_subscription: true)) if status.unlisted_visibility? && status.account.user&.reject_unlisted_subscription? + blocks.pluck(:domain).uniq + end end diff --git a/app/models/account_statuses_filter.rb b/app/models/account_statuses_filter.rb index 11750b8606..d440a6a8be 100644 --- a/app/models/account_statuses_filter.rb +++ b/app/models/account_statuses_filter.rb @@ -27,8 +27,8 @@ class AccountStatusesFilter scope.merge!(hashtag_scope) if tagged? scope.merge!(scope.where(searchability: :public)) if domain_block&.reject_send_not_public_searchability - scope.merge!(scope.where.not(visibility: :public_unlisted)) if domain_block&.reject_send_public_unlisted || (domain_block&.detect_invalid_subscription && @account.user&.setting_reject_public_unlisted_subscription) - scope.merge!(scope.where.not(visibility: :unlisted)) if domain_block&.detect_invalid_subscription && @account.user&.setting_unlisted_subscription + scope.merge!(scope.where.not(visibility: :public_unlisted)) if domain_block&.reject_send_public_unlisted || (domain_block&.detect_invalid_subscription && @account.user&.reject_public_unlisted_subscription?) + scope.merge!(scope.where.not(visibility: :unlisted)) if domain_block&.detect_invalid_subscription && @account.user&.unlisted_subscription? scope.merge!(scope.where(spoiler_text: ['', nil])) if domain_block&.reject_send_sensitive scope diff --git a/app/models/user.rb b/app/models/user.rb index 0f945c7805..1e755e930a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -320,6 +320,14 @@ class User < ApplicationRecord settings.default_searchability || 'public' end + def reject_public_unlisted_subscription? + settings.reject_public_unlisted_subscription + end + + def reject_unlisted_subscription? + settings.reject_unlisted_subscription + end + def allows_report_emails? settings.notification_emails['report'] end diff --git a/app/policies/status_policy.rb b/app/policies/status_policy.rb index 58784cd48f..e177703ed9 100644 --- a/app/policies/status_policy.rb +++ b/app/policies/status_policy.rb @@ -114,8 +114,8 @@ class StatusPolicy < ApplicationPolicy (@domain_block.reject_send_not_public_searchability && status.compute_searchability != 'public') || (@domain_block.reject_send_public_unlisted && status.public_unlisted_visibility?) || (@domain_block.reject_send_dissubscribable && status.account.dissubscribable) || - (@domain_block.detect_invalid_subscription && status.public_unlisted_visibility? && status.account.user&.setting_reject_public_unlisted_subscription) || - (@domain_block.detect_invalid_subscription && status.public_visibility? && status.account.user&.setting_reject_unlisted_subscription) || + (@domain_block.detect_invalid_subscription && status.public_unlisted_visibility? && status.account.user&.reject_public_unlisted_subscription) || + (@domain_block.detect_invalid_subscription && status.public_visibility? && status.account.user&.reject_unlisted_subscription) || (@domain_block.reject_send_media && status.with_media?) || (@domain_block.reject_send_sensitive && ((status.with_media? && status.sensitive) || status.spoiler_text?)) else diff --git a/app/serializers/activitypub/activity_for_misskey_serializer.rb b/app/serializers/activitypub/activity_for_misskey_serializer.rb new file mode 100644 index 0000000000..039bb63d57 --- /dev/null +++ b/app/serializers/activitypub/activity_for_misskey_serializer.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +class ActivityPub::ActivityForMisskeySerializer < ActivityPub::Serializer + def self.serializer_for(model, options) + case model.class.name + when 'Status' + ActivityPub::NoteForMisskeySerializer + when 'DeliverToDeviceService::EncryptedMessage' + ActivityPub::EncryptedMessageSerializer + else + super + end + end + + attributes :id, :type, :actor, :published, :to, :cc + + has_one :virtual_object, key: :object + + def published + object.published.iso8601 + end +end diff --git a/app/serializers/activitypub/note_for_misskey_serializer.rb b/app/serializers/activitypub/note_for_misskey_serializer.rb new file mode 100644 index 0000000000..fa38ff020e --- /dev/null +++ b/app/serializers/activitypub/note_for_misskey_serializer.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class ActivityPub::NoteForMisskeySerializer < ActivityPub::NoteSerializer + + def cc + ActivityPub::TagManager.instance.cc_for_misskey(object) + end + +end diff --git a/app/workers/activitypub/distribution_worker.rb b/app/workers/activitypub/distribution_worker.rb index 575e110257..683d4b93a2 100644 --- a/app/workers/activitypub/distribution_worker.rb +++ b/app/workers/activitypub/distribution_worker.rb @@ -15,13 +15,25 @@ class ActivityPub::DistributionWorker < ActivityPub::RawDistributionWorker protected def inboxes - @inboxes ||= StatusReachFinder.new(@status).inboxes + @inboxes ||= status_reach_finder.inboxes + end + + def inboxes_for_misskey + @inboxes_for_misskey ||= status_reach_finder.inboxes_for_misskey + end + + def status_reach_finder + @status_reach_finder ||= StatusReachFinder.new(@status) end def payload @payload ||= Oj.dump(serialize_payload(activity, ActivityPub::ActivitySerializer, signer: @account)) end + def payload_for_misskey + @payload ||= Oj.dump(serialize_payload(activity, ActivityPub::ActivityForMisskeySerializer, signer: @account)) + end + def activity ActivityPub::ActivityPresenter.from_status(@status) end diff --git a/app/workers/activitypub/raw_distribution_worker.rb b/app/workers/activitypub/raw_distribution_worker.rb index 8ecc17db9a..30371488f0 100644 --- a/app/workers/activitypub/raw_distribution_worker.rb +++ b/app/workers/activitypub/raw_distribution_worker.rb @@ -23,17 +23,27 @@ class ActivityPub::RawDistributionWorker protected def distribute! - return if inboxes.empty? + return if inboxes.empty? && inboxes_for_misskey.empty? ActivityPub::DeliveryWorker.push_bulk(inboxes) do |inbox_url| [payload, source_account_id, inbox_url, options] end + + return if inboxes_for_misskey.empty? + + ActivityPub::DeliveryWorker.push_bulk(inboxes_for_misskey) do |inbox_url| + [payload_for_misskey, source_account_id, inbox_url, options] + end end def payload @json end + def payload_for_misskey + payload + end + def source_account_id @account.id end @@ -42,6 +52,10 @@ class ActivityPub::RawDistributionWorker @inboxes ||= @account.followers.inboxes - @exclude_inboxes end + def inboxes_for_misskey + [] + end + def options {} end diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml index 0f6c9d4747..180d31e1f1 100644 --- a/config/locales/simple_form.ja.yml +++ b/config/locales/simple_form.ja.yml @@ -62,7 +62,7 @@ ja: setting_display_media_expand: Misskeyなどは4個を超えて投稿可能です。その追加分を最大8個まで表示します。kmyblueからアップロードはできません setting_noindex: 公開プロフィールおよび各投稿ページに影響します setting_public_post_to_unlisted: 未対応のサードパーティアプリからもローカル公開で投稿できますが、公開投稿はWeb以外できなくなります - setting_reject_unlisted_subscription: Misskeyやそのフォーク(Calckeyなど)は、フォローしていないアカウントの「未収載」投稿を **購読・検索** することができます。これはMastodonにおける「未収載」投稿の基本的な考え方、扱い方と矛盾します。そのようなサーバーのうち管理人が指定したものに、指定した公開範囲の投稿を配送しません。ただし構造上、完璧な配送停止は困難であること、ご理解ください + setting_reject_unlisted_subscription: Misskeyやそのフォーク(Calckeyなど)は、フォローしていないアカウントの「未収載」投稿を **購読・検索** することができます。これはMastodonにおける「未収載」投稿の基本的な考え方、扱い方と矛盾します。そのようなサーバーのうち管理人が指定したものに、指定した公開範囲の投稿を「フォロワーのみ」として配送します。ただし構造上、完璧な対応は困難でたまに未収載として配信されること、ご理解ください setting_show_application: 投稿するのに使用したアプリが投稿の詳細ビューに表示されるようになります setting_use_blurhash: ぼかしはメディアの色を元に生成されますが、細部は見えにくくなっています setting_use_pending_items: 新着があってもタイムラインを自動的にスクロールしないようにします From 3a1c73f60751b99c89acc601585ba373c9de13ee Mon Sep 17 00:00:00 2001 From: KMY Date: Mon, 1 May 2023 12:33:26 +0900 Subject: [PATCH 07/10] Add user config rejecting admin domain block settings --- .../settings/preferences_controller.rb | 1 + app/lib/status_reach_finder.rb | 12 +++++++----- app/lib/user_settings_decorator.rb | 9 +++++++-- app/models/user.rb | 5 +++++ app/policies/status_policy.rb | 18 +++++++++++------- .../settings/preferences/other/show.html.haml | 3 +++ config/locales/simple_form.en.yml | 1 + config/locales/simple_form.ja.yml | 2 ++ 8 files changed, 37 insertions(+), 14 deletions(-) diff --git a/app/controllers/settings/preferences_controller.rb b/app/controllers/settings/preferences_controller.rb index e7a047369c..4b9d60c03e 100644 --- a/app/controllers/settings/preferences_controller.rb +++ b/app/controllers/settings/preferences_controller.rb @@ -39,6 +39,7 @@ class Settings::PreferencesController < Settings::BaseController :setting_public_post_to_unlisted, :setting_reject_public_unlisted_subscription, :setting_reject_unlisted_subscription, + :setting_send_without_domain_blocks, :setting_default_language, :setting_unfollow_modal, :setting_boost_modal, diff --git a/app/lib/status_reach_finder.rb b/app/lib/status_reach_finder.rb index 475d41fa1c..5d972ebcd4 100644 --- a/app/lib/status_reach_finder.rb +++ b/app/lib/status_reach_finder.rb @@ -126,13 +126,15 @@ class StatusReachFinder def banned_domains_of_status(status) blocks = DomainBlock.where(domain: nil) - blocks = blocks.or(DomainBlock.where(reject_send_not_public_searchability: true)) if status.compute_searchability != 'public' - blocks = blocks.or(DomainBlock.where(reject_send_public_unlisted: true)) if status.public_unlisted_visibility? - blocks = blocks.or(DomainBlock.where(reject_send_dissubscribable: true)) if status.account.dissubscribable + unless status.account.user&.send_without_domain_blocks? + blocks = blocks.or(DomainBlock.where(reject_send_not_public_searchability: true)) if status.compute_searchability != 'public' + blocks = blocks.or(DomainBlock.where(reject_send_public_unlisted: true)) if status.public_unlisted_visibility? + blocks = blocks.or(DomainBlock.where(reject_send_dissubscribable: true)) if status.account.dissubscribable + blocks = blocks.or(DomainBlock.where(reject_send_media: true)) if status.with_media? + blocks = blocks.or(DomainBlock.where(reject_send_sensitive: true)) if (status.with_media? && status.sensitive) || status.spoiler_text? + end blocks = blocks.or(DomainBlock.where(detect_invalid_subscription: true)) if status.public_unlisted_visibility? && status.account.user&.reject_public_unlisted_subscription? blocks = blocks.or(DomainBlock.where(detect_invalid_subscription: true)) if status.unlisted_visibility? && status.account.user&.reject_unlisted_subscription? - blocks = blocks.or(DomainBlock.where(reject_send_media: true)) if status.with_media? - blocks = blocks.or(DomainBlock.where(reject_send_sensitive: true)) if (status.with_media? && status.sensitive) || status.spoiler_text? blocks.pluck(:domain).uniq end diff --git a/app/lib/user_settings_decorator.rb b/app/lib/user_settings_decorator.rb index 3354c5fa23..0840697e23 100644 --- a/app/lib/user_settings_decorator.rb +++ b/app/lib/user_settings_decorator.rb @@ -23,6 +23,7 @@ class UserSettingsDecorator user.settings['public_post_to_unlisted']=public_post_to_unlisted_preference if change?('setting_public_post_to_unlisted') user.settings['reject_public_unlisted_subscription'] = reject_public_unlisted_subscription_preference if change?('setting_reject_public_unlisted_subscription') user.settings['reject_unlisted_subscription'] = reject_unlisted_subscription_preference if change?('setting_reject_unlisted_subscription') + user.settings['send_without_domain_blocks']=send_without_domain_blocks_preference if change?('setting_send_without_domain_blocks') user.settings['default_language'] = default_language_preference if change?('setting_default_language') user.settings['unfollow_modal'] = unfollow_modal_preference if change?('setting_unfollow_modal') user.settings['boost_modal'] = boost_modal_preference if change?('setting_boost_modal') @@ -71,11 +72,15 @@ class UserSettingsDecorator end def reject_public_unlisted_subscription_preference - boolean_cast_setting 'setting_reject_public_unlisted_subscription_preference' + boolean_cast_setting 'setting_reject_public_unlisted_subscription' end def reject_unlisted_subscription_preference - boolean_cast_setting 'setting_reject_unlisted_subscription_preference' + boolean_cast_setting 'setting_reject_unlisted_subscription' + end + + def send_without_domain_blocks_preference + boolean_cast_setting 'setting_send_without_domain_blocks' end def unfollow_modal_preference diff --git a/app/models/user.rb b/app/models/user.rb index 1e755e930a..31246627c6 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -139,6 +139,7 @@ class User < ApplicationRecord :advanced_layout, :use_blurhash, :use_pending_items, :trends, :crop_images, :disable_swiping, :always_send_emails, :public_post_to_unlisted, :reject_public_unlisted_subscription, :reject_unlisted_subscription, + :send_without_domain_blocks, to: :settings, prefix: :setting, allow_nil: false delegate :can?, to: :role @@ -328,6 +329,10 @@ class User < ApplicationRecord settings.reject_unlisted_subscription end + def send_without_domain_blocks? + settings.send_without_domain_blocks + end + def allows_report_emails? settings.notification_emails['report'] end diff --git a/app/policies/status_policy.rb b/app/policies/status_policy.rb index e177703ed9..f8913f41e9 100644 --- a/app/policies/status_policy.rb +++ b/app/policies/status_policy.rb @@ -111,13 +111,17 @@ class StatusPolicy < ApplicationPolicy def server_blocking_domain_of_status?(status) @domain_block ||= DomainBlock.find_by(domain: current_account&.domain) if @domain_block - (@domain_block.reject_send_not_public_searchability && status.compute_searchability != 'public') || - (@domain_block.reject_send_public_unlisted && status.public_unlisted_visibility?) || - (@domain_block.reject_send_dissubscribable && status.account.dissubscribable) || - (@domain_block.detect_invalid_subscription && status.public_unlisted_visibility? && status.account.user&.reject_public_unlisted_subscription) || - (@domain_block.detect_invalid_subscription && status.public_visibility? && status.account.user&.reject_unlisted_subscription) || - (@domain_block.reject_send_media && status.with_media?) || - (@domain_block.reject_send_sensitive && ((status.with_media? && status.sensitive) || status.spoiler_text?)) + unless status.account.user&.send_without_domain_blocks? + (@domain_block.reject_send_not_public_searchability && status.compute_searchability != 'public') || + (@domain_block.reject_send_public_unlisted && status.public_unlisted_visibility?) || + (@domain_block.reject_send_dissubscribable && status.account.dissubscribable) || + (@domain_block.detect_invalid_subscription && status.public_unlisted_visibility? && status.account.user&.reject_public_unlisted_subscription) || + (@domain_block.detect_invalid_subscription && status.public_visibility? && status.account.user&.reject_unlisted_subscription) || + (@domain_block.reject_send_media && status.with_media?) || + (@domain_block.reject_send_sensitive && ((status.with_media? && status.sensitive) || status.spoiler_text?)) + else + (@domain_block.detect_invalid_subscription && status.public_unlisted_visibility? && status.account.user&.reject_public_unlisted_subscription) || + (@domain_block.detect_invalid_subscription && status.public_visibility? && status.account.user&.reject_unlisted_subscription) else false end diff --git a/app/views/settings/preferences/other/show.html.haml b/app/views/settings/preferences/other/show.html.haml index 69330e83cf..a0890b7185 100644 --- a/app/views/settings/preferences/other/show.html.haml +++ b/app/views/settings/preferences/other/show.html.haml @@ -34,6 +34,9 @@ .fields-group = f.input :setting_show_application, as: :boolean, wrapper: :with_label, recommended: true + .fields-group + = f.input :setting_send_without_domain_blocks, as: :boolean, wrapper: :with_label + .fields-group = f.input :setting_reject_public_unlisted_subscription, as: :boolean, wrapper: :with_label diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml index 4d5fd1dbc0..5e10a23fdf 100644 --- a/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -224,6 +224,7 @@ en: setting_reduce_motion: Reduce motion in animations setting_reject_public_unlisted_subscription: Reject sending public unlisted posts to Misskey, Calckey setting_reject_unlisted_subscription: Reject sending unlisted posts to Misskey, Calckey + setting_send_without_domain_blocks: Send your post to all server with administrator set as rejecting-post-server for protect you [DEPRECATED] setting_show_application: Disclose application used to send posts setting_system_font_ui: Use system's default font setting_theme: Site theme diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml index 180d31e1f1..3042a8fb7c 100644 --- a/config/locales/simple_form.ja.yml +++ b/config/locales/simple_form.ja.yml @@ -52,6 +52,7 @@ ja: person: これは人が使用している通常のアカウントです phrase: 投稿内容の大文字小文字や閲覧注意に関係なく一致 scopes: アプリの API に許可するアクセス権を選択してください。最上位のスコープを選択する場合、個々のスコープを選択する必要はありません。 + setting_send_without_domain_blocks: 管理人が同人コンテンツの配送にふさわしくないと判断したサーバーに、制限に関係なく全ての投稿を配送します。ただし何が起きても自己責任になります setting_aggregate_reblogs: 最近ブーストされた投稿が新たにブーストされても表示しません (設定後受信したものにのみ影響) setting_always_send_emails: 通常、Mastodon からメール通知は行われません。 setting_default_sensitive: 閲覧注意状態のメディアはデフォルトでは内容が伏せられ、クリックして初めて閲覧できるようになります @@ -227,6 +228,7 @@ ja: setting_reduce_motion: アニメーションの動きを減らす setting_reject_public_unlisted_subscription: 管理者の指定したサーバーに「ローカル公開」投稿を配送しない setting_reject_unlisted_subscription: 管理者の指定したサーバーに「未収載」投稿を配送しない + setting_send_without_domain_blocks: 管理人の設定した配送停止設定を拒否する (非推奨) setting_show_application: 送信したアプリを開示する setting_system_font_ui: システムのデフォルトフォントを使う setting_theme: サイトテーマ From d031ade823e218a987231d81753b099ecf018c6e Mon Sep 17 00:00:00 2001 From: KMY Date: Mon, 1 May 2023 12:34:02 +0900 Subject: [PATCH 08/10] Fix setting page text --- config/locales/simple_form.ja.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml index 3042a8fb7c..bb213f08e4 100644 --- a/config/locales/simple_form.ja.yml +++ b/config/locales/simple_form.ja.yml @@ -226,8 +226,8 @@ ja: setting_noindex: 検索エンジンによるインデックスを拒否する setting_public_post_to_unlisted: サードパーティアプリから投稿するとき、公開投稿をローカル公開に変更する setting_reduce_motion: アニメーションの動きを減らす - setting_reject_public_unlisted_subscription: 管理者の指定したサーバーに「ローカル公開」投稿を配送しない - setting_reject_unlisted_subscription: 管理者の指定したサーバーに「未収載」投稿を配送しない + setting_reject_public_unlisted_subscription: 管理者の指定したサーバーに「ローカル公開」投稿を「フォロワーのみ」に変換して配送する + setting_reject_unlisted_subscription: 管理者の指定したサーバーに「未収載」投稿を「フォロワーのみ」に変換して配送する setting_send_without_domain_blocks: 管理人の設定した配送停止設定を拒否する (非推奨) setting_show_application: 送信したアプリを開示する setting_system_font_ui: システムのデフォルトフォントを使う From 7bcef0f8b24c43fa6abcb17c96e6ac6f0185c6de Mon Sep 17 00:00:00 2001 From: KMY Date: Mon, 1 May 2023 13:26:10 +0900 Subject: [PATCH 09/10] Fix privacy for misskey --- app/lib/activitypub/tag_manager.rb | 13 ++++++------- app/policies/status_policy.rb | 1 + app/presenters/activitypub/activity_presenter.rb | 4 ++-- app/workers/activitypub/distribution_worker.rb | 6 +++++- .../activitypub/raw_distribution_worker.rb | 16 ++++++++-------- 5 files changed, 22 insertions(+), 18 deletions(-) diff --git a/app/lib/activitypub/tag_manager.rb b/app/lib/activitypub/tag_manager.rb index 35d143356f..bd612a5d6a 100644 --- a/app/lib/activitypub/tag_manager.rb +++ b/app/lib/activitypub/tag_manager.rb @@ -130,14 +130,13 @@ class ActivityPub::TagManager end def cc_for_misskey(status) - case status.visibility - when 'unlisted' - status.account.user&.reject_unlisted_subscription? ? cc_private_visibility(status) : cc(status) - when 'public_unlisted' - status.account.user&.reject_public_unlisted_subscription? ? cc_private_visibility(status) : cc(status) - else - cc(status) + if (status.account.user&.reject_unlisted_subscription? && status.visibility == 'unlisted') || (status.account.user&.reject_public_unlisted_subscription? && status.visibility == 'public_unlisted') + cc = cc_private_visibility(status) + cc << uri_for(status.reblog.account) if status.reblog? + return cc end + + cc(status) end def cc_private_visibility(status) diff --git a/app/policies/status_policy.rb b/app/policies/status_policy.rb index f8913f41e9..9c37c8679b 100644 --- a/app/policies/status_policy.rb +++ b/app/policies/status_policy.rb @@ -122,6 +122,7 @@ class StatusPolicy < ApplicationPolicy else (@domain_block.detect_invalid_subscription && status.public_unlisted_visibility? && status.account.user&.reject_public_unlisted_subscription) || (@domain_block.detect_invalid_subscription && status.public_visibility? && status.account.user&.reject_unlisted_subscription) + end else false end diff --git a/app/presenters/activitypub/activity_presenter.rb b/app/presenters/activitypub/activity_presenter.rb index 38e8527e8e..9524e64179 100644 --- a/app/presenters/activitypub/activity_presenter.rb +++ b/app/presenters/activitypub/activity_presenter.rb @@ -4,14 +4,14 @@ class ActivityPub::ActivityPresenter < ActiveModelSerializers::Model attributes :id, :type, :actor, :published, :to, :cc, :virtual_object class << self - def from_status(status, allow_inlining: true) + def from_status(status, allow_inlining: true, for_misskey: false) new.tap do |presenter| presenter.id = ActivityPub::TagManager.instance.activity_uri_for(status) presenter.type = status.reblog? ? 'Announce' : 'Create' presenter.actor = ActivityPub::TagManager.instance.uri_for(status.account) presenter.published = status.created_at presenter.to = ActivityPub::TagManager.instance.to(status) - presenter.cc = ActivityPub::TagManager.instance.cc(status) + presenter.cc = for_misskey ? ActivityPub::TagManager.instance.cc_for_misskey(status) : ActivityPub::TagManager.instance.cc(status) presenter.virtual_object = begin if status.reblog? diff --git a/app/workers/activitypub/distribution_worker.rb b/app/workers/activitypub/distribution_worker.rb index 683d4b93a2..34b6f6e32f 100644 --- a/app/workers/activitypub/distribution_worker.rb +++ b/app/workers/activitypub/distribution_worker.rb @@ -31,13 +31,17 @@ class ActivityPub::DistributionWorker < ActivityPub::RawDistributionWorker end def payload_for_misskey - @payload ||= Oj.dump(serialize_payload(activity, ActivityPub::ActivityForMisskeySerializer, signer: @account)) + @payload_for_misskey ||= Oj.dump(serialize_payload(activity_for_misskey, ActivityPub::ActivityForMisskeySerializer, signer: @account)) end def activity ActivityPub::ActivityPresenter.from_status(@status) end + def activity_for_misskey + ActivityPub::ActivityPresenter.from_status(@status, for_misskey: true) + end + def options { 'synchronize_followers' => @status.private_visibility? } end diff --git a/app/workers/activitypub/raw_distribution_worker.rb b/app/workers/activitypub/raw_distribution_worker.rb index 30371488f0..41760aa443 100644 --- a/app/workers/activitypub/raw_distribution_worker.rb +++ b/app/workers/activitypub/raw_distribution_worker.rb @@ -23,16 +23,16 @@ class ActivityPub::RawDistributionWorker protected def distribute! - return if inboxes.empty? && inboxes_for_misskey.empty? - - ActivityPub::DeliveryWorker.push_bulk(inboxes) do |inbox_url| - [payload, source_account_id, inbox_url, options] + unless inboxes.empty? + ActivityPub::DeliveryWorker.push_bulk(inboxes) do |inbox_url| + [payload, source_account_id, inbox_url, options] + end end - return if inboxes_for_misskey.empty? - - ActivityPub::DeliveryWorker.push_bulk(inboxes_for_misskey) do |inbox_url| - [payload_for_misskey, source_account_id, inbox_url, options] + unless inboxes_for_misskey.empty? + ActivityPub::DeliveryWorker.push_bulk(inboxes_for_misskey) do |inbox_url| + [payload_for_misskey, source_account_id, inbox_url, options] + end end end From f72b9ba01d1173acbe277fc676ee94ba631cdad1 Mon Sep 17 00:00:00 2001 From: KMY Date: Mon, 1 May 2023 14:05:18 +0900 Subject: [PATCH 10/10] Fix statuses filter merges --- app/models/account_statuses_filter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/account_statuses_filter.rb b/app/models/account_statuses_filter.rb index d440a6a8be..f95c4ce1b8 100644 --- a/app/models/account_statuses_filter.rb +++ b/app/models/account_statuses_filter.rb @@ -28,7 +28,7 @@ class AccountStatusesFilter scope.merge!(scope.where(searchability: :public)) if domain_block&.reject_send_not_public_searchability scope.merge!(scope.where.not(visibility: :public_unlisted)) if domain_block&.reject_send_public_unlisted || (domain_block&.detect_invalid_subscription && @account.user&.reject_public_unlisted_subscription?) - scope.merge!(scope.where.not(visibility: :unlisted)) if domain_block&.detect_invalid_subscription && @account.user&.unlisted_subscription? + scope.merge!(scope.where.not(visibility: :unlisted)) if domain_block&.detect_invalid_subscription && @account.user&.reject_unlisted_subscription? scope.merge!(scope.where(spoiler_text: ['', nil])) if domain_block&.reject_send_sensitive scope