Project

General

Profile

« Previous | Next » 

Revision 943bc1a2

Added by Ondřej Pražák almost 6 years ago

Fixes #23994 - Do not update templates out of scope

View differences:

app/models/concerns/taxonomy_collision_finder.rb
module TaxonomyCollisionFinder
extend ActiveSupport::Concern
module ClassMethods
def find_without_collision(attribute, value)
from_local = find_or_initialize_by attribute => value
from_global = unscoped.find_or_initialize_by attribute => value
from_local.errors.add(attribute, _("cannot be used, please choose another")) if from_local.new_record? && from_global.persisted?
from_local
end
end
end
app/models/provisioning_template.rb
friendly_id :name
include Parameterizable::ByIdName
include DirtyAssociations
include TaxonomyCollisionFinder
class << self
# we have to override the base_class because polymorphic associations does not detect it correctly, more details at
app/models/ptable.rb
include Parameterizable::ByIdName
include ValidateOsFamily
include DirtyAssociations
include TaxonomyCollisionFinder
class << self
# we have to override the base_class because polymorphic associations does not detect it correctly, more details at
app/models/template.rb
# based on +name it either finds existing template or builds a new one
# then it applies changes to it and return this object, note no changes were saved at this point
def self.import_without_save(name, text, options = {})
template = self.unscoped.find_or_initialize_by(:name => name)
template = self.find_without_collision :name, name
Foreman::Logging.logger('app').debug "#{template.new_record? ? 'building new' : 'updating existing'} template"
template.import_without_save(text, options)
end
......
# :default - default flag value (false by default)
def self.import!(name, text, options = {})
template = import_without_save(name, text, options)
return template unless template.valid?
if options[:force]
template.ignore_locking { template.save! }
else
......
template
end
# override in subclass to handle taxonomy scope, see TaxonomyCollisionFinder
def self.find_without_collision(attribute, name)
self.find_or_initialize_by :name => name
end
private
# This method can be overridden in Template children classes to import additional attributes
test/models/template_test.rb
describe '.import!' do
test 'by default it does not ignore locking' do
template = Minitest::Mock.new
template.expect(:valid?, true)
template.expect(:save!, true)
Template.expects(:import_without_save => template)
Template.import!('test', '')
......
test 'locking can be overriden by force option' do
template = Minitest::Mock.new
template.expect(:valid?, true)
template.expect(:ignore_locking, true)
Template.expects(:import_without_save => template)
Template.import!('test', '', { :force => true })
......
refute_includes @template.operatingsystem_ids, @os2.id
end
end
describe '::find_without_name_collision in subclasses' do
setup do
@org = FactoryBot.create(:organization, :name => 'TemplateOrg')
@empty = FactoryBot.create(:organization, :name => 'EmptyOrg')
@regular_template = FactoryBot.create(:provisioning_template, :name => 'regular template', :organizations => [@org])
@collision_template = FactoryBot.create(:provisioning_template, :name => 'collision template', :organizations => [@empty])
@common_template = FactoryBot.create(:provisioning_template, :name => 'common template', :organizations => [@empty, @org])
@before_org = Organization.current
Organization.current = @org
end
test 'should initialize a new template' do
template = ProvisioningTemplate.find_without_collision(:name, 'new template')
assert template.new_record?
assert template.errors.empty?
end
test 'should return existing template in current context' do
assert_equal @regular_template, ProvisioningTemplate.find_without_collision(:name, 'regular template')
end
test 'should return existing template if persent in multiple contexts' do
assert_equal @common_template, ProvisioningTemplate.find_without_collision(:name, 'common template')
end
test 'should return new instance with error when outside of current context' do
template = ProvisioningTemplate.find_without_collision(:name, 'collision template')
assert template.new_record?
refute template.errors.empty?
assert_equal "cannot be used, please choose another", template.errors.messages[:name].first
end
end
end
end

Also available in: Unified diff