0

ユーザーモデルでhas_secure_passwordを使用しています。ユーザーがモデルの外部でパスワードを変更する方法を実装しましたが、物事をドライに保つために、必要な検証をコントローラーからモデルに移動しようとしています。

ユーザーモデルは次のようになります。

class User
  include Mongoid::Document
  include ActiveModel::SecurePassword

  has_secure_password

  field: :password_digest, type: String

  attr_accessible :password, :password_confirmation, :current_password
end

ユーザーは、以下を送信してパスワードを変更します。

user[current_password] - Currently stored password
user[password] - New password
user[password_confirmation] - New password confirmation

現在のユーザーのユーザーモデルでupdate_attributes(params [:user])を使用しています。私の問題は、update_attributesを呼び出すと、検証を使用する前にpassword_digestが更新されるため、次のコードが機能しないことです。

def password_validation_required?
  password_digest.blank? || !password.blank? || !password_confirmation.blank?
end

validate(on: :update, if: :password_validation_required?) do
  unless authenticate(current_password)
    add(:current_password, 'invalid password')
  end
end

authenticateは、user[password]から生成された新しいpassword_digestに基づいて認証されます。認証のために古いpassword_digest値にアクセスするための洗練された方法はありますか?私が持っていたアイデアの1つは、ユーザーを再クエリして、古いpassword_digest値に対して認証する別の認証方法にアクセスすることでした。問題は、それがクリーンな解決策ではないということです。

4

2 に答える 2

1

これは@Parazuceのものよりも少しきれいだと思います:

  validate :validates_current_password

  private

  def validates_current_password
    return if password_digest_was.nil? || !password_digest_changed?
    unless BCrypt::Password.new(password_digest_was) == current_password
      errors.add(:current_password, "is incorrect")
    end
  end
于 2013-01-28T08:37:11.933 に答える
0

password_digestフィールドにはActiveModel::Dirtyメソッドが関連付けられているため、次のようにすることにしました。

validate(on: :update, if: :password_validation_required?) do
  unless BCrypt::Password.new(password_digest_was) == current_password
    errors.add(:current_password, "is incorrect")
  end
end

password=これにより、他の機能が使用された場合に将来バグを引き起こす可能性のある追加のロジックでオーバーライドする必要がなくなりますpassword=

于 2012-09-30T18:44:00.907 に答える