Rails 设计禁用某些用户类型的密码恢复

问题描述 投票:0回答:5

在我的 Rails 项目中,我有不同类型的用户,其中之一具有

user_status :admin
,与其他用户不同,它具有编辑内容的完全权限。出于显而易见的原因,我想为这些类型的用户添加额外的安全性,特别是完全禁用密码恢复。

覆盖标准 Devise 密码恢复(

:recoverable
Devise 模块)方法的正确方法是什么,以便当用户尝试为管理员用户(
user_status == "admin"
)获取重置密码链接时,系统会返回“找不到标准电子邮件”消息?

这有点像未回答的问题:仅将设计密码恢复限制为某些用户

提前谢谢您。

ruby-on-rails ruby ruby-on-rails-3 authentication devise
5个回答
10
投票

我选择的对我有用的方法是通过将以下内容添加到

send_reset_password_instructions
来覆盖用户模型的
models/user.rb
方法:

def send_reset_password_instructions
  return false if self.user_status == 'admin'
  super
end

这使得 Devise 在电子邮件属于管理员帐户的情况下不会执行任何操作。


5
投票

对于任何未来的观众,这里有另一种方法。维塔利的例子确实对我有用,但我仍然收到“您的密码电子邮件已发送”。注意(我想要一个单独的警报来闪烁),所以我走了另一条路。

扩展 Devise::PasswordsController 对我来说是最简单的解决方案:

class Devise::Extends::PasswordsController < Devise::PasswordsController

  def create
    if some_condition?
      redirect_to :root
      flash[:alert] = 'You cannot reset your password, buddy.'
    else
      super
    end
  end

然后,在routes.rb中:

devise_for :users, controllers: { passwords: 'devise/extends/passwords' }

这会将您的应用程序定向到扩展控制器,然后如果不满足您的条件,请点击设备控制器(“超级”)。


2
投票

未经测试,但我认为您可以覆盖用户模型中的

reset_password!
,如下所示:

def reset_password!(new_password, new_password_confirmation)
  return false if user_status == 'admin'
  super
end

如果用户是管理员,这可以防止密码被重置。

我不知道这是否是最好的覆盖方法,还有更多设计可恢复的方法可以在您的用户模型中被覆盖,即

send_reset_password_instructions
。查看手册了解所有有趣的方法。


0
投票
凯勒·马丁的

上面的片段效果非常好!

我遇到的一些小问题如下:

  1. 如果你得到
    uninitialized constant Devise::Extends (NameError)
    (可能只是由于旧的 ruby 版本?)那么你可以只使用嵌套模块定义。
  2. 如果您需要允许未经身份验证的用户运行某些操作,则可以跳过过滤器。

以下是更新的片段。

module Devise
  module Extends
    class PasswordsController < Devise::PasswordsController

      skip_before_filter :authenticate_user!, :only => [ :edit ]

      def edit
        redirect_to "https://www.google.com/"
      end

    end
  end
end

0
投票

感谢您提出这个问题,以及其他答案中描述的两个解决方案:

  • 覆盖
    send_reset_password_instructions
    :它有效,电子邮件未发送, 但用户对此没有任何反馈。
  • 覆盖
    create
    中的操作
    PasswordsController
    ,以向用户分享反馈。

回到 2024 年和 Devise 4.8.1 版本,这两种解决方案仍然有效🎉

贡献不大,如果条件是基于

PasswordsController
中的用户,我们可以使用
resource_params
:

def create
  user = User.find_by_email(resource_params["email"])
  
  if user.can_reset_password?
    super
  else
    redirect_to(new_user_session_url, alert: "Oups, sorry daddy") and return
  end
end
© www.soinside.com 2019 - 2024. All rights reserved.