Browse Source

Fixes #2664 - ObjectManager::Attribute names collide with reserved application words ( e.g. `url`) and break functionalities

Denny Bresch 5 years ago
parent
commit
106bfd56da

+ 1 - 1
app/models/object_manager/attribute.rb

@@ -901,7 +901,7 @@ is certain attribute used by triggers, overviews or schedulers
     raise 'At least one letters is needed' if !name.match?(/[a-z]/)
 
     # do not allow model method names as attributes
-    reserved_words = %w[destroy true false integer select drop create alter index table varchar blob date datetime timestamp]
+    reserved_words = %w[destroy true false integer select drop create alter index table varchar blob date datetime timestamp url icon initials avatar permission validate subscribe unsubscribe translate search]
     raise "#{name} is a reserved word, please choose a different one" if name.match?(/^(#{reserved_words.join('|')})$/)
 
     # fixes issue #2236 - Naming an attribute "attribute" causes ActiveRecord failure

+ 29 - 0
db/migrate/20190724000001_rename_reserved_words.rb

@@ -0,0 +1,29 @@
+class RenameReservedWords < ActiveRecord::Migration[5.1]
+  def up
+    return if !Setting.find_by(name: 'system_init_done')
+
+    models = ObjectManager.list_objects.map(&:underscore).map { |object| object.tr('_', '/') }.map(&:classify).map(&:constantize)
+
+    reserved_words = %w[url icon initials avatar permission validate subscribe unsubscribe translate search]
+    models.each do |model|
+
+      reserved_words.each do |reserved_word|
+
+        next if ActiveRecord::Base.connection.columns(model.table_name).map(&:name).exclude?(reserved_word)
+
+        sanitized_name = "_#{reserved_word}"
+
+        ActiveRecord::Migration.rename_column(model.table_name.to_sym, reserved_word.to_sym, sanitized_name.to_sym)
+        model.reset_column_information
+
+        attribute = ObjectManager::Attribute.get(
+          object: model.to_app_model,
+          name:   reserved_word,
+        )
+        next if !attribute
+
+        attribute.update!(name: sanitized_name)
+      end
+    end
+  end
+end

+ 6 - 4
spec/models/object_manager/attribute_spec.rb

@@ -57,10 +57,12 @@ RSpec.describe ObjectManager::Attribute, type: :model do
       end.to raise_error 'attribute is a reserved word, please choose a different one'
     end
 
-    it 'rejects Zammad reserved word "table"' do
-      expect do
-        ObjectManager::Attribute.add attributes_for :object_manager_attribute_text, name: 'table'
-      end.to raise_error 'table is a reserved word, please choose a different one'
+    %w[destroy true false integer select drop create alter index table varchar blob date datetime timestamp url icon initials avatar permission validate subscribe unsubscribe translate search].each do |reserved_word|
+      it "rejects Zammad reserved word '#{reserved_word}'" do
+        expect do
+          ObjectManager::Attribute.add attributes_for :object_manager_attribute_text, name: reserved_word
+        end.to raise_error "#{reserved_word} is a reserved word, please choose a different one"
+      end
     end
 
     it 'rejects duplicate attribute name of conflicting types' do