Commit dccf5f19 authored by Douwe Maan's avatar Douwe Maan

Merge branch 'tc-cache-trackable-attributes' into 'master'

Limit User's trackable attributes to update at most once/hour

Closes #22068

See merge request !11053
parents 2aa084a4 3531ea09
......@@ -40,6 +40,17 @@ class User < ActiveRecord::Base
devise :lockable, :recoverable, :rememberable, :trackable,
:validatable, :omniauthable, :confirmable, :registerable
# Override Devise::Models::Trackable#update_tracked_fields!
# to limit database writes to at most once every hour
def update_tracked_fields!(request)
update_tracked_fields(request)
lease = Gitlab::ExclusiveLease.new("user_update_tracked_fields:#{id}", timeout: 1.hour.to_i)
return unless lease.try_obtain
save(validate: false)
end
attr_accessor :force_random_password
# Virtual attribute for authenticating by either username or email
......
---
title: "Limit User's trackable attributes, like `current_sign_in_at`, to update at most once/hour"
merge_request: 11053
author:
......@@ -68,7 +68,7 @@ feature 'Groups > Members > Sorting', feature: true do
expect(page).to have_css('.member-sort-dropdown .dropdown-toggle-text', text: 'Name, descending')
end
scenario 'sorts by recent sign in' do
scenario 'sorts by recent sign in', :redis do
visit_members_list(sort: :recent_sign_in)
expect(first_member).to include(owner.name)
......@@ -76,7 +76,7 @@ feature 'Groups > Members > Sorting', feature: true do
expect(page).to have_css('.member-sort-dropdown .dropdown-toggle-text', text: 'Recent sign in')
end
scenario 'sorts by oldest sign in' do
scenario 'sorts by oldest sign in', :redis do
visit_members_list(sort: :oldest_sign_in)
expect(first_member).to include(developer.name)
......
......@@ -344,6 +344,35 @@ describe User, models: true do
end
end
describe '#update_tracked_fields!', :redis do
let(:request) { OpenStruct.new(remote_ip: "127.0.0.1") }
let(:user) { create(:user) }
it 'writes trackable attributes' do
expect do
user.update_tracked_fields!(request)
end.to change { user.reload.current_sign_in_at }
end
it 'does not write trackable attributes when called a second time within the hour' do
user.update_tracked_fields!(request)
expect do
user.update_tracked_fields!(request)
end.not_to change { user.reload.current_sign_in_at }
end
it 'writes trackable attributes for a different user' do
user2 = create(:user)
user.update_tracked_fields!(request)
expect do
user2.update_tracked_fields!(request)
end.to change { user2.reload.current_sign_in_at }
end
end
shared_context 'user keys' do
let(:user) { create(:user) }
let!(:key) { create(:key, user: user) }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment