设计更改密码不起作用(未知属性:current_password)

Mat*_*man 13 ruby-on-rails devise

我不太确定我做错了什么,但当用户尝试在我的应用上更改密码时,它会给出一个错误,即current_password是一个未知属性.

这是我的代码:

def configure_devise_permitted_parameters
  registration_params = [:email, :password, :password_confirmation, :first_name, :last_name]

  if params[:action] == 'update'
    devise_parameter_sanitizer.for(:user_update) {
      |u| u.permit(registration_params << :current_password)
    }
  elsif params[:action] == 'create'
    devise_parameter_sanitizer.for(:sign_up) {
      |u| u.permit(registration_params)
    }
  end
end

class RegistrationsController < Devise::RegistrationsController
  def update
    account_update_params = devise_parameter_sanitizer.sanitize(:user_update)

    if account_update_params[:password].blank?
      account_update_params.delete("password")
      account_update_params.delete("password_confirmation")
      account_update_params.delete("current_password")
    end

    @user = User.find(current_user.id)
    if @user.update_attributes(account_update_params)
      set_flash_message :notice, :updated
      sign_in @user, bypass: true
      redirect_to after_update_path_for(@user)
    else
      render "edit"
    end
  end
Run Code Online (Sandbox Code Playgroud)

我在这做错了什么?在正确保存新密码之前,我应该使用current_password检查它是否正确?

编辑:堆栈跟踪

activerecord (4.0.3) lib/active_record/attribute_assignment.rb:47:in `rescue in _assign_attribute'
activerecord (4.0.3) lib/active_record/attribute_assignment.rb:42:in `_assign_attribute'
activerecord (4.0.3) lib/active_record/attribute_assignment.rb:29:in `block in assign_attributes'
activerecord (4.0.3) lib/active_record/attribute_assignment.rb:23:in `each'
activerecord (4.0.3) lib/active_record/attribute_assignment.rb:23:in `assign_attributes'
Run Code Online (Sandbox Code Playgroud)

Tim*_*Tim 11

而不是调用@user.update_attributes(account_update_params)哪个因为current_password不是数据库中的字段(至少不在默认模式中),请尝试调用update_resource(@user, account_update_params)由您继承的Devise :: RegistrationsController提供的内容.这反过来调用source.update_with_password(params),它由devise的DatabaseAuthenticatable模块提供,并current_password在更新所有其他传递的参数之前检查.

但是,看起来标准的DeviseController :: RegistrationsController.update()会支持你想要的东西和更多(例如,如果更新需要确认电子邮件,则处理); 你有什么理由需要覆盖它吗?


mni*_*chi 8

今天,以下版本的Ruby,Rails和Devise遇到了相同的问题:

  • 红宝石-2.4.0
  • 轨道-5.1.4
  • devise-4.3.0

这是我的解决方案:

在中创建您的注册控制器 app/controllers/registrations_controller.rb

class RegistrationsController < Devise::RegistrationsController

  protected

  def update_resource(resource, params)
    # Require current password if user is trying to change password.
    return super if params["password"]&.present?

    # Allows user to update registration information without password.
    resource.update_without_password(params.except("current_password"))
  end
end
Run Code Online (Sandbox Code Playgroud)

告诉Devise您使用在中定义的注册控制器app/controllers/registrations_controller.rb

# config/routes.rb
devise_for :users, controllers: { registrations: "registrations" }
Run Code Online (Sandbox Code Playgroud)