FEATURE: Limit the number of active sessions for a user (#8411)
If a user has more than 60 active sessions, the oldest sessions will be terminated automatically. This protects performance when logging in and when loading the list of recently used devices.
This commit is contained in:
parent
1a6bbfd10b
commit
a227083c1c
|
@ -8,6 +8,8 @@ class UserAuthToken < ActiveRecord::Base
|
|||
# used when token did not arrive at client
|
||||
URGENT_ROTATE_TIME = 1.minute
|
||||
|
||||
MAX_SESSION_COUNT = 60
|
||||
|
||||
USER_ACTIONS = ['generate']
|
||||
|
||||
attr_accessor :unhashed_auth_token
|
||||
|
@ -220,6 +222,14 @@ class UserAuthToken < ActiveRecord::Base
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
def self.enforce_session_count_limit!(user_id)
|
||||
tokens_to_destroy = where(user_id: user_id).
|
||||
where('rotated_at > ?', SiteSetting.maximum_session_age.hours.ago).
|
||||
order("rotated_at DESC").offset(MAX_SESSION_COUNT)
|
||||
|
||||
tokens_to_destroy.delete_all # Returns the number of deleted rows
|
||||
end
|
||||
end
|
||||
|
||||
# == Schema Information
|
||||
|
|
|
@ -164,6 +164,9 @@ class Auth::DefaultCurrentUserProvider
|
|||
unstage_user(user)
|
||||
make_developer_admin(user)
|
||||
enable_bootstrap_mode(user)
|
||||
|
||||
UserAuthToken.enforce_session_count_limit!(user.id)
|
||||
|
||||
@env[CURRENT_USER_KEY] = user
|
||||
end
|
||||
|
||||
|
|
|
@ -586,6 +586,33 @@ describe Auth::DefaultCurrentUserProvider do
|
|||
expect(UserAuthToken.where(user_id: user.id).count).to eq(2)
|
||||
end
|
||||
|
||||
it "cleans up old sessions when a user logs in" do
|
||||
user = Fabricate(:user)
|
||||
|
||||
yesterday = 1.day.ago
|
||||
|
||||
UserAuthToken.insert_all((1..(UserAuthToken::MAX_SESSION_COUNT + 2)).to_a.map do |i|
|
||||
{
|
||||
user_id: user.id,
|
||||
created_at: yesterday + i.seconds,
|
||||
updated_at: yesterday + i.seconds,
|
||||
rotated_at: yesterday + i.seconds,
|
||||
prev_auth_token: "abc#{i}",
|
||||
auth_token: "abc#{i}"
|
||||
}
|
||||
end)
|
||||
|
||||
# Check the oldest 3 still exist
|
||||
expect(UserAuthToken.where(auth_token: (1..3).map { |i| "abc#{i}" }).count).to eq(3)
|
||||
|
||||
# On next login, gets fixed
|
||||
provider('/').log_on_user(user, {}, {})
|
||||
expect(UserAuthToken.where(user_id: user.id).count).to eq(UserAuthToken::MAX_SESSION_COUNT)
|
||||
|
||||
# Oldest sessions are 1, 2, 3. They should now be deleted
|
||||
expect(UserAuthToken.where(auth_token: (1..3).map { |i| "abc#{i}" }).count).to eq(0)
|
||||
end
|
||||
|
||||
it "sets secure, same site lax cookies" do
|
||||
SiteSetting.force_https = false
|
||||
SiteSetting.same_site_cookies = "Lax"
|
||||
|
|
Loading…
Reference in New Issue