从头开始进行Rails身份验证,跳过当前密码验证

时间:2015-05-20 14:59:48

标签: ruby-on-rails ruby-on-rails-4 model-validation rails-authorization

我从头开始有一个身份验证系统,当用户点击“编辑个人资料'无论他想编辑哪个字段,都必须输入当前密码。

def update
  if params[:user][:password].present?
    authenticated = @user.authenticate(params[:user][:current_password])
    if authenticated && @user.update(user_params)
      redirect_to root_url
      flash[:notice] = "Your profile was successfully updated!"
    else
      @user.errors.add(:current_password, 'is invalid') unless authenticated
      render :edit
    end
  elsif @user.update(user_params)
    redirect_to root_url
    flash[:notice] = "Your profile was successfully updated!"
  else
    render :edit
  end
end

如何仅在用户想要更改密码的情况下调用身份验证或使用某些上下文模型验证?

2 个答案:

答案 0 :(得分:1)

我不建议将此逻辑混合到模型中,因为随着应用程序的增长,最终会出现难以遵循的复杂性。

尝试查看表单对象:

我实现了这样的事情:

class UserUpdateForm
  include ActiveModel::Model

  # Attributes
  attr_accessor :user, :new_password, :new_password_confirmation

  # Validations
  validates :current_password, if: :new_password
  validate :authenticate, if: :current_password
  validates :new_password, confirmation: true, allow_blank: true

  def initialize(user)
    self.user = user
  end

  def submit(params)
    self.new_password = params[:new_password]
    self.new_password_confirmation = params[:new_password_confirmation]

    if self.valid?
      # Set other attributes as needed, then set new password below.
      self.user.password = self.new_password if self.new_password.present?
      self.user.save
    else
      false
    end
  end

private

  def authenticate
    unless self.authenticate(self.current_password)
      self.errors.add(:current_password, 'is invalid')
    end
  end
end

然后您可以从控制器中调用它,如下所示:

def update
  @user_update_form = UserUpdateForm.new(@user)

  if @user_update_form.submit(params)
    flash[:notice] = "Your profile was successfully updated!"
    redirect_to root_url
  else
    render :edit
  end
end

请参阅上面的链接,了解如何处理视图等。这只是为了让你开始。

答案 1 :(得分:0)

您可以在此操作语句中创建嵌套的if-else,以检查new_password是否存在new_password_confirmationparams[:user](或者调用新密码和确认字段){{1}对象。如果它们存在 - 您可以重定向到某个页面王,并要求输入现有密码。

另一种方法是使用ajax以异步方式显示具有相同请求的对话框(例如,处理该问题的respond_with自调用javascript函数)。然后在控制器的其他操作中处理对话框中的提交按钮。

更新(考虑使用验证器):

考虑到验证,您可以编写自己的validator(用于密码)和条件,以检查新密码字段何时附带来自客户端的一些数据。

我认为它看起来像这样:

validate :password_update?

def password_update?
    if new_password.present?
        if current_password !== self.password
          errors.add(:current_password, "must be supplied!")
        else
            # update data and password
        end
    else
        # do your regular update
    end
end