在Devise with Rails3中为密码重置查询添加子域条件?

时间:2011-05-05 12:33:13

标签: ruby-on-rails devise

我设置了Devise(在Rails 3上)以使用Basecamp样式的子域身份验证。在此模型下,用户可以使用相同的电子邮件地址在不同的子域下注册两次。

例如:

class User < ActiveRecord::Base
  belongs_to :account
end

class Account < ActiveRecord::Base
  # subdomain attribute stored here
end

用户1 在company1.myapp.com上注册,电子邮件地址为bob@acme.com
用户2 在company2.myapp.com上注册,电子邮件地址为bob@acme.com

(两个用户帐户都由同一个人控制,但属于不同的子域。)

登录工作正常,但标准密码重置仅按电子邮件地址查找,因此您只能重置用户1 的密码。我想要做的是考虑请求子域名,因此从company2.myapp.com/password/new重置密码会重置用户2 的密码。

Devise使用find_first方法查找用户,我认为不接受连接,因此我不能包含:account => {:subodmain => 'comapny2'}条件。

我可以重新实现send_reset_password_instructions手动查找用户记录,但感觉很烦,我也需要为send_confirmation_instructions执行此操作。

有更好的方法吗?

3 个答案:

答案 0 :(得分:1)

看起来这可以通过路径文件中的devise_for进行配置。

从我对源代码的阅读(我实际上没有尝试过这个),您可以添加reset_password_keys选项。这些应该包括子域。这会从lib/devise/models/recoverable.rbfind_or_initialize_with_errors传递给send_reset_password_instructions。在find_or_initialize_with_errorsonly these keys which are used to find the resource

您可能还希望覆盖Devise::PasswordsController#new模板,以便在用户提交重置密码请求时包含该用户的子域。

更新:要解决子域名存储在帐户和用户belongs_to :account上的问题,您可以使用Rails' delegate method

答案 1 :(得分:1)

我们遇到了同样的问题。 Mike Mazur的回答有效,但有一点不同: 我们将:reset_password_keys => [:email, :subdomain]放入对Users模型中devise方法的调用中。

答案 2 :(得分:1)

我最近在Rails 4 App中实现了这种行为。

... /配置/初始化/ devise.rb

(…)
# ==> Configuration for :recoverable
#
# Defines which key will be used when recovering the password for an account
config.reset_password_keys = [:email, :subdomain]
(…)

... /应用/视图/设计/口令/ new.html.erb

(…)
<%= f.input :subdomain, required: true %>
(…)

... /应用/控制器/用户/ passwords_controller.rb

class Users::PasswordsController < Devise::PasswordsController

  def resource_params
    params.require(:user).permit(:email, :subdomain, ...)
  end

  private :resource_params
end