From 1acfea488870bc7ec58aebf0ffe613db408ca63d Mon Sep 17 00:00:00 2001 From: noellabo Date: Fri, 16 Feb 2024 16:14:23 +0900 Subject: [PATCH 1/3] Add reject pattern to Admin setting --- .../admin/settings/others_controller.rb | 9 +++++++++ app/lib/activitypub/activity/create.rb | 6 +++++- app/models/form/admin_settings.rb | 2 ++ app/validators/regexp_syntax_validator.rb | 13 +++++++++++++ .../admin/settings/others/show.html.haml | 19 +++++++++++++++++++ .../admin/settings/shared/_links.html.haml | 1 + config/locales/en.yml | 8 ++++++++ config/routes/admin.rb | 1 + config/settings.yml | 1 + 9 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 app/controllers/admin/settings/others_controller.rb create mode 100644 app/validators/regexp_syntax_validator.rb create mode 100644 app/views/admin/settings/others/show.html.haml diff --git a/app/controllers/admin/settings/others_controller.rb b/app/controllers/admin/settings/others_controller.rb new file mode 100644 index 0000000000..113d0c84ff --- /dev/null +++ b/app/controllers/admin/settings/others_controller.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class Admin::Settings::OthersController < Admin::SettingsController + private + + def after_update_redirect_path + admin_settings_others_path + end +end diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 85195f4c39..bfb3ce7e8b 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -46,8 +46,12 @@ class ActivityPub::Activity::Create < ActivityPub::Activity ) end + def reject_pattern? + Setting.reject_pattern.present? && @object['content']&.match?(Setting.reject_pattern) + end + def create_status - return reject_payload! if unsupported_object_type? || non_matching_uri_hosts?(@account.uri, object_uri) || tombstone_exists? || !related_to_local_activity? + return reject_payload! if unsupported_object_type? || non_matching_uri_hosts?(@account.uri, object_uri) || tombstone_exists? || !related_to_local_activity? || reject_pattern? with_redis_lock("create:#{object_uri}") do return if delete_arrived_first?(object_uri) || poll_vote? diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb index cb37a52217..69907d7fe2 100644 --- a/app/models/form/admin_settings.rb +++ b/app/models/form/admin_settings.rb @@ -37,6 +37,7 @@ class Form::AdminSettings status_page_url captcha_enabled authorized_fetch + reject_pattern ).freeze INTEGER_KEYS = %i( @@ -79,6 +80,7 @@ class Form::AdminSettings validates :show_domain_blocks_rationale, inclusion: { in: %w(disabled users all) }, if: -> { defined?(@show_domain_blocks_rationale) } validates :media_cache_retention_period, :content_cache_retention_period, :backups_retention_period, numericality: { only_integer: true }, allow_blank: true, if: -> { defined?(@media_cache_retention_period) || defined?(@content_cache_retention_period) || defined?(@backups_retention_period) } validates :site_short_description, length: { maximum: 200 }, if: -> { defined?(@site_short_description) } + validates :reject_pattern, regexp_syntax: true, if: -> { defined?(@reject_pattern) } validates :status_page_url, url: true, allow_blank: true validate :validate_site_uploads diff --git a/app/validators/regexp_syntax_validator.rb b/app/validators/regexp_syntax_validator.rb new file mode 100644 index 0000000000..57ecf882c2 --- /dev/null +++ b/app/validators/regexp_syntax_validator.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class RegexpSyntaxValidator < ActiveModel::EachValidator + def validate_each(record, attribute, value) + return if value.blank? + + begin + Regexp.compile(value) + rescue RegexpError => e + record.errors.add(attribute, I18n.t('applications.invalid_regexp', message: e.message)) + end + end +end diff --git a/app/views/admin/settings/others/show.html.haml b/app/views/admin/settings/others/show.html.haml new file mode 100644 index 0000000000..06dcf2bf8b --- /dev/null +++ b/app/views/admin/settings/others/show.html.haml @@ -0,0 +1,19 @@ +- content_for :page_title do + = t('admin.settings.others.title') + +- content_for :heading do + %h2= t('admin.settings.title') + = render partial: 'admin/settings/shared/links' + += simple_form_for @admin_settings, url: admin_settings_others_path, html: { method: :patch } do |f| + = render 'shared/error_messages', object: @admin_settings + + %p.lead= t('admin.settings.others.preamble') + + %h4= t('admin.settings.others.activitypub') + + .fields-group + = f.input :reject_pattern, wrapper: :with_block_label, as: :text, label: t('admin.settings.reject_pattern.title'), hint: t('admin.settings.reject_pattern.desc_html'), input_html: { rows: 8 } + + .actions + = f.button :button, t('generic.save_changes'), type: :submit diff --git a/app/views/admin/settings/shared/_links.html.haml b/app/views/admin/settings/shared/_links.html.haml index d8b697592a..aa48b62cf6 100644 --- a/app/views/admin/settings/shared/_links.html.haml +++ b/app/views/admin/settings/shared/_links.html.haml @@ -7,3 +7,4 @@ primary.item :discovery, safe_join([fa_icon('search fw'), t('admin.settings.discovery.title')]), admin_settings_discovery_path primary.item :content_retention, safe_join([fa_icon('history fw'), t('admin.settings.content_retention.title')]), admin_settings_content_retention_path primary.item :appearance, safe_join([fa_icon('desktop fw'), t('admin.settings.appearance.title')]), admin_settings_appearance_path + primary.item :others, safe_join([fa_icon('cogs fw'), t('admin.settings.others.title')]), admin_settings_others_path diff --git a/config/locales/en.yml b/config/locales/en.yml index efd603740a..fa5d1e3716 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -766,6 +766,10 @@ en: all: To everyone disabled: To no one users: To logged-in local users + others: + activitypub: ActivityPub + preamble: Other settings, including customizing behavior + title: Other settings registrations: moderation_recommandation: Please make sure you have an adequate and reactive moderation team before you open registrations to everyone! preamble: Control who can create an account on your server. @@ -776,6 +780,9 @@ en: none: Nobody can sign up open: Anyone can sign up warning_hint: We recommend using “Approval required for sign up” unless you are confident your moderation team can handle spam and malicious registrations in a timely fashion. + reject_pattern: + desc_html: Set a regular expression pattern to inspect Create Activity content, and refuse Activity if you match + title: Reject Pattern security: authorized_fetch: Require authentication from federated servers authorized_fetch_hint: Requiring authentication from federated servers enables stricter enforcement of both user-level and server-level blocks. However, this comes at the cost of a performance penalty, reduces the reach of your replies, and may introduce compatibility issues with some federated services. In addition, this will not prevent dedicated actors from fetching your public posts and accounts. @@ -1034,6 +1041,7 @@ en: applications: created: Application successfully created destroyed: Application successfully deleted + invalid_regexp: "The provided Regexp is invalid: %{message}" logout: Logout regenerate_token: Regenerate access token token_regenerated: Access token successfully regenerated diff --git a/config/routes/admin.rb b/config/routes/admin.rb index 207cb0580d..6b1f0e1a16 100644 --- a/config/routes/admin.rb +++ b/config/routes/admin.rb @@ -50,6 +50,7 @@ namespace :admin do resource :about, only: [:show, :update], controller: 'about' resource :appearance, only: [:show, :update], controller: 'appearance' resource :discovery, only: [:show, :update], controller: 'discovery' + resource :others, only: [:show, :update], controller: 'others' end resources :site_uploads, only: [:destroy] diff --git a/config/settings.yml b/config/settings.yml index 208c8e3760..3691d9035a 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -38,6 +38,7 @@ defaults: &defaults require_invite_text: false backups_retention_period: 7 captcha_enabled: false + reject_pattern: '' development: <<: *defaults From 53ca4bd676832db28ebe4ebc7809e1eadff99c9f Mon Sep 17 00:00:00 2001 From: noellabo Date: Sat, 17 Feb 2024 01:02:19 +0900 Subject: [PATCH 2/3] Fix i18n-tasks normalize --- config/locales/en.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index fa5d1e3716..0d6ae47c11 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1041,7 +1041,7 @@ en: applications: created: Application successfully created destroyed: Application successfully deleted - invalid_regexp: "The provided Regexp is invalid: %{message}" + invalid_regexp: 'The provided Regexp is invalid: %{message}' logout: Logout regenerate_token: Regenerate access token token_regenerated: Access token successfully regenerated From 67b6af0f8bdbcbc8e0c244e418305189d32f6426 Mon Sep 17 00:00:00 2001 From: noellabo Date: Sat, 17 Feb 2024 01:30:25 +0900 Subject: [PATCH 3/3] Fix style --- app/lib/activitypub/activity/create.rb | 8 ++++---- app/validators/regexp_syntax_validator.rb | 8 +++----- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index bfb3ce7e8b..b9f78feb14 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -46,10 +46,6 @@ class ActivityPub::Activity::Create < ActivityPub::Activity ) end - def reject_pattern? - Setting.reject_pattern.present? && @object['content']&.match?(Setting.reject_pattern) - end - def create_status return reject_payload! if unsupported_object_type? || non_matching_uri_hosts?(@account.uri, object_uri) || tombstone_exists? || !related_to_local_activity? || reject_pattern? @@ -417,6 +413,10 @@ class ActivityPub::Activity::Create < ActivityPub::Activity Tombstone.exists?(uri: object_uri) end + def reject_pattern? + Setting.reject_pattern.present? && @object['content']&.match?(Setting.reject_pattern) + end + def forward_for_reply return unless @status.distributable? && @json['signature'].present? && reply_to_local? diff --git a/app/validators/regexp_syntax_validator.rb b/app/validators/regexp_syntax_validator.rb index 57ecf882c2..dd8dc80c9f 100644 --- a/app/validators/regexp_syntax_validator.rb +++ b/app/validators/regexp_syntax_validator.rb @@ -4,10 +4,8 @@ class RegexpSyntaxValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) return if value.blank? - begin - Regexp.compile(value) - rescue RegexpError => e - record.errors.add(attribute, I18n.t('applications.invalid_regexp', message: e.message)) - end + Regexp.compile(value) + rescue RegexpError => e + record.errors.add(attribute, I18n.t('applications.invalid_regexp', message: e.message)) end end