diff --git a/app/models/user.rb b/app/models/user.rb index 8e73356212e..b5d4d63ab54 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -727,13 +727,26 @@ class User < ActiveRecord::Base end end - def update_last_seen!(now = Time.zone.now) + def last_seen_redis_key(now) now_date = now.to_date - # Only update last seen once every minute - redis_key = "user:#{id}:#{now_date}" - return unless Discourse.redis.setnx(redis_key, "1") + "user:#{id}:#{now_date}" + end + + def clear_last_seen_cache!(now = Time.zone.now) + Discourse.redis.del(last_seen_redis_key(now)) + end + + def update_last_seen!(now = Time.zone.now) + redis_key = last_seen_redis_key(now) + + if SiteSetting.active_user_rate_limit_secs > 0 + return if !Discourse.redis.set( + redis_key, "1", + nx: true, + ex: SiteSetting.active_user_rate_limit_secs + ) + end - Discourse.redis.expire(redis_key, SiteSetting.active_user_rate_limit_secs) update_previous_visit(now) # using update_column to avoid the AR transaction update_column(:last_seen_at, now) diff --git a/spec/components/auth/default_current_user_provider_spec.rb b/spec/components/auth/default_current_user_provider_spec.rb index bd1ce30fb04..a6aacf219bc 100644 --- a/spec/components/auth/default_current_user_provider_spec.rb +++ b/spec/components/auth/default_current_user_provider_spec.rb @@ -244,13 +244,16 @@ describe Auth::DefaultCurrentUserProvider do cookies["_t"][:value] end + before do + @orig = freeze_time + user.clear_last_seen_cache!(@orig) + end + after do - Discourse.redis.flushdb + user.clear_last_seen_cache!(@orig) end it "should not update last seen for suspended users" do - freeze_time - provider2 = provider("/", "HTTP_COOKIE" => "_t=#{unhashed_token}") u = provider2.current_user u.reload @@ -262,7 +265,8 @@ describe Auth::DefaultCurrentUserProvider do u.suspended_till = 1.year.from_now u.save! - Discourse.redis.del("user:#{user.id}:#{Time.now.to_date}") + u.clear_last_seen_cache! + provider2 = provider("/", "HTTP_COOKIE" => "_t=#{unhashed_token}") expect(provider2.current_user).to eq(nil)