Devise - неинициализированная константа User :: PasswordHistory - PullRequest
1 голос
/ 15 августа 2011

У меня есть приложение rails 3, над которым я работаю и которое внедрило devise.У меня это работает, и теперь я хочу расширить его, чтобы пользователь не мог использовать старый пароль более одного раза.Нашел этот функционал на github, который к моему удивлению был хорош. Запретить ранее пароли - Git Hub

Я думал, что это будет прямо вперед, но это явно не так.Мой код выглядит следующим образом:

create_passwrod_histories.rb

class CreatePasswordHistories < ActiveRecord::Migration
  def self.up
    create_table(:password_histories) do |t|
      t.integer :user_id
      t.string  :encrypted_password
      t.timestamps
    end
  end

  def self.down
    drop_table :password_histories
  end
end

User.rb

class User < ActiveRecord::Base
  include ActiveModel::Validations
  has_many :roles_users
  has_many :roles, :through => :roles_users
  has_many :projects
  has_many :password_histories
  after_save :store_digest


  # authorization include this in whichever model that will use ACL9
  acts_as_authorization_subject
   def has_role?(role_name, object=nil)
    !! if object.nil?
      self.roles.find_by_name(role_name.to_s) ||
      self.roles.member?(get_role(role_name, nil))
    else
      method = "is_#{role_name.to_s}?".to_sym
      object.respond_to?(method) && object.send(method, self)
    end
  end



  def login(user)
    post_via_redirect user_session_path, 'user[username]' => user.username, 'user[password]' => user.password
  end
  # Include default devise modules. Others available are:
  # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable #:registerable,
  devise :database_authenticatable, :recoverable, :rememberable, :trackable, :validatable, :timeoutable
  acts_as_authorization_subject  :association_name => :roles
  attr_accessor :login
  # Setup accessible (or protected) attributes for your model
  attr_accessible :id, :login, :username, :full_name, :email, :password, :password_confirmation, :remember_me, :role_ids

   email_regex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

  validates_presence_of :username, :full_name
  validates_format_of :username, :with => /^[-\w\._@]+$/i, :allow_blank => true, :message => "should only contain letters, numbers, or . - _ @"
  validates_length_of :username, :minimum => 1, :allow_blank => true
  validates_uniqueness_of :username, :email
  validates :email, :presence => true,
                    :format   => { :with => email_regex }
  validates :password, :unique_password => true

  def self.find_for_database_authentication(warden_conditions)
   conditions = warden_conditions.dup
   login = conditions.delete(:login)
   where(conditions).where(["lower(username) = :value OR lower(email) = :value", { :value => login.downcase }]).first
  end

  private

  def store_digest
    if encrypted_password_changed?
      PasswordHistory.create(:user => self, :encrypted_password => encrypted_password)
    end
  end


end

unique_password_validator.rb

require 'bcrypt'
class UniquePasswordValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    record.password_histories.each do |ph|
      bcrypt = ::BCrypt::Password.new(ph.encrypted_password)
      hashed_value = ::BCrypt::Engine.hash_secret([value, Devise.pepper].join, bcrypt.salt)
      record.errors[attribute] << "has been used previously." and return if hashed_value == ph.encrypted_password
    end
  end
end

Затем я запускаю свое приложение и пытаюсь использовать тот же пароль.Затем он выбрасывает следующую ошибку uninitialized constant User::PasswordHistory

1 Ответ

2 голосов
/ 15 августа 2011

Единственный способ, которым я могу видеть из вашего кода, почему это происходит, если у вас не было объекта модели PasswordHistory.Этот код от Github на самом деле явно не говорит вам делать это, но вам, безусловно, это нужно.Итак, возможно, вы создали и запустили миграцию, но забыли создать модель, например:

class PasswordHistory < ActiveRecord::Base
...
end
...