commit 2d5e52d9b6631541ad7ff510720836cfd82e0060
Author: Ondřej Pražák <xprazak2@users.noreply.github.com>
Date:   Thu Jul 5 17:32:07 2018 +0200

    Fixes #23896 - Update taxonomies when refreshing metadata

diff --git a/app/models/concerns/template_tax.rb b/app/models/concerns/template_tax.rb
new file mode 100644
index 000000000..cb450ad54
--- /dev/null
+++ b/app/models/concerns/template_tax.rb
@@ -0,0 +1,20 @@
+module TemplateTax
+  extend ActiveSupport::Concern
+
+  module ClassMethods
+    def taxonomy_exportable
+      {
+        :organizations => method(:assigned_organization_titles),
+        :locations => method(:assigned_location_titles)
+      }
+    end
+
+    def assigned_organization_titles(template, user = User.current)
+      template.organizations.select { |org| user.my_organizations.include?(org) }.map(&:title)
+    end
+
+    def assigned_location_titles(template, user = User.current)
+      template.locations.select { |loc| user.my_locations.include?(loc) }.map(&:title)
+    end
+  end
+end
diff --git a/app/models/provisioning_template.rb b/app/models/provisioning_template.rb
index d35dbda35..da92480ce 100644
--- a/app/models/provisioning_template.rb
+++ b/app/models/provisioning_template.rb
@@ -35,6 +35,7 @@ class ProvisioningTemplate < Template
   # these can't be shared in parent class, scoped search can't handle STI properly
   # tested with scoped_search 3.2.0
   include Taxonomix
+  include TemplateTax
   scoped_search :on => :name,    :complete_value => true, :default_order => true
   scoped_search :on => :locked,  :complete_value => {:true => true, :false => false}
   scoped_search :on => :snippet, :complete_value => {:true => true, :false => false}
@@ -47,8 +48,10 @@ class ProvisioningTemplate < Template
   scoped_search :relation => :hostgroups,       :on => :name, :rename => :hostgroup,       :complete_value => true
   scoped_search :relation => :template_kind,    :on => :name, :rename => :kind,            :complete_value => true
 
-  attr_exportable :kind => Proc.new { |template| template.template_kind.try(:name) },
-                  :oses => Proc.new { |template| template.operatingsystems.map(&:name).uniq }
+  attr_exportable({
+    :kind => Proc.new { |template| template.template_kind.try(:name) },
+    :oses => Proc.new { |template| template.operatingsystems.map(&:name).uniq }
+  }.merge(taxonomy_exportable))
 
   dirty_has_many_associations :template_combinations, :os_default_templates, :operatingsystems
 
diff --git a/app/models/ptable.rb b/app/models/ptable.rb
index 639b7ace2..4dea2cd42 100644
--- a/app/models/ptable.rb
+++ b/app/models/ptable.rb
@@ -34,6 +34,7 @@ class Ptable < Template
   # these can't be shared in parent class, scoped search can't handle STI properly
   # tested with scoped_search 3.2.0
   include Taxonomix
+  include TemplateTax
   scoped_search :on => :name,    :complete_value => true, :default_order => true
   scoped_search :on => :locked,  :complete_value => {:true => true, :false => false}
   scoped_search :on => :snippet, :complete_value => {:true => true, :false => false}
@@ -46,7 +47,7 @@ class Ptable < Template
 
   alias_attribute :layout, :template
 
-  attr_exportable :os_family
+  attr_exportable :os_family, taxonomy_exportable
 
   dirty_has_many_associations :operatingsystems
 
diff --git a/test/controllers/api/v2/ptables_controller_test.rb b/test/controllers/api/v2/ptables_controller_test.rb
index 6cedf11ef..d0e79e368 100644
--- a/test/controllers/api/v2/ptables_controller_test.rb
+++ b/test/controllers/api/v2/ptables_controller_test.rb
@@ -231,6 +231,7 @@ class Api::V2::PtablesControllerTest < ActionController::TestCase
     get :export, params: { :id => ptable.to_param }
     assert_response :success
     assert_equal 'text/plain', response.content_type
+    User.current = users(:admin)
     assert_equal ptable.to_erb, response.body
   end
 
diff --git a/test/controllers/ptables_controller_test.rb b/test/controllers/ptables_controller_test.rb
index 8877906a8..e3c17305d 100644
--- a/test/controllers/ptables_controller_test.rb
+++ b/test/controllers/ptables_controller_test.rb
@@ -60,6 +60,7 @@ class PtablesControllerTest < ActionController::TestCase
     get :export, params: { :id => @ptable.to_param }, session: set_session_user
     assert_response :success
     assert_equal 'text/plain', response.content_type
+    User.current = users(:admin)
     assert_equal @ptable.to_erb, response.body
   end
 
diff --git a/test/models/template_test.rb b/test/models/template_test.rb
index 0364fc46c..71f4baa91 100644
--- a/test/models/template_test.rb
+++ b/test/models/template_test.rb
@@ -340,6 +340,7 @@ EOS
         @loc1 = FactoryBot.create(:location)
         @loc2 = FactoryBot.create(:location)
         @loc3 = FactoryBot.create(:location)
+        @loc4 = FactoryBot.create(:location, :ancestry => @loc3.id.to_s)
       end
 
       test 'it ignores locations if none was set in metadata and sets current location' do
@@ -358,6 +359,12 @@ EOS
         refute_includes @template.location_ids, @loc3.id
       end
 
+      test 'it properly imports nested locations' do
+        @template.instance_variable_set '@importing_metadata', { 'locations' => [@loc4.title] }
+        @template.send(:import_locations, :associate => 'always')
+        assert_includes @template.location_ids, @loc4.id
+      end
+
       test 'unknown locations are ignored' do
         @template.instance_variable_set '@importing_metadata', { 'locations' => ['not_available'] }
         assert_nothing_raised { @template.send(:import_oses, :associate => 'always') }
@@ -446,5 +453,18 @@ EOS
         assert_equal "cannot be used, please choose another", template.errors.messages[:name].first
       end
     end
+
+    describe 'taxonomies in metadata' do
+      test 'should add taxonomies to metadata' do
+        org = FactoryBot.create(:organization, :name => 'TemplateOrg')
+        loc = FactoryBot.create(:location, :name => 'TemplateLoc')
+        provisioning_template = FactoryBot.create(:provisioning_template,
+                                                  :name => 'exported_template',
+                                                  :organizations => [org],
+                                                  :locations => [loc])
+        assert_equal org.title, provisioning_template.to_export["organizations"].first
+        assert_equal loc.title, provisioning_template.to_export["locations"].first
+      end
+    end
   end
 end
