diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index e5aa3b033c9..8c931afdba0 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -477,15 +477,6 @@ class TopicsController < ApplicationController end def invite - unless guardian.is_staff? - RateLimiter.new( - current_user, - "topic-invitations-per-day", - SiteSetting.max_topic_invitations_per_day, - 1.day.to_i - ).performed! - end - topic = Topic.find_by(id: params[:topic_id]) raise Discourse::InvalidParameters.new unless topic diff --git a/app/models/topic.rb b/app/models/topic.rb index af5c6c521c1..22bfcda8dec 100644 --- a/app/models/topic.rb +++ b/app/models/topic.rb @@ -802,6 +802,8 @@ SQL true elsif username_or_email =~ /^.+@.+$/ && Guardian.new(invited_by).can_invite_via_email?(self) + rate_limit_topic_invitation(invited_by) + if target_user Invite.extend_permissions(self, target_user, invited_by) @@ -815,7 +817,10 @@ SQL end true - elsif target_user && topic_allowed_users.create!(user_id: target_user.id) + elsif target_user && + rate_limit_topic_invitation(invited_by) && + topic_allowed_users.create!(user_id: target_user.id) + create_invite_notification!( target_user, Notification.types[:invited_to_topic], @@ -1296,6 +1301,17 @@ SQL }.to_json ) end + + def rate_limit_topic_invitation(invited_by) + RateLimiter.new( + invited_by, + "topic-invitations-per-day", + SiteSetting.max_topic_invitations_per_day, + 1.day.to_i + ).performed! + + true + end end # == Schema Information diff --git a/spec/models/topic_spec.rb b/spec/models/topic_spec.rb index d1a6a8b1aeb..1768d9afaaf 100644 --- a/spec/models/topic_spec.rb +++ b/spec/models/topic_spec.rb @@ -469,6 +469,35 @@ describe Topic do let(:topic) { Fabricate(:topic, user: user) } let(:another_user) { Fabricate(:user) } + context 'rate limits' do + before do + SiteSetting.max_topic_invitations_per_day = 2 + RateLimiter.enable + end + + after do + RateLimiter.clear_all! + RateLimiter.disable + end + + it "rate limits topic invitations" do + + start = Time.now.tomorrow.beginning_of_day + freeze_time(start) + + user = Fabricate(:user) + trust_level_2 = Fabricate(:user, trust_level: 2) + topic = Fabricate(:topic, user: trust_level_2) + + topic.invite(topic.user, user.username) + topic.invite(topic.user, "walter@white.com") + + expect { + topic.invite(topic.user, "user@example.com") + }.to raise_error(RateLimiter::LimitExceeded) + end + end + describe 'when username_or_email is not valid' do it 'should return the right value' do expect do