Add a subdomain condition to password reset query in Devise with Rails3?
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
精彩评论