Fixed bug #1070: Existing resources get "save!"ed without changes. This triggers Rails model callbacks and executes unneeded actions.

This was caused by an error in the detection of changed associations. Unchanged associations were interpreted as a reset of the association. Therefore all associations without a new value won't get tracked anymore. This is the right behavior since they won't change the current value of the resource without a value.
This commit is contained in:
Thorsten Eckel 2017-05-12 17:24:15 +02:00
parent 199686dce1
commit 22f87c8826
3 changed files with 38 additions and 42 deletions

View file

@ -45,8 +45,13 @@ module Import
def changed_associations
changes = {}
tracked_associations.each do |association|
# skip if no new value will get assigned (no change is performed)
next if !@associations[:after].key?(association)
# skip if both values are equal
next if @associations[:before][association] == @associations[:after][association]
# skip if both values are blank
next if @associations[:before][association].blank? && @associations[:after][association].blank?
# store changes
changes[association] = [@associations[:before][association], @associations[:after][association]]
end
changes
@ -127,17 +132,20 @@ module Import
def associations_state(source)
state = {}
tracked_associations.each do |association|
state[association] = association_value(source, association)
end
state
end
# we have to support instances and (resource) hashes
# here since in case of an update we only have the
# hash as a source but on create we have an instance
def association_value(source, association)
return source[association] if source.is_a?(Hash)
source.send(association)
if source.is_a?(Hash)
# ignore if there is no key for the association
# of the Hash (update)
# otherwise wrong changes may get detected
next if !source.key?(association)
state[association] = source[association]
else
state[association] = source.send(association)
end
end
state
end
def tracked_associations

View file

@ -100,19 +100,6 @@ module Import
user_found = super
end
# in case an User was found and we had no roles
# to set/update we have to note the currently locally
# assigned roles so that our action check won't
# falsly detect changes to the User (from nil to current)
if user_found && @update_role_ids.blank?
resource[:role_ids] = @resource.role_ids
# we have to re-store/overwrite the stored
# associations since we've added the current
# state of the roles just yet
store_associations(:after, resource)
end
user_found
rescue => e
ldap_log(

View file

@ -220,24 +220,6 @@ RSpec.describe Import::Ldap::User do
}
end
it 'keeps local roles if signup roles are configured' do
ldap_config[:unassigned_users] = 'sigup_roles'
expect do
described_class.new(user_entry, ldap_config, user_roles, signup_role_ids)
end.not_to change {
User.last.role_ids
}
end
it "doesn't detect false changes if signup roles are configured" do
# make sure that the nothing has changed
User.find_by(login: uid).update_attribute(:email, 'example@example.com')
instance = described_class.new(user_entry, ldap_config, user_roles, signup_role_ids)
expect(instance.action).to eq(:unchanged)
end
it 'skips user if configured' do
ldap_config[:unassigned_users] = 'skip_sync'
@ -250,6 +232,27 @@ RSpec.describe Import::Ldap::User do
}
expect(instance.action).to eq(:skipped)
end
context 'signup roles configuration' do
it 'keeps local roles' do
ldap_config[:unassigned_users] = 'sigup_roles'
expect do
described_class.new(user_entry, ldap_config, user_roles, signup_role_ids)
end.not_to change {
User.last.role_ids
}
end
it "doesn't detect false changes" do
# make sure that the nothing has changed
User.find_by(login: uid).update_attribute(:email, 'example@example.com')
expect_any_instance_of(User).not_to receive(:save!)
instance = described_class.new(user_entry, ldap_config, user_roles, signup_role_ids)
expect(instance.action).to eq(:unchanged)
end
end
end
end
@ -265,7 +268,6 @@ RSpec.describe Import::Ldap::User do
User.count
}
expect(instance.action).to eq(:skipped)
end
it 'skips entries without attributes' do
@ -288,6 +290,5 @@ RSpec.describe Import::Ldap::User do
expect(HttpLog.last.status).to eq('success')
expect(HttpLog.last.url).to start_with('skipped')
end
end
end