开发者

Add a subdomain condition to password reset query in Devise with Rails3?

开发者 https://www.devze.com 2023-03-03 06:38 出处:网络
I\'ve setup Devise (on Rails 3) to use Basecamp-style subdomain authentication. Under this model, a user could be registered twice under different subdomains with the same email address.

I've setup Devise (on Rails 3) to use Basecamp-style subdomain authentication. Under this model, a user could be registered twice under different subdomains with the same email address.

For example:

class User < ActiveRecord::Base
  belongs_to :account
end

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

User 1 registered on company1.myapp.com with email address bob@acme.com

User 2 registered on company2.myapp.com with email address bob@acme.com

(Both user account are controlled by the same human, but belong to different subdomains.)

Logging in works fine, but the standard Password Reset only looks up by email address, so you can only ever reset the password for User 1. What I'd like to do is take into account the request subdomain, so a password reset from company2.myapp.com/password/new would reset the password for User 2.

The Devise looks up the user using a find_first method, which I don't think accepts joins, so I can't include a :account => {:subodmain => 'comapny2'} condition.

I can reimplement send_reset_password_instructions to manually look up the user record, but it feels hacky and I'll need to do it for send_confirmation_instructions, too.

Is there a be开发者_开发技巧tter way?


It looks like this may be configurable with devise_for in the routes file.

From my reading of the source (and I haven't actually tried this), you can add a reset_password_keys option. These should include the subdomain. This is passed to find_or_initialize_with_errors from send_reset_password_instructions in lib/devise/models/recoverable.rb. In find_or_initialize_with_errors it's only these keys which are used to find the resource.

You'll probably also want to override Devise::PasswordsController#new template to include the user's subdomain when they submit the reset password request.

UPDATE: to address the fact that the subdomain is stored on Account and User belongs_to :account you can probably use Rails' delegate method.


We experienced this same issue. Mike Mazur's answer worked, but for one difference: We put :reset_password_keys => [:email, :subdomain] in the call to the devise method in our Users model.


I recently implement this behaviour in a Rails 4 App.

…/config/initializers/devise.rb

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

…/app/views/devise/passwords/new.html.erb

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

…/app/controllers/users/passwords_controller.rb

class Users::PasswordsController < Devise::PasswordsController

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

  private :resource_params
end
0

精彩评论

暂无评论...
验证码 换一张
取 消