diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index ec44654b8..cb285896d 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -1080,6 +1080,7 @@ en: min_first_post_typing_time: "Minimum amount of time in milliseconds a user must type during first post, if threshold is not met post will automatically enter the needs approval queue. Set to 0 to disable (not recommended)" auto_block_fast_typers_on_first_post: "Automatically block users that do not meet min_first_post_typing_time" auto_block_fast_typers_max_trust_level: "Maximum trust level to auto block fast typers" + auto_block_first_post_regex: "Case insensitive regex that if passed will cause first post by user to be blocked and sent to approval queue. Example: raging|a[bc]a , will cause all posts containing raging or aba or aca to be blocked on first. Only applies to first post." reply_by_email_enabled: "Enable replying to topics via email." reply_by_email_address: "Template for reply by email incoming email address, for example: %{reply_key}@reply.example.com or replies+%{reply_key}@example.com" diff --git a/config/site_settings.yml b/config/site_settings.yml index 9c41cddee..42401150f 100644 --- a/config/site_settings.yml +++ b/config/site_settings.yml @@ -683,6 +683,7 @@ spam: min_first_post_typing_time: 3000 auto_block_fast_typers_on_first_post: true auto_block_fast_typers_max_trust_level: 0 + auto_block_first_post_regex: "" rate_limits: unique_posts_mins: diff --git a/lib/new_post_manager.rb b/lib/new_post_manager.rb index a2ae5217c..4213d817c 100644 --- a/lib/new_post_manager.rb +++ b/lib/new_post_manager.rb @@ -28,15 +28,40 @@ class NewPostManager @sorted_handlers.sort_by! {|h| -h[:priority]} end - def self.is_fast_typer?(manager) + def self.is_first_post?(manager) user = manager.user args = manager.args args[:first_post_checks] && - user.post_count == 0 && + user.post_count == 0 + end + + def self.is_fast_typer?(manager) + args = manager.args + + is_first_post?(manager) && args[:typing_duration_msecs].to_i < SiteSetting.min_first_post_typing_time end + def self.matches_auto_block_regex?(manager) + args = manager.args + + pattern = SiteSetting.auto_block_first_post_regex + + return false unless pattern.present? + return false unless is_first_post?(manager) + + begin + regex = Regexp.new(pattern, Regexp::IGNORECASE) + rescue => e + Rails.logger.warn "Invalid regex in auto_block_first_post_regex #{e}" + return false + end + + "#{args[:title]} #{args[:raw]}" =~ regex + + end + def self.user_needs_approval?(manager) user = manager.user @@ -44,7 +69,8 @@ class NewPostManager (user.post_count < SiteSetting.approve_post_count) || (user.trust_level < SiteSetting.approve_unless_trust_level.to_i) || - is_fast_typer?(manager) + is_fast_typer?(manager) || + matches_auto_block_regex?(manager) end def self.default_handler(manager) @@ -52,13 +78,13 @@ class NewPostManager result = manager.enqueue('default') - if is_fast_typer?(manager) && - SiteSetting.auto_block_fast_typers_on_first_post && - SiteSetting.auto_block_fast_typers_max_trust_level <= manager.user.trust_level + block = is_fast_typer?(manager) && + SiteSetting.auto_block_fast_typers_on_first_post && + SiteSetting.auto_block_fast_typers_max_trust_level <= manager.user.trust_level - manager.user.update_columns(blocked: true) + block ||= matches_auto_block_regex?(manager) - end + manager.user.update_columns(blocked: true) if block result diff --git a/spec/controllers/posts_controller_spec.rb b/spec/controllers/posts_controller_spec.rb index 7e1c617fd..c26a98ca4 100644 --- a/spec/controllers/posts_controller_spec.rb +++ b/spec/controllers/posts_controller_spec.rb @@ -505,6 +505,20 @@ describe PostsController do end + it 'blocks correctly based on auto_block_first_post_regex' do + SiteSetting.auto_block_first_post_regex = "I love candy|i eat s[1-5]" + + xhr :post, :create, {raw: 'this is the test content', title: 'when I eat s3 sometimes when not looking'} + + expect(response).to be_success + parsed = ::JSON.parse(response.body) + + expect(parsed["action"]).to eq("enqueued") + + user.reload + expect(user.blocked).to eq(true) + end + it 'creates the post' do xhr :post, :create, {raw: 'this is the test content', title: 'this is the test title for the topic'}