FEATURE: make username suggester suggest `user1`, `user2` etc. for input that contains invalid characters only (#14179)

FEATURE: make username suggester suggest user1, user2 etc. for input that contains invalid characters only (#14179)

We were suggesting 111, 1111, 1112 before.

See the discussion on Meta – https://meta.discourse.org/t/curious-account-creation-behaviour/199970/14.

diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml
index b34aa9f..24dd820 100644
--- a/config/locales/server.en.yml
+++ b/config/locales/server.en.yml
@@ -5119,3 +5119,5 @@ en:
       other: "%{topic_title} (Part %{count})"
     post_raw: "Continuing the discussion from %{parent_url}.\n\nPrevious discussions:\n\n%{previous_topics}"
     small_action_post_raw: "Continue discussion at %{new_title}."
+
+  fallback_username: "user"
diff --git a/lib/user_name_suggester.rb b/lib/user_name_suggester.rb
index b367ffc..bf767d6 100644
--- a/lib/user_name_suggester.rb
+++ b/lib/user_name_suggester.rb
@@ -2,6 +2,7 @@
 
 module UserNameSuggester
   GENERIC_NAMES = ['i', 'me', 'info', 'support', 'admin', 'webmaster', 'hello', 'mail', 'office', 'contact', 'team']
+  LAST_RESORT_USERNAME = "user"
 
   def self.suggest(name_or_email, allowed_username = nil)
     return unless name_or_email.present?
@@ -102,7 +103,13 @@ module UserNameSuggester
   end
 
   def self.fix_username(name)
-    rightsize_username(sanitize_username(name))
+    fixed_username = sanitize_username(name)
+    if fixed_username.empty?
+      fixed_username << sanitize_username(I18n.t('fallback_username'))
+      fixed_username << LAST_RESORT_USERNAME if fixed_username.empty?
+    end
+
+    rightsize_username(fixed_username)
   end
 
   def self.sanitize_username(name)
diff --git a/spec/components/user_name_suggester_spec.rb b/spec/components/user_name_suggester_spec.rb
index c20c507..446fd76 100644
--- a/spec/components/user_name_suggester_spec.rb
+++ b/spec/components/user_name_suggester_spec.rb
@@ -8,6 +8,7 @@ describe UserNameSuggester do
     before do
       SiteSetting.min_username_length = 3
       SiteSetting.max_username_length = 15
+      SiteSetting.reserved_usernames = ''
     end
 
     it "keeps adding numbers to the username" do
@@ -82,6 +83,11 @@ describe UserNameSuggester do
       expect(UserNameSuggester.suggest("myname!^$=")).to eq('myname')
     end
 
+    it "suggest a fallback username if name contains only invalid characters" do
+      suggestion = UserNameSuggester.suggest("---")
+      expect(suggestion).to eq(I18n.t('fallback_username'))
+    end
+
     it "allows dots in the middle" do
       expect(UserNameSuggester.suggest("my.name")).to eq('my.name')
     end
@@ -119,9 +125,10 @@ describe UserNameSuggester do
         expect(UserNameSuggester.suggest('Jørn')).to eq('Jorn')
       end
 
-      it "replaces Unicode characters" do
-        expect(UserNameSuggester.suggest('طائر')).to eq('111')
-        expect(UserNameSuggester.suggest('πουλί')).to eq('111')
+      it "uses fallback username if there are Unicode characters only" do
+        fallback_username = I18n.t('fallback_username')
+        expect(UserNameSuggester.suggest('طائر')).to eq(fallback_username)
+        expect(UserNameSuggester.suggest('πουλί')).to eq(fallback_username)
       end
     end
 
@@ -178,7 +185,7 @@ describe UserNameSuggester do
       it "uses allowlist" do
         SiteSetting.allowed_unicode_username_characters = "[äöüßÄÖÜẞ]"
 
-        expect(UserNameSuggester.suggest('πουλί')).to eq('111')
+        expect(UserNameSuggester.suggest('πουλί')).to eq(I18n.t('fallback_username'))
         expect(UserNameSuggester.suggest('a鳥b')).to eq('a_b')
         expect(UserNameSuggester.suggest('Löwe')).to eq('Löwe')
 

GitHub sha: 149e869c22523b9840454bcf3d69f262b822ab2d

This commit appears in #14179 which was approved by davidtaylorhq and gschlager. It was merged by AndrewPrigorshnev.