Add ng words for post/update

This commit is contained in:
KMY 2023-07-24 10:38:36 +09:00
parent d4602118fb
commit c553275381
12 changed files with 110 additions and 2 deletions

View file

@ -0,0 +1,34 @@
# frozen_string_literal: true
module Admin
class NgWordsController < BaseController
def show
authorize :ng_words, :show?
@admin_settings = Form::AdminSettings.new
end
def create
authorize :ng_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_ng_words_path
end
def settings_params
params.require(:form_admin_settings).permit(*Form::AdminSettings::KEYS)
end
end
end

View file

@ -88,6 +88,8 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
process_tags
process_audience
return unless valid_status?
ApplicationRecord.transaction do
@status = Status.create!(@params)
attach_tags(@status)
@ -139,6 +141,10 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
}
end
def valid_status?
!Admin::NgWord.reject?("#{@params[:spoiler_text]}\n#{@params[:text]}")
end
def reply_to_local_account?
accounts_in_audience.any?(&:local?)
end

View file

@ -0,0 +1,15 @@
# frozen_string_literal: true
class Admin::NgWord
class << self
def reject?(text)
ng_words.any? { |word| text.include?(word) }
end
private
def ng_words
Setting.ng_words
end
end
end

View file

@ -34,6 +34,7 @@ class Form::AdminSettings
backups_retention_period
status_page_url
captcha_enabled
ng_words
).freeze
INTEGER_KEYS = %i(
@ -61,6 +62,10 @@ class Form::AdminSettings
mascot
).freeze
STRING_ARRAY_KEYS = %i(
ng_words
).freeze
attr_accessor(*KEYS)
validates :registrations_mode, inclusion: { in: %w(open approved none) }, if: -> { defined?(@registrations_mode) }
@ -80,6 +85,8 @@ class Form::AdminSettings
stored_value = if UPLOAD_KEYS.include?(key)
SiteUpload.where(var: key).first_or_initialize(var: key)
elsif STRING_ARRAY_KEYS.include?(key)
Setting.public_send(key)&.join("\n") || ''
else
Setting.public_send(key)
end
@ -122,6 +129,8 @@ class Form::AdminSettings
value == '1'
elsif INTEGER_KEYS.include?(key)
value.blank? ? value : Integer(value)
elsif STRING_ARRAY_KEYS.include?(key)
value&.split(/\r\n|\r|\n/)&.filter(&:present?)&.uniq || []
else
value
end

View file

@ -36,6 +36,7 @@ class UserRole < ApplicationRecord
manage_roles: (1 << 17),
manage_user_access: (1 << 18),
delete_user_data: (1 << 19),
manage_ng_words: (1 << 30),
}.freeze
module Flags
@ -61,6 +62,7 @@ class UserRole < ApplicationRecord
manage_blocks
manage_taxonomies
manage_invites
manage_ng_words
).freeze,
administration: %w(

View file

@ -0,0 +1,11 @@
# frozen_string_literal: true
class NgWordsPolicy < ApplicationPolicy
def show?
role.can?(:manage_ng_words)
end
def create?
role.can?(:manage_ng_words)
end
end

View file

@ -18,7 +18,7 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
@request_id = request_id
# Only native types can be updated at the moment
return @status if !expected_type? || already_updated_more_recently?
return @status if !expected_type? || already_updated_more_recently? || !valid_status?
if @status_parser.edited_at.present? && (@status.edited_at.nil? || @status_parser.edited_at > @status.edited_at)
handle_explicit_update!
@ -152,6 +152,10 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
end
end
def valid_status?
!Admin::NgWord.reject?("#{@status_parser.spoiler_text}\n#{@status_parser.text}")
end
def update_immediate_attributes!
@status.text = @status_parser.text || ''
@status.spoiler_text = @status_parser.spoiler_text || ''

View file

@ -44,6 +44,7 @@ class PostStatusService < BaseService
return idempotency_duplicate if idempotency_given? && idempotency_duplicate?
validate_status!
validate_media!
preprocess_attributes!
@ -158,6 +159,10 @@ class PostStatusService < BaseService
GroupReblogService.new.call(@status)
end
def validate_status!
raise Mastodon::ValidationError, I18n.t('statuses.contains_ng_words') if Admin::NgWord.reject?("#{@options[:spoiler_text]}\n#{@options[:text]}")
end
def validate_media!
if @options[:media_ids].blank? || !@options[:media_ids].is_a?(Enumerable)
@media = []

View file

@ -27,6 +27,8 @@ class UpdateStatusService < BaseService
clear_histories! if @options[:no_history]
validate_status!
Status.transaction do
create_previous_edit! unless @options[:no_history]
update_media_attachments! if @options.key?(:media_ids)
@ -71,6 +73,10 @@ class UpdateStatusService < BaseService
@status.media_attachments.reload
end
def validate_status!
raise Mastodon::ValidationError, I18n.t('statuses.contains_ng_words') if Admin::NgWord.reject?("#{@options[:spoiler_text]}\n#{@options[:text]}")
end
def validate_media!
return [] if @options[:media_ids].blank? || !@options[:media_ids].is_a?(Enumerable)

View file

@ -0,0 +1,14 @@
- content_for :page_title do
= t('admin.ng_words.title')
- content_for :header_tags do
= javascript_pack_tag 'admin', async: true, crossorigin: 'anonymous'
= simple_form_for @admin_settings, url: admin_ng_words_path, html: { method: :post } do |f|
= render 'shared/error_messages', object: @admin_settings
.fields-group
= f.input :ng_words, wrapper: :with_label, as: :text, input_html: { rows: 12 }, label: t('antennas.edit.keywords_raw')
.actions
= f.button :button, t('generic.save_changes'), type: :submit

View file

@ -36,10 +36,11 @@ SimpleNavigation::Configuration.run do |navigation|
s.item :links, safe_join([fa_icon('newspaper-o fw'), t('admin.trends.links.title')]), admin_trends_links_path, highlights_on: %r{/admin/trends/links}
end
n.item :moderation, safe_join([fa_icon('gavel fw'), t('moderation.title')]), nil, if: -> { current_user.can?(:manage_reports, :view_audit_log, :manage_users, :manage_invites, :manage_taxonomies, :manage_federation, :manage_blocks) } do |s|
n.item :moderation, safe_join([fa_icon('gavel fw'), t('moderation.title')]), nil, if: -> { current_user.can?(:manage_reports, :view_audit_log, :manage_users, :manage_invites, :manage_taxonomies, :manage_federation, :manage_blocks, :manage_ng_words) } do |s|
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 :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 :invites, safe_join([fa_icon('user-plus fw'), t('admin.invites.title')]), admin_invites_path, if: -> { current_user.can?(:manage_invites) }
s.item :follow_recommendations, safe_join([fa_icon('user-plus fw'), t('admin.follow_recommendations.title')]), admin_follow_recommendations_path, highlights_on: %r{/admin/follow_recommendations}, if: -> { current_user.can?(:manage_taxonomies) }
s.item :instances, safe_join([fa_icon('cloud fw'), t('admin.instances.title')]), admin_instances_path(limited: whitelist_mode? ? nil : '1'), highlights_on: %r{/admin/instances|/admin/domain_blocks|/admin/domain_allows}, if: -> { current_user.can?(:manage_federation) }

View file

@ -33,6 +33,7 @@ namespace :admin do
resources :action_logs, only: [:index]
resources :warning_presets, except: [:new, :show]
resources :media_attachments, only: [:index]
resource :ng_words, only: [:show, :create]
resources :announcements, except: [:show] do
member do