В моем приложении пользователи могут редактировать информацию своего профиля. В форме редактирования профиля пользователь может вносить изменения во все поля (имя, должность и т. д.). В этой же форме есть три поля: current_password
, password
и password_confirmation
. Я использую функцию has_secure_password
bcrypt
для аутентификации по паролю. Я вообще не использую Devise.
Я хочу, чтобы пользователи могли изменить свой пароль только в том случае, если они предоставили правильный текущий пароль. У меня это работало раньше со следующим кодом в методе update
моего контроллера Users:
# Check if the user tried changing his/her password and CANNOT be authenticated with the entered current password
if !the_params[:password].blank? && [email protected](the_params[:current_password])
# Add an error that states the user's current password is incorrect
@user.errors.add(:base, "Current password is incorrect.")
else
# Try to update the user
if @user.update_attributes(the_params)
# Notify the user that his/her profile was updated
flash.now[:success] = "Your changes have been saved"
end
end
Однако проблема с этим подходом заключается в том, что он отбрасывает все изменения в пользовательской модели, если неверным является только текущий пароль. Я хочу сохранить все изменения в модели пользователя, но НЕ изменить пароль, если текущий пароль неверен. Я попытался разделить операторы IF следующим образом:
# Check if the user tried changing his/her password and CANNOT be authenticated with the entered current password
if !the_params[:password].blank? && [email protected](the_params[:current_password])
# Add an error that states the user's current password is incorrect
@user.errors.add(:base, "Current password is incorrect.")
end
# Try to update the user
if @user.update_attributes(the_params)
# Notify the user that his/her profile was updated
flash.now[:success] = "Your changes have been saved"
end
Это не работает, потому что пользователь может изменить свой пароль, даже если текущий пароль неверен. При пошаговом вводе кода, хотя "Текущий пароль неверный". к @user
добавляется ошибка, после прогона метода update_attributes
вроде игнорирует это сообщение об ошибке.
Кстати, поле current_password
является виртуальным атрибутом в моей модели User:
attr_accessor :current_password
Я застрял, пытаясь понять это уже пару часов, так что мне действительно нужна помощь.
Спасибо!
Решение
Благодаря papirtiger у меня все получилось. Я немного изменил код из его ответа. Ниже мой код. Обратите внимание, что любой фрагмент кода будет работать нормально.
В модели пользователя (user.rb)
class User < ActiveRecord::Base
has_secure_password
attr_accessor :current_password
# Validate current password when the user is updated
validate :current_password_is_correct, on: :update
# Check if the inputted current password is correct when the user tries to update his/her password
def current_password_is_correct
# Check if the user tried changing his/her password
if !password.blank?
# Get a reference to the user since the "authenticate" method always returns false when calling on itself (for some reason)
user = User.find_by_id(id)
# Check if the user CANNOT be authenticated with the entered current password
if (user.authenticate(current_password) == false)
# Add an error stating that the current password is incorrect
errors.add(:current_password, "is incorrect.")
end
end
end
end
И код в моем контроллере Users теперь просто:
# Try to update the user
if @user.update_attributes(the_params)
# Notify the user that his/her profile was updated
flash.now[:success] = "Your changes have been saved"
end