Add: #545 NGワード指定で実際に除外された投稿のログ (#561)

This commit is contained in:
KMY(雪あすか) 2024-02-16 17:52:59 +09:00 committed by GitHub
parent 0ca2a73fd2
commit 7421c89431
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 262 additions and 17 deletions

View file

@ -0,0 +1,19 @@
# frozen_string_literal: true
module Admin
class NgwordHistoriesController < BaseController
before_action :set_histories
PER_PAGE = 20
def index
authorize :ng_words, :show?
end
private
def set_histories
@histories = NgwordHistory.order(id: :desc).page(params[:page]).per(PER_PAGE)
end
end
end

View file

@ -143,9 +143,9 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
end end
def valid_status? def valid_status?
valid = !Admin::NgWord.reject?("#{@params[:spoiler_text]}\n#{@params[:text]}") && !Admin::NgWord.hashtag_reject?(@tags.size) valid = !Admin::NgWord.reject?("#{@params[:spoiler_text]}\n#{@params[:text]}", uri: @params[:uri], target_type: :status, public: @status_parser.distributable_visibility?) && !Admin::NgWord.hashtag_reject?(@tags.size)
valid = !Admin::NgWord.stranger_mention_reject?("#{@params[:spoiler_text]}\n#{@params[:text]}") if valid && mention_to_local_but_not_followed? valid = !Admin::NgWord.stranger_mention_reject?("#{@params[:spoiler_text]}\n#{@params[:text]}", uri: @params[:uri], target_type: :status, public: @status_parser.distributable_visibility?) if valid && mention_to_local_but_not_followed?
valid valid
end end

View file

@ -92,6 +92,10 @@ class ActivityPub::Parser::StatusParser
end end
end end
def distributable_visibility?
%i(public public_unlisted unlisted login).include?(visibility)
end
def searchability def searchability
from_audience = searchability_from_audience from_audience = searchability_from_audience
return from_audience if from_audience return from_audience if from_audience

View file

@ -2,8 +2,16 @@
class Admin::NgWord class Admin::NgWord
class << self class << self
def reject?(text) def reject?(text, **options)
ng_words.any? { |word| include?(text, word) } hit_word = ng_words.detect { |word| include?(text, word) ? word : nil }
record!(:ng_words, text, hit_word, options) if hit_word.present?
hit_word.present?
end
def stranger_mention_reject?(text, **options)
hit_word = ng_words_for_stranger_mention.detect { |word| include?(text, word) ? word : nil }
record!(:ng_words_for_stranger_mention, text, hit_word, options) if hit_word.present?
hit_word.present?
end end
def reject_with_custom_words?(text, custom_ng_words) def reject_with_custom_words?(text, custom_ng_words)
@ -18,10 +26,6 @@ class Admin::NgWord
hashtag_reject?(Extractor.extract_hashtags(text)&.size || 0) hashtag_reject?(Extractor.extract_hashtags(text)&.size || 0)
end end
def stranger_mention_reject?(text)
ng_words_for_stranger_mention.any? { |word| include?(text, word) }
end
private private
def include?(text, word) def include?(text, word)
@ -44,5 +48,18 @@ class Admin::NgWord
value = Setting.post_hash_tags_max value = Setting.post_hash_tags_max
value.is_a?(Integer) && value.positive? ? value : 0 value.is_a?(Integer) && value.positive? ? value : 0
end end
def record!(type, text, keyword, options)
return unless options[:uri] && options[:target_type]
return if options.key?(:public) && !options.delete(:public)
return if NgwordHistory.where('created_at > ?', 1.day.ago).exists?(uri: options[:uri], keyword: options[:keyword])
NgwordHistory.create(options.merge({
reason: type,
text: text,
keyword: keyword,
}))
end
end end
end end

View file

@ -0,0 +1,21 @@
# frozen_string_literal: true
# == Schema Information
#
# Table name: ngword_histories
#
# id :bigint(8) not null, primary key
# uri :string not null
# target_type :integer not null
# reason :integer not null
# text :string not null
# keyword :string not null
# created_at :datetime not null
# updated_at :datetime not null
#
class NgwordHistory < ApplicationRecord
include Paginable
enum target_type: { status: 0, account_note: 1, account_name: 2 }, _suffix: :blocked
enum reason: { ng_words: 0, ng_words_for_stranger_mention: 1 }, _prefix: :within
end

View file

@ -14,7 +14,6 @@
# sign_in_count :integer default(0), not null # sign_in_count :integer default(0), not null
# current_sign_in_at :datetime # current_sign_in_at :datetime
# last_sign_in_at :datetime # last_sign_in_at :datetime
# admin :boolean default(FALSE), not null
# confirmation_token :string # confirmation_token :string
# confirmed_at :datetime # confirmed_at :datetime
# confirmation_sent_at :datetime # confirmation_sent_at :datetime
@ -29,7 +28,6 @@
# otp_backup_codes :string is an Array # otp_backup_codes :string is an Array
# account_id :bigint(8) not null # account_id :bigint(8) not null
# disabled :boolean default(FALSE), not null # disabled :boolean default(FALSE), not null
# moderator :boolean default(FALSE), not null
# invite_id :bigint(8) # invite_id :bigint(8)
# chosen_languages :string is an Array # chosen_languages :string is an Array
# created_by_application_id :bigint(8) # created_by_application_id :bigint(8)

View file

@ -133,7 +133,8 @@ class ActivityPub::ProcessAccountService < BaseService
def valid_account? def valid_account?
display_name = @json['name'] || '' display_name = @json['name'] || ''
note = @json['summary'] || '' note = @json['summary'] || ''
!Admin::NgWord.reject?(display_name) && !Admin::NgWord.reject?(note) !Admin::NgWord.reject?(display_name, uri: @uri, target_type: :account_name) &&
!Admin::NgWord.reject?(note, uri: @uri, target_type: :account_note)
end end
def set_fetchable_key! def set_fetchable_key!

View file

@ -161,11 +161,11 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
end end
def valid_status? def valid_status?
!Admin::NgWord.reject?("#{@status_parser.spoiler_text}\n#{@status_parser.text}") && !Admin::NgWord.hashtag_reject?(@raw_tags.size) !Admin::NgWord.reject?("#{@status_parser.spoiler_text}\n#{@status_parser.text}", uri: @status.uri, target_type: :status) && !Admin::NgWord.hashtag_reject?(@raw_tags.size)
end end
def validate_status_mentions! def validate_status_mentions!
raise AbortError if mention_to_stranger? && Admin::NgWord.stranger_mention_reject?("#{@status.spoiler_text}\n#{@status.text}") raise AbortError if mention_to_stranger? && Admin::NgWord.stranger_mention_reject?("#{@status.spoiler_text}\n#{@status.text}", uri: @status.uri, target_type: :status)
end end
def mention_to_stranger? def mention_to_stranger?

View file

@ -7,14 +7,18 @@
= simple_form_for @admin_settings, url: admin_ng_words_path, html: { method: :post } do |f| = simple_form_for @admin_settings, url: admin_ng_words_path, html: { method: :post } do |f|
= render 'shared/error_messages', object: @admin_settings = render 'shared/error_messages', object: @admin_settings
%p.hint
= t 'admin.ng_words.history_hint'
= link_to t('admin.ngword_histories.title'), admin_ngword_histories_path
.fields-group .fields-group
= f.input :ng_words_for_stranger_mention, wrapper: :with_label, as: :text, input_html: { rows: 12 }, label: t('admin.ng_words.keywords_for_stranger_mention'), hint: t('admin.ng_words.keywords_for_stranger_mention_hint') = f.input :ng_words_for_stranger_mention, wrapper: :with_label, as: :text, input_html: { rows: 10 }, label: t('admin.ng_words.keywords_for_stranger_mention'), hint: t('admin.ng_words.keywords_for_stranger_mention_hint')
.fields-group .fields-group
= f.input :stranger_mention_from_local_ng, wrapper: :with_label, as: :boolean, label: t('admin.ng_words.stranger_mention_from_local_ng'), hint: t('admin.ng_words.stranger_mention_from_local_ng_hint') = f.input :stranger_mention_from_local_ng, wrapper: :with_label, as: :boolean, label: t('admin.ng_words.stranger_mention_from_local_ng'), hint: t('admin.ng_words.stranger_mention_from_local_ng_hint')
.fields-group .fields-group
= f.input :ng_words, wrapper: :with_label, as: :text, input_html: { rows: 12 }, label: t('admin.ng_words.keywords'), hint: t('admin.ng_words.keywords_hint') = f.input :ng_words, wrapper: :with_label, as: :text, input_html: { rows: 10 }, label: t('admin.ng_words.keywords'), hint: t('admin.ng_words.keywords_hint')
.fields-group .fields-group
= f.input :post_hash_tags_max, wrapper: :with_label, as: :integer, label: t('admin.ng_words.post_hash_tags_max') = f.input :post_hash_tags_max, wrapper: :with_label, as: :integer, label: t('admin.ng_words.post_hash_tags_max')

View file

@ -0,0 +1,30 @@
.batch-table__row
%label.batch-table__row__select.batch-checkbox
-# = f.check_box :history_ids, { multiple: true, include_hidden: false }, history.id
.batch-table__row__content
.status__content><
= html_aware_format(history.text, false)
.detailed-status__meta
%span.negative-hint= history.keyword
·
- if history.within_ng_words?
= t('admin.ng_words.keywords')
- elsif history.within_ng_words_for_stranger_mention?
= t('admin.ng_words.keywords_for_stranger_mention')
%br/
%time.formatted{ datetime: history.created_at.iso8601, title: l(history.created_at) }= l(history.created_at)
·
- if history.account_note_blocked?
= t('admin.ngword_history.target_types.account_note')
- elsif history.account_name_blocked?
= t('admin.ngword_history.target_types.account_name')
- elsif history.status_blocked?
= t('admin.ngword_history.target_types.status')
·
= history.uri
-# if history.application
= history.application.name
·

View file

@ -0,0 +1,22 @@
- content_for :page_title do
= t('admin.ngword_histories.title')
.filters
.back-link
= link_to admin_ng_words_path do
= fa_icon 'chevron-left fw'
= t('admin.ngword_histories.back_to_ng_words')
%hr.spacer/
.batch-table
.batch-table__toolbar
%label.batch-table__toolbar__select.batch-checkbox-all
= check_box_tag :batch_checkbox_all, nil, false
.batch-table__body
- if @histories.empty?
= nothing_here 'nothing-here--under-tabs'
- else
= render partial: 'admin/ngword_histories/history', collection: @histories
= paginate @histories

View file

@ -642,6 +642,7 @@ en:
title: Media attachments title: Media attachments
ng_words: ng_words:
hide_local_users_for_anonymous: Hide timeline local user posts from anonymous hide_local_users_for_anonymous: Hide timeline local user posts from anonymous
history_hint: We recommend that you regularly check your NG words to make sure that you have not specified the NG words incorrectly.
keywords: Reject keywords keywords: Reject keywords
keywords_for_stranger_mention: Reject keywords when mention/reply from strangers keywords_for_stranger_mention: Reject keywords when mention/reply from strangers
keywords_for_stranger_mention_hint: Currently this words are checked posts from other servers only. keywords_for_stranger_mention_hint: Currently this words are checked posts from other servers only.
@ -651,6 +652,13 @@ en:
stranger_mention_from_local_ng_hint: サーバーの登録が承認制でない場合、あなたのサーバーにもスパムが入り込む可能性があります stranger_mention_from_local_ng_hint: サーバーの登録が承認制でない場合、あなたのサーバーにもスパムが入り込む可能性があります
test_error: Testing is returned any errors test_error: Testing is returned any errors
title: NG words and against spams title: NG words and against spams
ngword_histories:
back_to_ng_words: NG words and against spams
target_types:
account_name: Account name
account_note: Account note
status: Post
title: NG words history
relationships: relationships:
title: "%{acct}'s relationships" title: "%{acct}'s relationships"
relays: relays:

View file

@ -635,6 +635,7 @@ ja:
title: 投稿された画像 title: 投稿された画像
ng_words: ng_words:
hide_local_users_for_anonymous: ログインしていない状態でローカルユーザーの投稿をタイムラインから取得できないようにする hide_local_users_for_anonymous: ログインしていない状態でローカルユーザーの投稿をタイムラインから取得できないようにする
history_hint: 設定されたNGワードによって実際に拒否された投稿などは、履歴より確認できます。NGワードの指定に誤りがないか定期的に確認することをおすすめします。
keywords: 投稿できないキーワード keywords: 投稿できないキーワード
keywords_for_stranger_mention: フォローしていないアカウントへのメンションで利用できないキーワード keywords_for_stranger_mention: フォローしていないアカウントへのメンションで利用できないキーワード
keywords_for_stranger_mention_hint: フォローしていないアカウントへのメンションにのみ適用されます。現状は外部サーバーから来た投稿のみに適用されます keywords_for_stranger_mention_hint: フォローしていないアカウントへのメンションにのみ適用されます。現状は外部サーバーから来た投稿のみに適用されます
@ -644,6 +645,13 @@ ja:
stranger_mention_from_local_ng_hint: サーバーの登録が承認制でない場合、あなたのサーバーにもスパムが入り込む可能性があります stranger_mention_from_local_ng_hint: サーバーの登録が承認制でない場合、あなたのサーバーにもスパムが入り込む可能性があります
test_error: NGワードのテストに失敗しました。正規表現のミスが含まれているかもしれません test_error: NGワードのテストに失敗しました。正規表現のミスが含まれているかもしれません
title: NGワードとスパム title: NGワードとスパム
ngword_histories:
back_to_ng_words: NGワードとスパム
target_types:
account_name: アカウントの名前
account_note: アカウントの説明文
status: 投稿
title: NGワード検出履歴
relationships: relationships:
title: "%{acct} さんのフォロー・フォロワー" title: "%{acct} さんのフォロー・フォロワー"
relays: relays:

View file

@ -49,7 +49,7 @@ SimpleNavigation::Configuration.run do |navigation|
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, :manage_sensitive_words) && !self_destruct } 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, :manage_sensitive_words) && !self_destruct } 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 :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 :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 :ng_words, safe_join([fa_icon('list fw'), t('admin.ng_words.title')]), admin_ng_words_path, highlights_on: %r{/admin/(ng_words|ngword_histories)}, 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 :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) }

View file

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

View file

@ -0,0 +1,17 @@
# frozen_string_literal: true
class CreateNgwordHistories < ActiveRecord::Migration[7.1]
def change
create_table :ngword_histories do |t|
t.string :uri, null: false
t.integer :target_type, null: false
t.integer :reason, null: false
t.string :text, null: false
t.string :keyword, null: false
t.timestamps
end
add_index :ngword_histories, [:uri, :keyword, :created_at], unique: false
end
end

View file

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.1].define(version: 2024_02_12_230358) do ActiveRecord::Schema[7.1].define(version: 2024_02_16_042730) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -868,6 +868,17 @@ ActiveRecord::Schema[7.1].define(version: 2024_02_12_230358) do
t.index ["target_account_id"], name: "index_mutes_on_target_account_id" t.index ["target_account_id"], name: "index_mutes_on_target_account_id"
end end
create_table "ngword_histories", force: :cascade do |t|
t.string "uri", null: false
t.integer "target_type", null: false
t.integer "reason", null: false
t.string "text", null: false
t.string "keyword", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["uri", "keyword", "created_at"], name: "index_ngword_histories_on_uri_and_keyword_and_created_at"
end
create_table "notifications", force: :cascade do |t| create_table "notifications", force: :cascade do |t|
t.bigint "activity_id", null: false t.bigint "activity_id", null: false
t.string "activity_type", null: false t.string "activity_type", null: false

View file

@ -1781,6 +1781,11 @@ RSpec.describe ActivityPub::Activity::Create do
it 'creates status' do it 'creates status' do
expect(sender.statuses.first).to_not be_nil expect(sender.statuses.first).to_not be_nil
end end
it 'does not record history' do
history = NgwordHistory.find_by(uri: object_json[:id])
expect(history).to be_nil
end
end end
context 'when hit ng words' do context 'when hit ng words' do
@ -1789,6 +1794,34 @@ RSpec.describe ActivityPub::Activity::Create do
it 'creates status' do it 'creates status' do
expect(sender.statuses.first).to be_nil expect(sender.statuses.first).to be_nil
end end
it 'records history' do
history = NgwordHistory.find_by(uri: object_json[:id])
expect(history).to_not be_nil
expect(history.status_blocked?).to be true
expect(history.within_ng_words?).to be true
expect(history.keyword).to eq ng_words
end
end
context 'when hit ng words but does not public visibility' do
let(:content) { 'hello, world!' }
let(:object_json) do
{
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
type: 'Note',
content: content,
}
end
it 'creates status' do
expect(sender.statuses.first).to be_nil
end
it 'records history' do
history = NgwordHistory.find_by(uri: object_json[:id])
expect(history).to be_nil
end
end end
context 'when mention from tags' do context 'when mention from tags' do
@ -1799,6 +1832,7 @@ RSpec.describe ActivityPub::Activity::Create do
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
type: 'Note', type: 'Note',
content: content, content: content,
to: 'https://www.w3.org/ns/activitystreams#Public',
tag: [ tag: [
{ {
type: 'Mention', type: 'Mention',
@ -1814,6 +1848,11 @@ RSpec.describe ActivityPub::Activity::Create do
it 'creates status' do it 'creates status' do
expect(sender.statuses.first).to_not be_nil expect(sender.statuses.first).to_not be_nil
end end
it 'does not record history' do
history = NgwordHistory.find_by(uri: object_json[:id])
expect(history).to be_nil
end
end end
context 'with using ng words for stranger' do context 'with using ng words for stranger' do
@ -1822,6 +1861,14 @@ RSpec.describe ActivityPub::Activity::Create do
it 'creates status' do it 'creates status' do
expect(sender.statuses.first).to be_nil expect(sender.statuses.first).to be_nil
end end
it 'records history' do
history = NgwordHistory.find_by(uri: object_json[:id])
expect(history).to_not be_nil
expect(history.status_blocked?).to be true
expect(history.within_ng_words_for_stranger_mention?).to be true
expect(history.keyword).to eq ng_words_for_stranger_mention
end
end end
context 'with using ng words for stranger but receiver is following him' do context 'with using ng words for stranger but receiver is following him' do
@ -1836,6 +1883,11 @@ RSpec.describe ActivityPub::Activity::Create do
it 'creates status' do it 'creates status' do
expect(sender.statuses.first).to_not be_nil expect(sender.statuses.first).to_not be_nil
end end
it 'does not record history' do
history = NgwordHistory.find_by(uri: object_json[:id])
expect(history).to be_nil
end
end end
context 'with using ng words for stranger but multiple receivers are partically following him' do context 'with using ng words for stranger but multiple receivers are partically following him' do
@ -1847,6 +1899,7 @@ RSpec.describe ActivityPub::Activity::Create do
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
type: 'Note', type: 'Note',
content: content, content: content,
to: 'https://www.w3.org/ns/activitystreams#Public',
tag: [ tag: [
{ {
type: 'Mention', type: 'Mention',
@ -1868,6 +1921,14 @@ RSpec.describe ActivityPub::Activity::Create do
it 'creates status' do it 'creates status' do
expect(sender.statuses.first).to be_nil expect(sender.statuses.first).to be_nil
end end
it 'records history' do
history = NgwordHistory.find_by(uri: object_json[:id])
expect(history).to_not be_nil
expect(history.status_blocked?).to be true
expect(history.within_ng_words_for_stranger_mention?).to be true
expect(history.keyword).to eq ng_words_for_stranger_mention
end
end end
end end
@ -1880,6 +1941,7 @@ RSpec.describe ActivityPub::Activity::Create do
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
type: 'Note', type: 'Note',
content: 'ohagi peers', content: 'ohagi peers',
to: 'https://www.w3.org/ns/activitystreams#Public',
inReplyTo: ActivityPub::TagManager.instance.uri_for(original_status), inReplyTo: ActivityPub::TagManager.instance.uri_for(original_status),
} }
end end
@ -1888,6 +1950,14 @@ RSpec.describe ActivityPub::Activity::Create do
it 'creates status' do it 'creates status' do
expect(sender.statuses.first).to be_nil expect(sender.statuses.first).to be_nil
end end
it 'records history' do
history = NgwordHistory.find_by(uri: object_json[:id])
expect(history).to_not be_nil
expect(history.status_blocked?).to be true
expect(history.within_ng_words_for_stranger_mention?).to be true
expect(history.keyword).to eq ng_words_for_stranger_mention
end
end end
context 'with following' do context 'with following' do
@ -1901,6 +1971,11 @@ RSpec.describe ActivityPub::Activity::Create do
it 'creates status' do it 'creates status' do
expect(sender.statuses.first).to_not be_nil expect(sender.statuses.first).to_not be_nil
end end
it 'does not record history' do
history = NgwordHistory.find_by(uri: object_json[:id])
expect(history).to be_nil
end
end end
end end
end end

View file

@ -308,12 +308,21 @@ RSpec.describe ActivityPub::ProcessAccountService, type: :service do
Setting.ng_words = ['Amazon'] Setting.ng_words = ['Amazon']
subject subject
expect(account.reload.display_name).to eq 'Ohagi' expect(account.reload.display_name).to eq 'Ohagi'
history = NgwordHistory.find_by(uri: payload[:id])
expect(history).to be_nil
end end
it 'does not create account when ng word is set' do it 'does not create account when ng word is set' do
Setting.ng_words = ['Ohagi'] Setting.ng_words = ['Ohagi']
subject subject
expect(account.reload.display_name).to_not eq 'Ohagi' expect(account.reload.display_name).to_not eq 'Ohagi'
history = NgwordHistory.find_by(uri: payload[:id])
expect(history).to_not be_nil
expect(history.account_name_blocked?).to be true
expect(history.within_ng_words?).to be true
expect(history.keyword).to eq 'Ohagi'
end end
end end