仅在生产环境中禁用 Devise 注册

70
我正在推出一个beta网站,只向一组特定的用户开放。我想仅在生产环境中短暂禁用注册功能(即,我不想完全删除注册功能)。我知道我可以简单地隐藏“注册”链接,但我怀疑比我聪明的黑客仍然可以使用RESTful路由来完成注册。有什么最好的方法可以禁用注册,以便我的测试/开发环境仍然正常工作,但影响到生产环境?谢谢您提供任何建议。
我尝试过将命名范围指向“sign_up”转到“sign_in”,但没有成功。以下是我的尝试方式:
devise_scope :user do
    get "users/sign_in", :to => "devise/sessions#new", :as => :sign_in
    get "users/sign_up", :to => "devise/sessions#new", :as => :sign_up
end

理想情况下,我们会将用户发送到一个名为"pages#registration_disabled"的页面或类似的页面。我只是想得到一些可以玩耍的东西。

编辑: 按照要求,我已经更改了模型,然后在/spec/user_spec.rb中添加了以下内容。

describe "validations" do
    it "should fail registration if in production mode" do
      ENV['RAILS_ENV'] = "production"
      @user = Factory(:user).should_not be_valid
    end
end

它传递的是"true"而不是false。有没有一种方法来模拟生产环境?我只是随便想了一个。

谢谢!


我刚刚得知RAILS_ENV已被弃用,现在最好使用Rails.env。我的策略是这样的:如果Rails.env.production?设置一些常量为true,然后在测试中,只需测试该常量即可。 - Fareesh Vijayarangam
能否在测试模式下运行RSPEC,但让它假装是生产环境?比如设置Rails.env? - panzhuli
你可以在模型中添加 if Rails.env.production? or Rails.env.test? 来解决这个问题。 - Fareesh Vijayarangam
好的。我希望在部署之前能够进行测试... 我还是比较新手的 :) - panzhuli
是的,测试优先永远是正确的方式。 - Fareesh Vijayarangam
1
值得注意的是,如果删除:registrable,则会破坏创建和编辑注册的命名路由。这可能超出了预期的效果。 - Chris Nicola
4个回答

103

编辑 user 模型并删除 :registerable,我认为这样就可以得到你想要的结果。

编辑:

我认为这样可以解决问题:

if Rails.env.production?
  devise :database_authenticatable, :recoverable, :rememberable, :trackable, :validatable
else
  devise :database_authenticatable, :recoverable, :rememberable, :trackable, :validatable, :registerable 
end

那会移除所有环境的,对吧?有没有一种在模型级别指定环境的方法? - panzhuli
7
本不需要这个功能,但发现在模型中可以使用“Rails.env”。太棒了 :) 感谢。 - vvohra87
8
根据Chris Nicola在https://dev59.com/4W435IYBdhLWcg3whQY5#8291318中的回答,这将禁用编辑注册功能,这可能超出所期望的效果(在我的情况下肯定是这样)。 - Ted
如何在生产环境下禁用 /users/sign_in? - W.M.

88

看到其他人也遇到了和我一样的问题(请参阅我的评论),我来分享下我是如何解决的。我使用了murphyslaw的想法,但你还需要确保Devise使用你的新控制器进行注册路由,否则它对你来说没有任何作用。

以下是我覆盖的控制器:

class RegistrationsController < Devise::RegistrationsController
  def new
    flash[:info] = 'Registrations are not open yet, but please check back soon'
    redirect_to root_path
  end

  def create
    flash[:info] = 'Registrations are not open yet, but please check back soon'
    redirect_to root_path
  end
end

我已经添加了闪存消息,以便向无意中跳转到注册页面的人说明它为什么不起作用。

这是我的routes.rb中的内容:

  if Rails.env.production?
    devise_for :users, :controllers => { :registrations => "registrations" } 
  else
    devise_for :users
  end

controllers哈希指定我想要使用我重写的registrations控制器。

无论如何,我希望这能为某人节省一些时间。


3
不行,因为它继承自“Devise:RegistrationsController”,其中包含所有路由处理程序。我所做的就是覆盖了create路由。 - Chris Nicola
非常感谢你,Chris! :) - Katie H
好的回答!我自己也在使用这个。需要注意的是:自从Rails v2.2.1以后,你可以使用Rails.env.production?代替Rails.env == 'production' - Ben
是的,我现在通常这样做。更新了答案,因为看起来更好。 - Chris Nicola
1
谢谢Chris Nicola! - rld
显示剩余2条评论

11

仅仅移除:registerable是不能解决问题的。如果你在你的视图中有一些路由,你将会得到一个错误:

undefined local variable or method 'edit_user_registration_path'

要注意这个问题。


应用程序的重启可能也是必需的。 - Will

6

你可以重写 Devise::RegistrationsController 中的 create 方法,将其重定向到所需页面。该控制器应该类似于以下代码:

class User::RegistrationsController < Devise::RegistrationsController

  def create
    redirect_to your_page_path if Rails.env.production?
  end

end

1
这很重要,因为禁用:registerable会破坏编辑和创建注册路由。因此,如果您在已经创建用户的生产环境中进行测试,则禁用:registrable可能会导致一系列问题。 - Chris Nicola
没错。实际上我不得不在生产环境中取消我的注册路由。当我重建网站的一些核心功能时,我会尝试这个方法。谢谢! - panzhuli
在非生产环境中,请务必调用“super”。 - Sunny

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接