FIX: do not allow tag with name 'none' (#9867)

FIX: do not allow tag with name ‘none’ (#9867)

https://meta.discourse.org/t/none-tag-is-uneditable/152003

diff --git a/app/models/tag.rb b/app/models/tag.rb
index 825b90d..6ff6afe 100644
--- a/app/models/tag.rb
+++ b/app/models/tag.rb
@@ -5,15 +5,16 @@ class Tag < ActiveRecord::Base
   include HasDestroyedWebHook
 
   RESERVED_TAGS = [
-    'c'
+    'c',
+    'none'
   ]
 
   validates :name,
     presence: true,
-    uniqueness: { case_sensitive: false },
-    exclusion: { in: RESERVED_TAGS }
+    uniqueness: { case_sensitive: false }
 
   validate :target_tag_validator, if: Proc.new { |t| t.new_record? || t.will_save_change_to_target_tag_id? }
+  validate :name_validator
 
   scope :where_name, ->(name) do
     name = Array(name).map(&:downcase)
@@ -181,6 +182,14 @@ class Tag < ActiveRecord::Base
       true
     end
   end
+
+  private
+
+  def name_validator
+    if name.present? && RESERVED_TAGS.include?(self.name.strip.downcase)
+      errors.add(:name, :invalid)
+    end
+  end
 end
 
 # == Schema Information
diff --git a/db/migrate/20200525072638_remove_none_tags.rb b/db/migrate/20200525072638_remove_none_tags.rb
new file mode 100644
index 0000000..ed50eea
--- /dev/null
+++ b/db/migrate/20200525072638_remove_none_tags.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class RemoveNoneTags < ActiveRecord::Migration[6.0]
+  def up
+    none_tag_id = DB.query_single("SELECT id FROM tags WHERE lower(name) = 'none'").first
+    if none_tag_id.present?
+      [:tag_users, :topic_tags, :category_tag_stats, :category_tags, :tag_group_memberships].each do |table_name|
+        execute "DELETE FROM #{table_name} WHERE tag_id = #{none_tag_id}"
+      end
+      execute "DELETE FROM tags WHERE id = #{none_tag_id} OR target_tag_id = #{none_tag_id}"
+    end
+  end
+
+  def down
+    raise ActiveRecord::IrreversibleMigration
+  end
+end
diff --git a/spec/models/tag_spec.rb b/spec/models/tag_spec.rb
index 441bb73..8bf0f7e 100644
--- a/spec/models/tag_spec.rb
+++ b/spec/models/tag_spec.rb
@@ -36,6 +36,9 @@ describe Tag do
       expect { Fabricate.build(:tag, name: "hElLo").save! }.to raise_error(ActiveRecord::RecordInvalid)
     end
 
+    it 'does not allow creation of tag with name in "RESERVED_TAGS"' do
+      expect { Fabricate.build(:tag, name: "None").save! }.to raise_error(ActiveRecord::RecordInvalid)
+    end
   end
 
   describe 'destroy' do

GitHub sha: 5462fe94

1 Like

This commit appears in #9867 which was approved by nlalonde. It was merged by techAPJ.

This commit has been mentioned on Discourse Meta. There might be relevant details there:

https://meta.discourse.org/t/none-tag-is-uneditable/152003/8