discourse/spec/lib/user_name_suggester_spec.rb
Ted Johansson 56df077931
FIX: Don't error out on empty reserved_usernames setting ()
We're seeing errors in logs due to some sites setting the reserved_usernames setting to nil. This is causing multiple use cases upstream of User#reserved_username? to error out.

This commit changes from using the raw #reserved_usernames to using the #reserved_usernames_map helper which exists on list-type site settings. It returns an empty array if the raw value is nil or empty string.
2024-10-21 14:38:37 +08:00

232 lines
8.1 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# frozen_string_literal: true
require "user_name_suggester"
RSpec.describe UserNameSuggester do
describe ".suggest" do
before do
SiteSetting.min_username_length = 3
SiteSetting.max_username_length = 15
SiteSetting.reserved_usernames = ""
end
let(:fallback_username) { I18n.t("fallback_username") + "1" }
it "keeps adding numbers to the username" do
Fabricate(:user, username: "sam")
Fabricate(:user, username: "sAm1")
Fabricate(:user, username: "sam2")
Fabricate(:user, username: "sam4")
expect(UserNameSuggester.suggest("saM")).to eq("saM3")
end
it "doesn't raise an error on nil username and suggest the fallback username" do
expect(UserNameSuggester.suggest(nil)).to eq(fallback_username)
end
it "doesn't raise an error on integer username" do
expect(UserNameSuggester.suggest(999)).to eq("999")
end
it "corrects weird characters" do
expect(UserNameSuggester.suggest("Darth%^Vader")).to eq("Darth_Vader")
end
it "adds 1 to an existing username" do
user = Fabricate(:user)
expect(UserNameSuggester.suggest(user.username)).to eq("#{user.username}1")
end
it "adds numbers if it's too short" do
expect(UserNameSuggester.suggest("a")).to eq("a11")
end
it "is able to guess a decent username from an email" do
expect(UserNameSuggester.suggest("bob@example.com")).to eq("bob")
end
it "has a special case for me and i emails" do
expect(UserNameSuggester.suggest("me@eviltrout.com")).to eq("eviltrout")
expect(UserNameSuggester.suggest("i@eviltrout.com")).to eq("eviltrout")
end
it "shortens very long suggestions" do
expect(UserNameSuggester.suggest("myreallylongnameisrobinwardesquire")).to eq(
"myreallylongnam",
)
end
it "makes room for the digit added if the username is too long" do
User.create(username: "myreallylongnam", email: "fake@discourse.org")
expect(UserNameSuggester.suggest("myreallylongnam")).to eq("myreallylongna1")
end
it "doesn't suggest reserved usernames" do
SiteSetting.reserved_usernames = "myadmin|steve|steve1"
expect(UserNameSuggester.suggest("myadmin@hissite.com")).to eq("myadmin1")
expect(UserNameSuggester.suggest("steve")).to eq("steve2")
end
it "doesn't suggest generic usernames" do
UserNameSuggester::GENERIC_NAMES.each do |name|
expect(UserNameSuggester.suggest("#{name}@apple.org")).to eq("apple")
end
end
it "replaces the leading character with _ if it is not alphanumeric" do
expect(UserNameSuggester.suggest("=myname")).to eq("_myname")
end
it "allows leading _" do
expect(UserNameSuggester.suggest("_myname")).to eq("_myname")
end
it "removes trailing characters if they are invalid" 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(fallback_username)
end
it "allows dots in the middle" do
expect(UserNameSuggester.suggest("my.name")).to eq("my.name")
end
it "replaces multiple dots in the middle with _" do
expect(UserNameSuggester.suggest("my..name")).to eq("my_name")
end
it "removes leading dots" do
expect(UserNameSuggester.suggest("..myname")).to eq("myname")
end
it "removes trailing dots" do
expect(UserNameSuggester.suggest("myname..")).to eq("myname")
end
it "handles usernames with a sequence of 2 or more special chars" do
expect(UserNameSuggester.suggest("Darth__Vader")).to eq("Darth_Vader")
expect(UserNameSuggester.suggest("Darth_-_Vader")).to eq("Darth_Vader")
end
it "should handle typical facebook usernames" do
expect(UserNameSuggester.suggest("roger.nelson.3344913")).to eq("roger.nelson.33")
end
it "removes underscore at the end of long usernames that get truncated" do
expect(UserNameSuggester.suggest("uuuuuuuuuuuuuu_u")).to_not end_with("_")
end
it "adds number if it's too short after removing trailing underscore" do
User.stubs(:username_length).returns(8..8)
expect(UserNameSuggester.suggest("uuuuuuu_u")).to eq("uuuuuuu1")
end
it "preserves current username" do
# if several users have username "bill" on the external site,
# they will have usernames bill, bill1, bill2 etc in Discourse:
Fabricate(:user, username: "bill")
Fabricate(:user, username: "bill1")
Fabricate(:user, username: "bill2")
Fabricate(:user, username: "bill3")
Fabricate(:user, username: "bill4")
# the number should be preserved, bill3 should remain bill3
suggestion = UserNameSuggester.suggest("bill", current_username: "bill3")
expect(suggestion).to eq "bill3"
end
it "skips input made entirely of disallowed characters" do
SiteSetting.unicode_usernames = false
input = %w[Πλάτων علي William]
suggestion = UserNameSuggester.suggest(*input)
expect(suggestion).to eq "William"
end
it "uses the first item if it isn't made entirely of disallowed characters" do
SiteSetting.unicode_usernames = false
input = %w[William علي Πλάτων]
suggestion = UserNameSuggester.suggest(*input)
expect(suggestion).to eq "William"
end
context "with Unicode usernames disabled" do
before { SiteSetting.unicode_usernames = false }
it "transliterates some characters" do
expect(UserNameSuggester.suggest("Jørn")).to eq("Jorn")
end
it "uses fallback username if there are Unicode characters only" do
expect(UserNameSuggester.suggest("طائر")).to eq(fallback_username)
expect(UserNameSuggester.suggest("πουλί")).to eq(fallback_username)
end
end
context "with Unicode usernames enabled" do
before { SiteSetting.unicode_usernames = true }
it "normalizes unicode usernames with Σ to lowercase" do
expect(UserNameSuggester.suggest('ΣΣ\'"ΣΣ')).to eq("σς_σς")
end
it "does not transliterate" do
expect(UserNameSuggester.suggest("Jørn")).to eq("Jørn")
end
it "does not replace Unicode characters" do
expect(UserNameSuggester.suggest("طائر")).to eq("طائر")
expect(UserNameSuggester.suggest("πουλί")).to eq("πουλί")
end
it "shortens usernames by counting grapheme clusters" do
SiteSetting.max_username_length = 10
expect(UserNameSuggester.suggest("बहुत-लंबा-उपयोगकर्ता-नाम")).to eq("बहुत-लंबा-उपयो")
end
it "adds numbers if it's too short" do
expect(UserNameSuggester.suggest("")).to eq("鳥11")
# grapheme cluster consists of 3 code points
expect(UserNameSuggester.suggest("য়া")).to eq("য়া11")
end
it "normalizes usernames" do
actual = "Löwe" # NFD, "Lo\u0308we"
expected = "Löwe" # NFC, "L\u00F6we"
expect(UserNameSuggester.suggest(actual)).to eq(expected)
end
it "does not suggest a username longer than max column size" do
SiteSetting.max_username_length = 40
expect(
UserNameSuggester.suggest(
"য়া-য়া-য়া-য়া-য়া-য়া-য়া-য়া-য়া-য়া-য়া-য়া-য়া-য়া-য়া-য়া-য়া-য়া-য়া",
),
).to eq("য়া-য়া-য়া-য়া-য়া-য়া-য়া-য়া-য়া-য়া-য়া-য়া-য়া-য়া-য়া")
end
it "uses allowlist" do
SiteSetting.allowed_unicode_username_characters = "[äöüßÄÖÜẞ]"
expect(UserNameSuggester.suggest("πουλί")).to eq(fallback_username)
expect(UserNameSuggester.suggest("a鳥b")).to eq("a_b")
expect(UserNameSuggester.suggest("Löwe")).to eq("Löwe")
SiteSetting.allowed_unicode_username_characters = "[য়া]"
expect(UserNameSuggester.suggest("aয়াb鳥c")).to eq("aয়াb_c")
end
end
end
end