Files
danbooru/test/unit/user_test.rb
evazion dddd28a27b users: don't allow Hangul filler characters in names.
Don't allow the following characters in names:

* https://codepoints.net/U+115F (HANGUL CHOSEONG FILLER)
* https://codepoints.net/U+1160 (HANGUL JUNGSEONG FILLER)
* https://codepoints.net/U+3164 (HANGUL FILLER)
* https://codepoints.net/U+FFA0 (HALFWIDTH HANGUL FILLER)

These are space-like characters that were inadvertently allowed because they're not considered
whitespace by Unicode and because they're in the Hangul script (which we otherwise allow).
2022-12-05 23:58:31 -06:00

338 lines
11 KiB
Ruby

require 'test_helper'
class UserTest < ActiveSupport::TestCase
def assert_promoted_to(new_level, user, promoter)
user.promote_to!(new_level, promoter)
assert_equal(new_level, user.reload.level)
end
def assert_not_promoted_to(new_level, user, promoter)
assert_raise(User::PrivilegeError) do
user.promote_to!(new_level, promoter)
end
assert_not_equal(new_level, user.reload.level)
end
context "A user" do
setup do
@user = FactoryBot.create(:user)
CurrentUser.user = @user
end
teardown do
CurrentUser.user = nil
end
context "promoting a user" do
setup do
@builder = create(:builder_user)
@mod = create(:moderator_user)
@admin = create(:admin_user)
@owner = create(:owner_user)
end
should "allow moderators to promote users up to builder level" do
assert_promoted_to(User::Levels::GOLD, @user, @mod)
assert_promoted_to(User::Levels::PLATINUM, @user, @mod)
assert_promoted_to(User::Levels::BUILDER, @user, @mod)
assert_not_promoted_to(User::Levels::MODERATOR, @user, @mod)
assert_not_promoted_to(User::Levels::ADMIN, @user, @mod)
assert_not_promoted_to(User::Levels::OWNER, @user, @mod)
end
should "allow admins to promote users up to moderator level" do
assert_promoted_to(User::Levels::GOLD, @user, @admin)
assert_promoted_to(User::Levels::PLATINUM, @user, @admin)
assert_promoted_to(User::Levels::BUILDER, @user, @admin)
assert_promoted_to(User::Levels::MODERATOR, @user, @admin)
assert_not_promoted_to(User::Levels::ADMIN, @user, @admin)
assert_not_promoted_to(User::Levels::OWNER, @user, @admin)
end
should "allow the owner to promote users up to admin level" do
assert_promoted_to(User::Levels::GOLD, @user, @owner)
assert_promoted_to(User::Levels::PLATINUM, @user, @owner)
assert_promoted_to(User::Levels::BUILDER, @user, @owner)
assert_promoted_to(User::Levels::MODERATOR, @user, @owner)
assert_promoted_to(User::Levels::ADMIN, @user, @owner)
assert_not_promoted_to(User::Levels::OWNER, @user, @owner)
end
should "not allow non-moderators to promote other users" do
assert_not_promoted_to(User::Levels::GOLD, @user, @builder)
assert_not_promoted_to(User::Levels::PLATINUM, @user, @builder)
assert_not_promoted_to(User::Levels::BUILDER, @user, @builder)
assert_not_promoted_to(User::Levels::MODERATOR, @user, @builder)
assert_not_promoted_to(User::Levels::ADMIN, @user, @builder)
assert_not_promoted_to(User::Levels::OWNER, @user, @builder)
end
should "not allow users to promote or demote other users at their rank or above" do
assert_not_promoted_to(User::Levels::ADMIN, create(:moderator_user), @mod)
assert_not_promoted_to(User::Levels::BUILDER, create(:moderator_user), @mod)
assert_not_promoted_to(User::Levels::OWNER, create(:admin_user), @admin)
assert_not_promoted_to(User::Levels::MODERATOR, create(:admin_user), @admin)
assert_not_promoted_to(User::Levels::ADMIN, create(:owner_user), @owner)
end
should "not allow users to promote themselves" do
assert_not_promoted_to(User::Levels::ADMIN, @mod, @mod)
assert_not_promoted_to(User::Levels::OWNER, @admin, @admin)
end
should "not allow users to demote themselves" do
assert_not_promoted_to(User::Levels::MEMBER, @mod, @mod)
assert_not_promoted_to(User::Levels::MEMBER, @admin, @admin)
assert_not_promoted_to(User::Levels::MEMBER, @owner, @owner)
end
should "create a neutral feedback" do
@user.promote_to!(User::Levels::GOLD, @mod)
assert_equal("You have been promoted to a Gold level account from Member.", @user.feedback.last.body)
end
should "send an automated dmail to the user" do
bot = FactoryBot.create(:user)
User.stubs(:system).returns(bot)
assert_difference("Dmail.count", 1) do
@user.promote_to!(User::Levels::GOLD, @admin)
end
assert(@user.dmails.exists?(from: bot, to: @user, title: "Your account has been updated"))
refute(@user.dmails.exists?(from: bot, to: @user, title: "Your user record has been updated"))
end
end
should "authenticate password" do
assert_equal(@user, @user.authenticate_password("password"))
assert_equal(false, @user.authenticate_password("password2"))
end
should "normalize its level" do
user = FactoryBot.create(:user, :level => User::Levels::OWNER)
assert(user.is_owner?)
assert(user.is_admin?)
assert(user.is_moderator?)
assert(user.is_gold?)
user = FactoryBot.create(:user, :level => User::Levels::ADMIN)
assert(!user.is_owner?)
assert(user.is_moderator?)
assert(user.is_gold?)
user = FactoryBot.create(:user, :level => User::Levels::MODERATOR)
assert(!user.is_admin?)
assert(user.is_moderator?)
assert(user.is_gold?)
user = FactoryBot.create(:user, :level => User::Levels::GOLD)
assert(!user.is_admin?)
assert(!user.is_moderator?)
assert(user.is_gold?)
user = FactoryBot.create(:user)
assert(!user.is_admin?)
assert(!user.is_moderator?)
assert(!user.is_gold?)
end
context "name" do
should "not contain whitespace" do
# U+2007: https://en.wikipedia.org/wiki/Figure_space
user = build(:user, name: "foo\u2007bar")
user.save
assert_equal(["Name can't contain whitespace"], user.errors.full_messages)
end
should "not conflict with an existing name" do
create(:user, name: "bkub")
user = build(:user, name: "BKUB")
user.save
assert_equal(["Name already taken"], user.errors.full_messages)
end
should "be less than 25 characters long" do
user = build(:user, name: "a"*25)
user.save
assert_equal(["Name must be less than 25 characters long"], user.errors.full_messages)
end
should "not contain a colon" do
user = build(:user, name: "a:b")
user.save
assert_equal(["Name can't contain ':'"], user.errors.full_messages)
end
should "not begin with an underscore" do
user = build(:user, name: "_x")
user.save
assert_equal(["Name can't start with '_'"], user.errors.full_messages)
end
should "not end with an underscore" do
user = build(:user, name: "x_")
user.save
assert_equal(["Name can't end with '_'"], user.errors.full_messages)
end
should "not contain consecutive underscores" do
user = build(:user, name: "x__y")
user.save
assert_equal(["Name can't contain multiple underscores in a row"], user.errors.full_messages)
end
should "not allow non-ASCII characters" do
user = build(:user, name: "Pokémon")
user.save
assert_equal(["Name must contain only basic letters or numbers"], user.errors.full_messages)
end
should "not allow names ending in file extensions" do
user = build(:user, name: "evazion.json")
user.save
assert_equal(["Name can't end with a file extension"], user.errors.full_messages)
end
should "not be in the same format as a deleted user" do
user = build(:user, name: "user_1234")
user.save
assert_equal(["Name can't be the same as a deleted user"], user.errors.full_messages)
end
should "not allow blacklisted names" do
Danbooru.config.stubs(:user_name_blacklist).returns(["voldemort"])
user = build(:user, name: "voldemort42")
user.save
assert_equal(["Name is not allowed"], user.errors.full_messages)
end
should_not allow_value("any").for(:name)
should_not allow_value("none").for(:name)
should_not allow_value("new").for(:name)
should_not allow_value("admin").for(:name)
should_not allow_value("mod").for(:name)
should_not allow_value("moderator").for(:name)
should_not allow_value("foo_\u115F").for(:name)
should_not allow_value("foo_\u1160").for(:name)
should_not allow_value("foo_\u3164").for(:name)
should_not allow_value("foo_\uFFA0").for(:name)
end
context "searching for users by name" do
setup do
@miku = create(:user, name: "hatsune_miku")
end
should "be case-insensitive" do
assert_equal("hatsune_miku", User.normalize_name("Hatsune_Miku"))
assert_equal(@miku.id, User.find_by_name("Hatsune_Miku").id)
assert_equal(@miku.id, User.name_to_id("Hatsune_Miku"))
end
should "handle whitespace" do
assert_equal("hatsune_miku", User.normalize_name(" hatsune miku "))
assert_equal(@miku.id, User.find_by_name(" hatsune miku ").id)
assert_equal(@miku.id, User.name_to_id(" hatsune miku "))
end
should "return nil for nonexistent names" do
assert_nil(User.find_by_name("does_not_exist"))
assert_nil(User.name_to_id("does_not_exist"))
end
should "work for names containing asterisks or backslashes" do
@user1 = build(:user, name: "user*1")
@user2 = build(:user, name: "user*2")
@user3 = build(:user, name: "user\*3")
@user1.save(validate: false)
@user2.save(validate: false)
@user3.save(validate: false)
assert_equal(@user1.id, User.find_by_name("user*1").id)
assert_equal(@user2.id, User.find_by_name("user*2").id)
assert_equal(@user3.id, User.find_by_name("user\*3").id)
end
end
context "ip address" do
setup do
@user = FactoryBot.create(:user)
end
context "in the json representation" do
should "not appear" do
assert(@user.to_json !~ /addr/)
end
end
context "in the xml representation" do
should "not appear" do
assert(@user.to_xml !~ /addr/)
end
end
end
context "password" do
context "in the json representation" do
setup do
@user = FactoryBot.create(:user)
end
should "not appear" do
assert(@user.to_json !~ /password/)
end
end
context "in the xml representation" do
setup do
@user = FactoryBot.create(:user)
end
should "not appear" do
assert(@user.to_xml !~ /password/)
end
end
end
context "when searched by name" do
should "match wildcards" do
user1 = build(:user, name: "foo")
user2 = build(:user, name: "foo*bar")
user3 = build(:user, name: "bar\*baz")
user1.save(validate: false)
user2.save(validate: false)
user3.save(validate: false)
assert_search_equals([user2, user1], name: "foo*")
assert_search_equals(user2, name: "foo\*bar")
assert_search_equals(user3, name: "bar\\\*baz")
end
end
context "custom CSS" do
should "raise a validation error on invalid custom CSS" do
user = build(:user, custom_style: "}}}")
assert_equal(true, user.invalid?)
assert_match(/Custom CSS contains a syntax error/, user.errors[:base].first)
end
should "allow blank CSS" do
user = build(:user, custom_style: " ")
assert_equal(true, user.valid?)
end
end
end
end