mirror of
https://github.com/discourse/discourse.git
synced 2025-01-18 13:52:50 +08:00
rate limits for topics and posts on first day
max_topics_in_first_day and max_replies_in_first_day
This commit is contained in:
parent
ecc7ba4be6
commit
ad2ed5fe51
|
@ -17,6 +17,7 @@ class Post < ActiveRecord::Base
|
|||
versioned if: :raw_changed?
|
||||
|
||||
rate_limit
|
||||
rate_limit :limit_posts_per_day
|
||||
|
||||
belongs_to :user
|
||||
belongs_to :topic, counter_cache: :posts_count
|
||||
|
@ -54,6 +55,12 @@ class Post < ActiveRecord::Base
|
|||
@types ||= Enum.new(:regular, :moderator_action)
|
||||
end
|
||||
|
||||
def limit_posts_per_day
|
||||
if user.created_at > 1.day.ago && post_number > 1
|
||||
RateLimiter.new(user, "first-day-replies-per-day:#{Date.today.to_s}", SiteSetting.max_replies_in_first_day, 1.day.to_i)
|
||||
end
|
||||
end
|
||||
|
||||
def trash!(trashed_by=nil)
|
||||
self.topic_links.each(&:destroy)
|
||||
super(trashed_by)
|
||||
|
|
|
@ -66,6 +66,9 @@ class SiteSetting < ActiveRecord::Base
|
|||
setting(:flags_required_to_hide_post, 3)
|
||||
setting(:cooldown_minutes_after_hiding_posts, 10)
|
||||
|
||||
setting(:max_topics_in_first_day, 5)
|
||||
setting(:max_replies_in_first_day, 10)
|
||||
|
||||
setting(:num_flags_to_block_new_user, 3)
|
||||
setting(:num_users_to_block_new_user, 3)
|
||||
setting(:notify_mods_when_user_blocked, false)
|
||||
|
|
|
@ -183,6 +183,9 @@ class Topic < ActiveRecord::Base
|
|||
# Additional rate limits on topics: per day and private messages per day
|
||||
def limit_topics_per_day
|
||||
RateLimiter.new(user, "topics-per-day:#{Date.today.to_s}", SiteSetting.max_topics_per_day, 1.day.to_i)
|
||||
if user.created_at > 1.day.ago
|
||||
RateLimiter.new(user, "first-day-topics-per-day:#{Date.today.to_s}", SiteSetting.max_topics_in_first_day, 1.day.to_i)
|
||||
end
|
||||
end
|
||||
|
||||
def limit_private_messages_per_day
|
||||
|
|
|
@ -530,6 +530,10 @@ en:
|
|||
|
||||
flags_required_to_hide_post: "Number of flags that cause a post to be automatically hidden and PM sent to the user (0 for never)"
|
||||
cooldown_minutes_after_hiding_posts: "Number of minutes a user must wait before they can edit a post hidden via flagging"
|
||||
|
||||
max_topics_in_first_day: "The maximum number of topics a user is alowed to create in thier first day on the site"
|
||||
max_replies_in_first_day: "The maximum number of replies a user is alowed to create in thier first day on the site"
|
||||
|
||||
num_flags_to_block_new_user: "If a new user's posts get this many spam flags from (n) different users, hide all their posts and prevent future posting. 0 disables this feature."
|
||||
num_users_to_block_new_user: "If a new user's posts get (x) spam flags from this many different users, hide all their posts and prevent future posting. 0 disables this feature."
|
||||
notify_mods_when_user_blocked: "If a user is automatically blocked, send a message to all moderators."
|
||||
|
|
|
@ -67,10 +67,14 @@ module SiteSettingExtension
|
|||
|
||||
def client_settings_json
|
||||
Rails.cache.fetch(SiteSettingExtension.client_settings_cache_key, expires_in: 30.minutes) do
|
||||
MultiJson.dump(Hash[*@@client_settings.map{|n| [n, self.send(n)]}.flatten])
|
||||
client_settings_json_uncached
|
||||
end
|
||||
end
|
||||
|
||||
def client_settings_json_uncached
|
||||
MultiJson.dump(Hash[*@@client_settings.map{|n| [n, self.send(n)]}.flatten])
|
||||
end
|
||||
|
||||
# Retrieve all settings
|
||||
def all_settings
|
||||
@defaults.map do |s, v|
|
||||
|
|
|
@ -565,10 +565,9 @@ describe Topic do
|
|||
shared_examples_for "adding a star to a topic" do
|
||||
it 'triggers a forum topic user change with true' do
|
||||
# otherwise no chance the mock will work
|
||||
freeze_time do
|
||||
TopicUser.expects(:change).with(@user, @topic.id, starred: true, starred_at: DateTime.now, unstarred_at: nil)
|
||||
@topic.toggle_star(@user, true)
|
||||
end
|
||||
freeze_time
|
||||
TopicUser.expects(:change).with(@user, @topic.id, starred: true, starred_at: DateTime.now, unstarred_at: nil)
|
||||
@topic.toggle_star(@user, true)
|
||||
end
|
||||
|
||||
it 'increases the star_count of the forum topic' do
|
||||
|
@ -603,10 +602,9 @@ describe Topic do
|
|||
end
|
||||
|
||||
it 'triggers a forum topic user change with false' do
|
||||
freeze_time do
|
||||
TopicUser.expects(:change).with(@user, @topic.id, starred: false, unstarred_at: DateTime.now)
|
||||
@topic.toggle_star(@user, false)
|
||||
end
|
||||
freeze_time
|
||||
TopicUser.expects(:change).with(@user, @topic.id, starred: false, unstarred_at: DateTime.now)
|
||||
@topic.toggle_star(@user, false)
|
||||
end
|
||||
|
||||
it 'reduces the star_count' do
|
||||
|
@ -1181,4 +1179,32 @@ describe Topic do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "limits new users to max_topics_in_first_day and max_posts_in_first_day" do
|
||||
SiteSetting.stubs(:max_topics_in_first_day).returns(1)
|
||||
SiteSetting.stubs(:max_replies_in_first_day).returns(1)
|
||||
RateLimiter.stubs(:disabled?).returns(false)
|
||||
SiteSetting.stubs(:client_settings_json).returns(SiteSetting.client_settings_json_uncached)
|
||||
|
||||
start = Time.now.tomorrow.beginning_of_day
|
||||
|
||||
freeze_time(start)
|
||||
|
||||
user = Fabricate(:user)
|
||||
topic_id = create_post(user: user).topic_id
|
||||
|
||||
freeze_time(start + 10.minutes)
|
||||
lambda {
|
||||
create_post(user: user)
|
||||
}.should raise_exception
|
||||
|
||||
freeze_time(start + 20.minutes)
|
||||
create_post(user: user, topic_id: topic_id)
|
||||
|
||||
freeze_time(start + 30.minutes)
|
||||
|
||||
lambda {
|
||||
create_post(user: user, topic_id: topic_id)
|
||||
}.should raise_exception
|
||||
end
|
||||
end
|
||||
|
|
|
@ -85,26 +85,9 @@ Spork.prefork do
|
|||
|
||||
end
|
||||
|
||||
class DateTime
|
||||
class << self
|
||||
alias_method :old_now, :now
|
||||
def now
|
||||
@now || old_now
|
||||
end
|
||||
def now=(v)
|
||||
@now = v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def freeze_time(d=nil)
|
||||
begin
|
||||
d ||= DateTime.now
|
||||
DateTime.now = d
|
||||
yield
|
||||
ensure
|
||||
DateTime.now = nil
|
||||
end
|
||||
def freeze_time(now=Time.now)
|
||||
DateTime.stubs(:now).returns(DateTime.parse(now.to_s))
|
||||
Time.stubs(:now).returns(Time.parse(now.to_s))
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue
Block a user