diff --git a/app/models/user.rb b/app/models/user.rb index 3af5b661a..61d2e710d 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -7,13 +7,50 @@ class User < ActiveRecord::Base validates_format_of :name, :with => /\A[^\s;,]+\Z/, :on => :create, :message => "cannot have whitespace, commas, or semicolons" validates_uniqueness_of :name, :case_sensitive => false, :on => :create validates_uniqueness_of :email, :case_sensitive => false, :on => :create, :if => lambda {|rec| !rec.email.blank?} + validates_length_of :password, :minimum => 5, :if => lambda {|rec| rec.password} validates_confirmation_of :password before_save :encrypt_password after_save {|rec| Cache.put("user_name:#{rec.id}", rec.name)} - scope :named, lambda {|name| where(["lower(name) = ?", name])} + scope :named, lambda {|name| where(["lower(name) = ?", name])} + + def can_update?(object, foreign_key = :user_id) + is_moderator? || is_admin? || object.__send__(foreign_key) == id + end + + ### Name Methods ### + def self.find_name(user_id) + Cache.get("user_name:#{user_id}") do + select_value_sql("SELECT name FROM users WHERE id = ?", user_id) || Danbooru.config.default_guest_name + end + end + def pretty_name + name.tr("_", " ") + end + + ### Password Methods ### + def encrypt_password + self.password_hash = self.class.sha1(password) if password + end + + def reset_password + consonants = "bcdfghjklmnpqrstvqxyz" + vowels = "aeiou" + pass = "" + + 4.times do + pass << consonants[rand(21), 1] + pass << vowels[rand(5), 1] + end + + pass << rand(100).to_s + execute_sql("UPDATE users SET password_hash = ? WHERE id = ?", self.class.sha1(pass), id) + pass + end + + ### Authentication Methods ### def self.authenticate(name, pass) authenticate_hash(name, sha1(pass)) end @@ -25,23 +62,5 @@ class User < ActiveRecord::Base def self.sha1(pass) Digest::SHA1.hexdigest("#{Danbooru.config.password_salt}--#{pass}--") end - - def self.find_name(user_id) - Cache.get("user_name:#{user_id}") do - select_value_sql("SELECT name FROM users WHERE id = ?", user_id) || Danbooru.config.default_guest_name - end - end - - def can_update?(object, foreign_key = :user_id) - is_moderator? || is_admin? || object.__send__(foreign_key) == id - end - - def pretty_name - name.tr("_", " ") - end - - def encrypt_password - self.password_hash = self.class.sha1(password) if password - end end diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb index 5e8358875..e17cd1c02 100644 --- a/test/unit/user_test.rb +++ b/test/unit/user_test.rb @@ -6,12 +6,45 @@ class UserTest < ActiveSupport::TestCase MEMCACHE.flush_all end - should "be authenticate" do + should "authenticate" do @user = Factory.create(:user) assert(User.authenticate(@user.name, "password"), "Authentication should have succeeded") assert(!User.authenticate(@user.name, "password2"), "Authentication should not have succeeded") assert(User.authenticate_hash(@user.name, @user.password_hash), "Authentication should have succeeded") assert(!User.authenticate_hash(@user.name, "xxxx"), "Authentication should not have succeeded") end + + context "password" do + should "confirm its password" do + @user = Factory.create(:user) + @user.password = "zugzug5" + @user.password_confirmation = "zugzug5" + @user.save + @user.reload + assert(User.authenticate(@user.name, "zugzug5"), "Authentication should have succeeded") + end + + should "must match the confirmation" do + @user = Factory.create(:user) + @user.password = "zugzug6" + @user.password_confirmation = "zugzug5" + @user.save + assert_equal(["Password doesn't match confirmation"], @user.errors.full_messages) + end + + should "not be too short" do + @user = Factory.create(:user) + @user.password = "x5" + @user.password_confirmation = "x5" + @user.save + assert_equal(["Password is too short (minimum is 5 characters)"], @user.errors.full_messages) + end + + should "should be reset" do + @user = Factory.create(:user) + new_pass = @user.reset_password + assert(User.authenticate(@user.name, new_pass), "Authentication should have succeeded") + end + end end end