FEATURE: optional regex to be applied against first posts
for spam prevention you can add a regex to auto_block_first_post_regex this will be applied against all first posts, if it matches post will go into the approval queue and user will be blocked
This commit is contained in:
parent
d16de4a0a1
commit
ca393bcc53
4 changed files with 50 additions and 8 deletions
config
lib
spec/controllers
|
@ -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)"
|
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_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_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_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"
|
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"
|
||||||
|
|
|
@ -683,6 +683,7 @@ spam:
|
||||||
min_first_post_typing_time: 3000
|
min_first_post_typing_time: 3000
|
||||||
auto_block_fast_typers_on_first_post: true
|
auto_block_fast_typers_on_first_post: true
|
||||||
auto_block_fast_typers_max_trust_level: 0
|
auto_block_fast_typers_max_trust_level: 0
|
||||||
|
auto_block_first_post_regex: ""
|
||||||
|
|
||||||
rate_limits:
|
rate_limits:
|
||||||
unique_posts_mins:
|
unique_posts_mins:
|
||||||
|
|
|
@ -28,15 +28,40 @@ class NewPostManager
|
||||||
@sorted_handlers.sort_by! {|h| -h[:priority]}
|
@sorted_handlers.sort_by! {|h| -h[:priority]}
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.is_fast_typer?(manager)
|
def self.is_first_post?(manager)
|
||||||
user = manager.user
|
user = manager.user
|
||||||
args = manager.args
|
args = manager.args
|
||||||
|
|
||||||
args[:first_post_checks] &&
|
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
|
args[:typing_duration_msecs].to_i < SiteSetting.min_first_post_typing_time
|
||||||
end
|
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)
|
def self.user_needs_approval?(manager)
|
||||||
user = manager.user
|
user = manager.user
|
||||||
|
|
||||||
|
@ -44,7 +69,8 @@ class NewPostManager
|
||||||
|
|
||||||
(user.post_count < SiteSetting.approve_post_count) ||
|
(user.post_count < SiteSetting.approve_post_count) ||
|
||||||
(user.trust_level < SiteSetting.approve_unless_trust_level.to_i) ||
|
(user.trust_level < SiteSetting.approve_unless_trust_level.to_i) ||
|
||||||
is_fast_typer?(manager)
|
is_fast_typer?(manager) ||
|
||||||
|
matches_auto_block_regex?(manager)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.default_handler(manager)
|
def self.default_handler(manager)
|
||||||
|
@ -52,13 +78,13 @@ class NewPostManager
|
||||||
|
|
||||||
result = manager.enqueue('default')
|
result = manager.enqueue('default')
|
||||||
|
|
||||||
if is_fast_typer?(manager) &&
|
block = is_fast_typer?(manager) &&
|
||||||
SiteSetting.auto_block_fast_typers_on_first_post &&
|
SiteSetting.auto_block_fast_typers_on_first_post &&
|
||||||
SiteSetting.auto_block_fast_typers_max_trust_level <= manager.user.trust_level
|
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
|
result
|
||||||
|
|
||||||
|
|
|
@ -505,6 +505,20 @@ describe PostsController do
|
||||||
|
|
||||||
end
|
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
|
it 'creates the post' do
|
||||||
xhr :post, :create, {raw: 'this is the test content', title: 'this is the test title for the topic'}
|
xhr :post, :create, {raw: 'this is the test content', title: 'this is the test title for the topic'}
|
||||||
|
|
||||||
|
|
Reference in a new issue