]> git.openstreetmap.org Git - rails.git/commitdiff
Require display names to have a minimum unicode width of 3 columns
authorTom Hughes <tom@compton.nu>
Sun, 25 Feb 2024 13:16:40 +0000 (13:16 +0000)
committerTom Hughes <tom@compton.nu>
Sun, 25 Feb 2024 13:21:03 +0000 (13:21 +0000)
Fixes #4538

.rubocop_todo.yml
Gemfile
Gemfile.lock
app/models/user.rb
app/validators/width_validator.rb [new file with mode: 0644]
test/models/user_test.rb

index 6c917e218c69764ccf47423ef0ab6deeff7ec638..fdc7c35a5343242903305b93d5ec5ab9ff4b2ecf 100644 (file)
@@ -66,7 +66,7 @@ Metrics/BlockNesting:
 # Offense count: 26
 # Configuration parameters: CountComments, CountAsOne.
 Metrics/ClassLength:
-  Max: 313
+  Max: 314
 
 # Offense count: 59
 # Configuration parameters: AllowedMethods, AllowedPatterns.
diff --git a/Gemfile b/Gemfile
index 63d9c49e808bd71522c11c6af215fe5bb2db4789..832b96c9ac9df43df595a969888cacb29ed57715 100644 (file)
--- a/Gemfile
+++ b/Gemfile
@@ -136,6 +136,9 @@ gem "aws-sdk-s3"
 # Used to resize user images
 gem "image_processing"
 
+# Used to validate widths
+gem "unicode-display_width"
+
 # Gems useful for development
 group :development do
   gem "better_errors"
index 24beeb4d196946b4a82346dca07b969f06a3b632..234090689e738af6a641bbffbed76b5759bc72ca 100644 (file)
@@ -683,6 +683,7 @@ DEPENDENCIES
   sprockets-exporters_pack
   strong_migrations
   terser
+  unicode-display_width
   validates_email_format_of (>= 1.5.1)
   vendorer
   webmock
index 6fa0f330eaa244a38ee843ea8352e41213747512..125e5e97372c87c539540b682e805f5909d0611f 100644 (file)
@@ -98,7 +98,8 @@ class User < ApplicationRecord
                            :normalized_uniqueness => { :case_sensitive => false }
   validates :display_name, :if => proc { |u| u.display_name_changed? },
                            :characters => { :url_safe => true },
-                           :whitespace => { :leading => false, :trailing => false }
+                           :whitespace => { :leading => false, :trailing => false },
+                           :width => { :minimum => 3 }
   validate :display_name_cannot_be_user_id_with_other_id, :if => proc { |u| u.display_name_changed? }
   validates :email, :presence => true, :confirmation => true, :characters => true
   validates :email, :if => proc { |u| u.email_changed? },
diff --git a/app/validators/width_validator.rb b/app/validators/width_validator.rb
new file mode 100644 (file)
index 0000000..a3a4d41
--- /dev/null
@@ -0,0 +1,11 @@
+class WidthValidator < ActiveModel::Validations::LengthValidator
+  module WidthAsLength
+    def length
+      Unicode::DisplayWidth.of(to_s)
+    end
+  end
+
+  def validate_each(record, attribute, value)
+    super(record, attribute, value.extend(WidthAsLength))
+  end
+end
index 42949504f633925b8a6473cd203972ab944d9a71..92e7d419c33c50f7ec91d1899581793ffd72508a 100644 (file)
@@ -67,6 +67,18 @@ class UserTest < ActiveSupport::TestCase
     assert_not_predicate user, :valid?, "should not allow nil value"
   end
 
+  def test_display_name_width
+    user = build(:user)
+    user.display_name = "123"
+    assert_predicate user, :valid?, "should allow 3 column name name"
+    user.display_name = "12"
+    assert_not_predicate user, :valid?, "should not allow 2 column name"
+    user.display_name = "1\u{200B}2"
+    assert_not_predicate user, :valid?, "should not allow 2 column name"
+    user.display_name = "\u{200B}\u{200B}\u{200B}"
+    assert_not_predicate user, :valid?, "should not allow 0 column name"
+  end
+
   def test_display_name_valid
     # Due to sanitisation in the view some of these that you might not
     # expect are allowed