Add sensitive words setting
This commit is contained in:
parent
0dbc070037
commit
cd00d7f533
12 changed files with 128 additions and 1 deletions
34
app/controllers/admin/sensitive_words_controller.rb
Normal file
34
app/controllers/admin/sensitive_words_controller.rb
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Admin
|
||||||
|
class SensitiveWordsController < BaseController
|
||||||
|
def show
|
||||||
|
authorize :sensitive_words, :show?
|
||||||
|
|
||||||
|
@admin_settings = Form::AdminSettings.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
authorize :sensitive_words, :create?
|
||||||
|
|
||||||
|
@admin_settings = Form::AdminSettings.new(settings_params)
|
||||||
|
|
||||||
|
if @admin_settings.save
|
||||||
|
flash[:notice] = I18n.t('generic.changes_saved_msg')
|
||||||
|
redirect_to after_update_redirect_path
|
||||||
|
else
|
||||||
|
render :index
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def after_update_redirect_path
|
||||||
|
admin_sensitive_words_path
|
||||||
|
end
|
||||||
|
|
||||||
|
def settings_params
|
||||||
|
params.require(:form_admin_settings).permit(*Form::AdminSettings::KEYS)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
25
app/models/admin/sensitive_word.rb
Normal file
25
app/models/admin/sensitive_word.rb
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Admin::SensitiveWord
|
||||||
|
class << self
|
||||||
|
def sensitive?(text, spoiler_text)
|
||||||
|
exposure_text = (spoiler_text.presence || text)
|
||||||
|
(spoiler_text.blank? && sensitive_words.any? { |word| text.include?(word) }) ||
|
||||||
|
sensitive_words_for_full.any? { |word| exposure_text.include?(word) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def modified_text(text, spoiler_text)
|
||||||
|
spoiler_text.present? ? "#{spoiler_text}\n\n#{text}" : text
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def sensitive_words
|
||||||
|
Setting.sensitive_words || []
|
||||||
|
end
|
||||||
|
|
||||||
|
def sensitive_words_for_full
|
||||||
|
Setting.sensitive_words_for_full || []
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -38,6 +38,8 @@ class Form::AdminSettings
|
||||||
enable_block_emoji_reaction_settings
|
enable_block_emoji_reaction_settings
|
||||||
hide_local_users_for_anonymous
|
hide_local_users_for_anonymous
|
||||||
post_hash_tags_max
|
post_hash_tags_max
|
||||||
|
sensitive_words
|
||||||
|
sensitive_words_for_full
|
||||||
).freeze
|
).freeze
|
||||||
|
|
||||||
INTEGER_KEYS = %i(
|
INTEGER_KEYS = %i(
|
||||||
|
@ -70,6 +72,8 @@ class Form::AdminSettings
|
||||||
|
|
||||||
STRING_ARRAY_KEYS = %i(
|
STRING_ARRAY_KEYS = %i(
|
||||||
ng_words
|
ng_words
|
||||||
|
sensitive_words
|
||||||
|
sensitive_words_for_full
|
||||||
).freeze
|
).freeze
|
||||||
|
|
||||||
attr_accessor(*KEYS)
|
attr_accessor(*KEYS)
|
||||||
|
|
|
@ -36,6 +36,7 @@ class UserRole < ApplicationRecord
|
||||||
manage_roles: (1 << 17),
|
manage_roles: (1 << 17),
|
||||||
manage_user_access: (1 << 18),
|
manage_user_access: (1 << 18),
|
||||||
delete_user_data: (1 << 19),
|
delete_user_data: (1 << 19),
|
||||||
|
manage_sensitive_words: (1 << 29),
|
||||||
manage_ng_words: (1 << 30),
|
manage_ng_words: (1 << 30),
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
|
@ -63,6 +64,7 @@ class UserRole < ApplicationRecord
|
||||||
manage_taxonomies
|
manage_taxonomies
|
||||||
manage_invites
|
manage_invites
|
||||||
manage_ng_words
|
manage_ng_words
|
||||||
|
manage_sensitive_words
|
||||||
).freeze,
|
).freeze,
|
||||||
|
|
||||||
administration: %w(
|
administration: %w(
|
||||||
|
|
11
app/policies/sensitive_words_policy.rb
Normal file
11
app/policies/sensitive_words_policy.rb
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class SensitiveWordsPolicy < ApplicationPolicy
|
||||||
|
def show?
|
||||||
|
role.can?(:manage_sensitive_words)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create?
|
||||||
|
role.can?(:manage_sensitive_words)
|
||||||
|
end
|
||||||
|
end
|
|
@ -82,10 +82,18 @@ class PostStatusService < BaseService
|
||||||
@scheduled_at = @options[:scheduled_at]&.to_datetime
|
@scheduled_at = @options[:scheduled_at]&.to_datetime
|
||||||
@scheduled_at = nil if scheduled_in_the_past?
|
@scheduled_at = nil if scheduled_in_the_past?
|
||||||
@reference_ids = (@options[:status_reference_ids] || []).map(&:to_i).filter(&:positive?)
|
@reference_ids = (@options[:status_reference_ids] || []).map(&:to_i).filter(&:positive?)
|
||||||
|
process_sensitive_words
|
||||||
rescue ArgumentError
|
rescue ArgumentError
|
||||||
raise ActiveRecord::RecordInvalid
|
raise ActiveRecord::RecordInvalid
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def process_sensitive_words
|
||||||
|
if [:public, :public_unlisted, :login].include?(@visibility&.to_sym) && Admin::SensitiveWord.sensitive?(@text, @options[:spoiler_text] || '')
|
||||||
|
@text = Admin::SensitiveWord.modified_text(@text, @options[:spoiler_text])
|
||||||
|
@options[:spoiler_text] = I18n.t('admin.sensitive_words.alert')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def searchability
|
def searchability
|
||||||
return :private if @options[:searchability]&.to_sym == :public && @visibility&.to_sym == :unlisted && @account.user&.setting_disallow_unlisted_public_searchability
|
return :private if @options[:searchability]&.to_sym == :public && @visibility&.to_sym == :unlisted && @account.user&.setting_disallow_unlisted_public_searchability
|
||||||
|
|
||||||
|
|
|
@ -127,6 +127,7 @@ class UpdateStatusService < BaseService
|
||||||
@status.markdown = @options[:markdown] || false
|
@status.markdown = @options[:markdown] || false
|
||||||
@status.sensitive = @options[:sensitive] || @options[:spoiler_text].present? if @options.key?(:sensitive) || @options.key?(:spoiler_text)
|
@status.sensitive = @options[:sensitive] || @options[:spoiler_text].present? if @options.key?(:sensitive) || @options.key?(:spoiler_text)
|
||||||
@status.language = valid_locale_cascade(@options[:language], @status.language, @status.account.user&.preferred_posting_language, I18n.default_locale)
|
@status.language = valid_locale_cascade(@options[:language], @status.language, @status.account.user&.preferred_posting_language, I18n.default_locale)
|
||||||
|
process_sensitive_words
|
||||||
|
|
||||||
# We raise here to rollback the entire transaction
|
# We raise here to rollback the entire transaction
|
||||||
raise NoChangesSubmittedError unless significant_changes?
|
raise NoChangesSubmittedError unless significant_changes?
|
||||||
|
@ -137,6 +138,13 @@ class UpdateStatusService < BaseService
|
||||||
@status.save!
|
@status.save!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def process_sensitive_words
|
||||||
|
return unless [:public, :public_unlisted, :login].include?(@status.visibility&.to_sym) && Admin::SensitiveWord.sensitive?(@status.text, @status.spoiler_text || '')
|
||||||
|
|
||||||
|
@status.text = Admin::SensitiveWord.modified_text(@status.text, @status.spoiler_text)
|
||||||
|
@status.spoiler_text = I18n.t('admin.sensitive_words.alert')
|
||||||
|
end
|
||||||
|
|
||||||
def update_expiration!
|
def update_expiration!
|
||||||
UpdateStatusExpirationService.new.call(@status)
|
UpdateStatusExpirationService.new.call(@status)
|
||||||
end
|
end
|
||||||
|
|
19
app/views/admin/sensitive_words/show.html.haml
Normal file
19
app/views/admin/sensitive_words/show.html.haml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
- content_for :page_title do
|
||||||
|
= t('admin.sensitive_words.title')
|
||||||
|
|
||||||
|
- content_for :header_tags do
|
||||||
|
= javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous'
|
||||||
|
|
||||||
|
%p.hint= t 'admin.sensitive_words.hint'
|
||||||
|
|
||||||
|
= simple_form_for @admin_settings, url: admin_sensitive_words_path, html: { method: :post } do |f|
|
||||||
|
= render 'shared/error_messages', object: @admin_settings
|
||||||
|
|
||||||
|
.fields-group
|
||||||
|
= f.input :sensitive_words_for_full, wrapper: :with_label, as: :text, input_html: { rows: 12 }, label: t('admin.sensitive_words.keywords_for_all'), hint: t('admin.sensitive_words.keywords_for_all_hint')
|
||||||
|
|
||||||
|
.fields-group
|
||||||
|
= f.input :sensitive_words, wrapper: :with_label, as: :text, input_html: { rows: 12 }, label: t('admin.sensitive_words.keywords'), hint: t('admin.sensitive_words.keywords_hint')
|
||||||
|
|
||||||
|
.actions
|
||||||
|
= f.button :button, t('generic.save_changes'), type: :submit
|
|
@ -773,6 +773,12 @@ en:
|
||||||
edit: Edit rule
|
edit: Edit rule
|
||||||
empty: No server rules have been defined yet.
|
empty: No server rules have been defined yet.
|
||||||
title: Server rules
|
title: Server rules
|
||||||
|
sensitive_words:
|
||||||
|
alert: This post contains sensitive words, so alert added
|
||||||
|
hint: This keywords is applied to public posts only..
|
||||||
|
keywords: Sensitive keywords
|
||||||
|
keywords_for_all: Sensitive keywords (Contains CW alert)
|
||||||
|
title: Sensitive words and moderation options
|
||||||
settings:
|
settings:
|
||||||
about:
|
about:
|
||||||
manage_rules: Manage server rules
|
manage_rules: Manage server rules
|
||||||
|
|
|
@ -769,6 +769,14 @@ ja:
|
||||||
edit: ルールを編集
|
edit: ルールを編集
|
||||||
empty: サーバーのルールが定義されていません。
|
empty: サーバーのルールが定義されていません。
|
||||||
title: サーバーのルール
|
title: サーバーのルール
|
||||||
|
sensitive_words:
|
||||||
|
alert: この投稿にはセンシティブなキーワードが含まれるため、警告文が追加されました
|
||||||
|
hint: センシティブなキーワードの設定は、当サーバーのローカルユーザーによる公開範囲「公開」「ローカル公開」「ログインユーザーのみ」に対して適用されます。
|
||||||
|
keywords: センシティブなキーワード(警告文は除外)
|
||||||
|
keywords_for_all: センシティブなキーワード(警告文にも適用)
|
||||||
|
keywords_for_all_hint: ここで指定したキーワードを含む投稿は強制的にCWになります。警告文にも含まれていればCWになります
|
||||||
|
keywords_hint: ここで指定したキーワードを含む投稿は強制的にCWになります。ただし警告文に使用していた場合は無視されます
|
||||||
|
title: センシティブ単語と設定
|
||||||
settings:
|
settings:
|
||||||
about:
|
about:
|
||||||
manage_rules: サーバーのルールを管理
|
manage_rules: サーバーのルールを管理
|
||||||
|
|
|
@ -40,7 +40,8 @@ SimpleNavigation::Configuration.run do |navigation|
|
||||||
s.item :reports, safe_join([fa_icon('flag fw'), t('admin.reports.title')]), admin_reports_path, highlights_on: %r{/admin/reports}, if: -> { current_user.can?(:manage_reports) }
|
s.item :reports, safe_join([fa_icon('flag fw'), t('admin.reports.title')]), admin_reports_path, highlights_on: %r{/admin/reports}, if: -> { current_user.can?(:manage_reports) }
|
||||||
s.item :accounts, safe_join([fa_icon('users fw'), t('admin.accounts.title')]), admin_accounts_path(origin: 'local'), highlights_on: %r{/admin/accounts|/admin/pending_accounts|/admin/disputes|/admin/users}, if: -> { current_user.can?(:manage_users) }
|
s.item :accounts, safe_join([fa_icon('users fw'), t('admin.accounts.title')]), admin_accounts_path(origin: 'local'), highlights_on: %r{/admin/accounts|/admin/pending_accounts|/admin/disputes|/admin/users}, if: -> { current_user.can?(:manage_users) }
|
||||||
s.item :media_attachments, safe_join([fa_icon('picture-o fw'), t('admin.media_attachments.title')]), admin_media_attachments_path, highlights_on: %r{/admin/media_attachments}, if: -> { current_user.can?(:manage_users) }
|
s.item :media_attachments, safe_join([fa_icon('picture-o fw'), t('admin.media_attachments.title')]), admin_media_attachments_path, highlights_on: %r{/admin/media_attachments}, if: -> { current_user.can?(:manage_users) }
|
||||||
s.item :ng_words, safe_join([fa_icon('picture-o fw'), t('admin.ng_words.title')]), admin_ng_words_path, highlights_on: %r{/admin/ng_words}, if: -> { current_user.can?(:manage_ng_words) }
|
s.item :ng_words, safe_join([fa_icon('list fw'), t('admin.ng_words.title')]), admin_ng_words_path, highlights_on: %r{/admin/ng_words}, if: -> { current_user.can?(:manage_ng_words) }
|
||||||
|
s.item :sensitive_words, safe_join([fa_icon('list fw'), t('admin.sensitive_words.title')]), admin_sensitive_words_path, highlights_on: %r{/admin/sensitive_words}, if: -> { current_user.can?(:manage_sensitive_words) }
|
||||||
s.item :invites, safe_join([fa_icon('user-plus fw'), t('admin.invites.title')]), admin_invites_path, if: -> { current_user.can?(:manage_invites) }
|
s.item :invites, safe_join([fa_icon('user-plus fw'), t('admin.invites.title')]), admin_invites_path, if: -> { current_user.can?(:manage_invites) }
|
||||||
s.item :follow_recommendations, safe_join([fa_icon('user-plus fw'), t('admin.follow_recommendations.title')]), admin_follow_recommendations_path, highlights_on: %r{/admin/follow_recommendations}, if: -> { current_user.can?(:manage_taxonomies) }
|
s.item :follow_recommendations, safe_join([fa_icon('user-plus fw'), t('admin.follow_recommendations.title')]), admin_follow_recommendations_path, highlights_on: %r{/admin/follow_recommendations}, if: -> { current_user.can?(:manage_taxonomies) }
|
||||||
s.item :instances, safe_join([fa_icon('cloud fw'), t('admin.instances.title')]), admin_instances_path(limited: whitelist_mode? ? nil : '1'), highlights_on: %r{/admin/instances|/admin/domain_blocks|/admin/domain_allows}, if: -> { current_user.can?(:manage_federation) }
|
s.item :instances, safe_join([fa_icon('cloud fw'), t('admin.instances.title')]), admin_instances_path(limited: whitelist_mode? ? nil : '1'), highlights_on: %r{/admin/instances|/admin/domain_blocks|/admin/domain_allows}, if: -> { current_user.can?(:manage_federation) }
|
||||||
|
|
|
@ -34,6 +34,7 @@ namespace :admin do
|
||||||
resources :warning_presets, except: [:new, :show]
|
resources :warning_presets, except: [:new, :show]
|
||||||
resources :media_attachments, only: [:index]
|
resources :media_attachments, only: [:index]
|
||||||
resource :ng_words, only: [:show, :create]
|
resource :ng_words, only: [:show, :create]
|
||||||
|
resource :sensitive_words, only: [:show, :create]
|
||||||
|
|
||||||
resources :announcements, except: [:show] do
|
resources :announcements, except: [:show] do
|
||||||
member do
|
member do
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue