2019-05-02 18:17:27 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2013-02-05 14:16:51 -05:00
|
|
|
class RateLimiter
|
|
|
|
# A mixin we can use on ActiveRecord Models to automatically rate limit them
|
|
|
|
# based on a SiteSetting.
|
|
|
|
#
|
|
|
|
# It expects a SiteSetting called `rate_limit_create_{model_name}` where
|
2013-02-25 11:42:20 -05:00
|
|
|
# `model_name` is the class name of your model, underscored.
|
2013-02-05 14:16:51 -05:00
|
|
|
#
|
|
|
|
module OnCreateRecord
|
|
|
|
# Over write to define your own rate limiter
|
|
|
|
def default_rate_limiter
|
|
|
|
return @rate_limiter if @rate_limiter.present?
|
|
|
|
|
|
|
|
limit_key = "create_#{self.class.name.underscore}"
|
2016-04-13 10:16:03 -04:00
|
|
|
max_setting =
|
|
|
|
if user && user.new_user? && SiteSetting.has_setting?("rate_limit_new_user_#{limit_key}")
|
2019-05-06 21:00:09 -04:00
|
|
|
SiteSetting.get("rate_limit_new_user_#{limit_key}")
|
2014-07-14 16:58:10 -04:00
|
|
|
else
|
2019-05-06 21:00:09 -04:00
|
|
|
SiteSetting.get("rate_limit_#{limit_key}")
|
2014-07-14 16:58:10 -04:00
|
|
|
end
|
2013-02-25 11:42:20 -05:00
|
|
|
@rate_limiter = RateLimiter.new(user, limit_key, 1, max_setting)
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def self.included(base)
|
2013-02-25 11:42:20 -05:00
|
|
|
base.extend(ClassMethods)
|
2015-04-21 13:16:05 -04:00
|
|
|
end
|
|
|
|
|
2015-04-21 13:35:00 -04:00
|
|
|
# For the lifetime of this instance, don't enforce rate limits.
|
|
|
|
def disable_rate_limits!
|
|
|
|
@rate_limits_disabled = true
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
module ClassMethods
|
|
|
|
def rate_limit(limiter_method = nil)
|
|
|
|
limiter_method = limiter_method || :default_rate_limiter
|
|
|
|
|
2015-04-21 13:16:05 -04:00
|
|
|
self.after_create do |*args|
|
|
|
|
next if @rate_limits_disabled
|
|
|
|
|
2019-05-06 22:22:37 -04:00
|
|
|
if rate_limiter = public_send(limiter_method)
|
2013-12-13 01:04:45 -05:00
|
|
|
rate_limiter.performed!
|
|
|
|
@performed ||= {}
|
|
|
|
@performed[limiter_method] = true
|
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
self.after_destroy do
|
2015-04-21 13:16:05 -04:00
|
|
|
next if @rate_limits_disabled
|
2019-05-06 22:22:37 -04:00
|
|
|
if rate_limiter = public_send(limiter_method)
|
2013-12-13 01:04:45 -05:00
|
|
|
rate_limiter.rollback!
|
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
self.after_rollback do
|
2015-04-21 13:16:05 -04:00
|
|
|
next if @rate_limits_disabled
|
2019-05-06 22:22:37 -04:00
|
|
|
if rate_limiter = public_send(limiter_method)
|
2013-12-13 01:04:45 -05:00
|
|
|
if @performed.present? && @performed[limiter_method]
|
|
|
|
rate_limiter.rollback!
|
|
|
|
@performed[limiter_method] = false
|
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2013-02-25 11:42:20 -05:00
|
|
|
end
|