diff --git a/app/models/tipline_message.rb b/app/models/tipline_message.rb index d648d8a3ca..cf0cbcf6ae 100644 --- a/app/models/tipline_message.rb +++ b/app/models/tipline_message.rb @@ -6,6 +6,8 @@ class TiplineMessage < ApplicationRecord validates_presence_of :team, :uid, :platform, :language, :direction, :sent_at, :payload, :state validates_inclusion_of :state, in: ['sent', 'received', 'delivered'] + after_commit :verify_user_rate_limit, on: :create + def save_ignoring_duplicate! begin self.save! @@ -14,6 +16,16 @@ def save_ignoring_duplicate! end end + private + + def verify_user_rate_limit + rate_limit = CheckConfig.get('tipline_user_max_messages_per_day', 1500, :integer) + # Block tipline user when they have sent more than X messages in 24 hours + if self.state == 'received' && TiplineMessage.where(uid: self.uid, created_at: Time.now.ago(1.day)..Time.now, state: 'received').count > rate_limit + Bot::Smooch.block_user(self.uid) + end + end + class << self def from_smooch_payload(msg, payload, event = nil, language = nil) msg = msg.with_indifferent_access diff --git a/config/config.yml.example b/config/config.yml.example index 63a205f99e..e9f89e4976 100644 --- a/config/config.yml.example +++ b/config/config.yml.example @@ -258,6 +258,13 @@ development: &default otel_traces_sampler: otel_custom_sampling_rate: + # Rate limit for tipline submissions, tipline users are blocked after reaching this limit + # + # OPTIONAL + # When not set, a default number will be used. + # + tipline_user_max_messages_per_day: 1500 + test: <<: *default checkdesk_base_url_private: http://api:3000 diff --git a/test/models/tipline_message_test.rb b/test/models/tipline_message_test.rb index 943f91e53e..5cf57d870f 100644 --- a/test/models/tipline_message_test.rb +++ b/test/models/tipline_message_test.rb @@ -198,4 +198,26 @@ def setup end end end + + test "should block user when rate limit is reached" do + uid = random_string + assert !Bot::Smooch.user_blocked?(uid) + stub_configs({ 'tipline_user_max_messages_per_day' => 2 }) do + # User sent a message + create_tipline_message uid: uid, state: 'received' + assert !Bot::Smooch.user_blocked?(uid) + # User sent a message + create_tipline_message uid: uid, state: 'received' + assert !Bot::Smooch.user_blocked?(uid) + # Another user sent a message + create_tipline_message state: 'received' + assert !Bot::Smooch.user_blocked?(uid) + # User received a message + create_tipline_message uid: uid, state: 'delivered' + assert !Bot::Smooch.user_blocked?(uid) + # User sent a message and is now over rate limit, so should be blocked + create_tipline_message uid: uid, state: 'received' + assert Bot::Smooch.user_blocked?(uid) + end + end end