Files
danbooru/test/unit/user_test.rb
evazion c82e05d828 users: add stricter checks for user promotions.
New rules for user promotions:

* Moderators can no longer promote other users to moderator level. Only
  Admins can promote users to Mod level. Mods can only promote up to Builder level.
* Admins can no longer promote other users to Admin level. Only Owners
  can promote users to Admin. Admins can only promote up to Mod level.
* Admins can no longer demote themselves or other admins.

These rules are being changed to account for the new Owner user level.

Also change it so that when a user upgrades their account, the promotion
is done by DanbooruBot. This means that the inviter and the mod action
will show DanbooruBot as the promoter instead of the user themselves.
2020-12-13 21:21:08 -06:00

273 lines
9.3 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
CurrentUser.ip_addr = "127.0.0.1"
end
teardown do
CurrentUser.user = nil
CurrentUser.ip_addr = 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 = FactoryBot.build(:user, :name => "foo\u2007bar")
user.save
assert_equal(["Name cannot have whitespace or colons"], user.errors.full_messages)
end
should "not contain a colon" do
user = FactoryBot.build(:user, :name => "a:b")
user.save
assert_equal(["Name cannot have whitespace or colons"], user.errors.full_messages)
end
should "not begin with an underscore" do
user = FactoryBot.build(:user, :name => "_x")
user.save
assert_equal(["Name cannot begin or end with an underscore"], user.errors.full_messages)
end
should "not end with an underscore" do
user = FactoryBot.build(:user, :name => "x_")
user.save
assert_equal(["Name cannot begin or end with an underscore"], 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 "be updated" do
@user = FactoryBot.create(:user)
@user.update_attribute(:name, "danzig")
end
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 backlashes" do
@user1 = create(:user, name: "user*1")
@user2 = create(:user, name: "user*2")
@user3 = create(:user, name: "user\*3")
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 = FactoryBot.create(:user, :name => "foo")
user2 = FactoryBot.create(:user, :name => "foo*bar")
user3 = FactoryBot.create(:user, :name => "bar\*baz")
assert_equal([user2.id, user1.id], User.search(name: "foo*").map(&:id))
assert_equal([user2.id], User.search(name: "foo\*bar").map(&:id))
assert_equal([user3.id], User.search(name: "bar\\\*baz").map(&:id))
end
end
end
end