【问题标题】:Devise: allow users to reset password only设计:只允许用户重置密码
【发布时间】:2013-04-10 04:37:09
【问题描述】:

我有一个非常标准的 User 模型和 Devise。管理员由模型上的 :admin 布尔值控制,非管理员用户无法管理自己(即,只有管理员可以对用户进行更改)。

我希望允许用户在忘记密码时重置密码。他们将输入他们的电子邮件地址,然后通过电子邮件发送一个令牌,该令牌将授予他们更改它的权限。我已经开始了解决方案,但我真的不知道如何进行。

user.rb

class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
  attr_accessor :current_password
  attr_accessible :name, :password, :password_confirmation, :current_password, :email, :remember_me, :ftp, :colour1, :colour2, :logo, :logo2, :address, :url, :disclosure, :general_advice, :facebook, :twitter, :brand_id, :analytics
  attr_protected :admin
  validates_uniqueness_of :email, :ftp
  belongs_to :brand
  has_many :docs
  has_many :orders, :through => :docs
  has_attached_file :logo
  has_attached_file :logo2
end

class Ability
  include CanCan::Ability
  def initialize(user)
    user ||= User.new #guesting
    if user.admin?
      can :manage, :all
    else
      can :manage, :recoverable
    end
  end
end

方法如下:

def reset
  @idiot = User.where(:email => params[:email]).first
    unless @idiot.nil?
      Notifier.send_reset_notice(@idiot).deliver
      @idiot.send_reset_password_instructions
      redirect_to new_user_session_url
    else
      redirect_to new_user_session_url, :flash => { :error => "That email address matches no user." }
    end
end

用户收到设计电子邮件,但单击链接会将用户带到应用程序根目录,而不是密码重置表单。我不知道如何从这里开始。有什么想法吗?干杯!

更新

相关路线:

devise_for :users, :path => "d"
devise_scope :user do
  get '/sign_in' => 'devise/sessions#new'
  get '/sign_out' => 'devise/sessions#destroy'
end

【问题讨论】:

  • 这个解决方案一定要试试Devise wiki吗?
  • 是的,它不适合我的情况。感觉好像我的路线有问题之类的。我会用我的路线更新问题。

标签: ruby-on-rails ruby-on-rails-3 devise


【解决方案1】:

首先,为句柄 Devise::PasswordsController 创建控制器

class PasswordusersController < Devise::PasswordsController 
  prepend_before_filter :require_no_authentication
  append_before_filter :assert_reset_token_passed, :only => :edit

  def new
    super
  end

  def create
    self.resource = resource_class.send_reset_password_instructions(resource_params)

    if successfully_sent?(resource)
      redirect_to root_path, :notice => "Instruction has been send to your email"
    else
      respond_with(resource)
    end
  end

  def edit
    super
  end

  def update
    self.resource = resource_class.reset_password_by_token(resource_params)

    if resource.errors.empty?
      resource.unlock_access! if unlockable?(resource)
      flash_message = resource.active_for_authentication? ? :updated : :updated_not_active
      set_flash_message(:notice, flash_message) if is_navigational_format?
      sign_in(resource_name, resource)
      redirect_to login_path, :notice => "Password has been change"
    else
      respond_with resource
    end
  end

  protected

    def after_sending_reset_password_instructions_path_for(resource_name)
      root_path
    end

    def assert_reset_token_passed
      super
    end

    def unlockable?(resource)
      super
    end

end

然后,为设计运行生成视图

new.html.erbedit.html.erbviews/devise/passwords复制到views/passwordusers

routes.rb你可以配置如:

devise_scope :user do
get '/reset_password' => "passowrdusers#new", :as => :reset_password
get '/new_password' => "passwordusers#edit", :as => :new_password
end

编辑devise/mailer/reset_password_instructions.html.erb上的链接

<p><%= link_to 'Change My Password', new_password_path(@resource, :reset_password_token => @resource.reset_password_token) %></p>

最后,在查看表单登录时添加这个

<%= link_to "Forgot Password?", reset_password_url(resource_name) %>

更新

routes.rb 上,您可以进行如下配置:

devise_scope :user do
get '/reset_password' => "passowrdusers#new", :as => :reset_password
get '/new_password' => "passwordusers#edit", :as => :new_password
post '/send_email' => 'passwordusers#create', :as => :create_password
put '/change' =>  'passwordusers#update', :as => :update_password
end

views/passwordusers/new.html.erb

  <%= form_for("user", :url => create_password_path(resource_name), :html => { :method => :post }) do |f| %>

views/passwordusers/edit.html.erb

<%= form_for("user", :url => update_password_path(resource_name), :html => { :method => :put }) do |f| %>

【讨论】:

  • 感谢您的回复!这感觉很接近,但我遇到了一些错误。首先,生成的 URL 看起来像 domain.com/new_password.2?reset_password_token=... 这不起作用。当我将其更改为 /new_password/2?... 时,我收到 No route matches [GET] "/new_password/2" 错误。
  • new.html.erb 表单上,例如&lt;%= form_for("user", :url =&gt; passwordusers_create_path(resource_name), :html =&gt; { :method =&gt; :post }) do |f| %&gt; ?
  • 他们是这样的:&lt;%= form_for(resource, :as =&gt; resource_name, :url =&gt; password_path(resource_name), :html =&gt; { :method =&gt; :post }) do |f| %&gt;。我应该把它们改成你写的吗?
  • 我仍在生成此 URL:domain.com/new_password.2?reset_password_token=...,当我将其更改为 /new_password/2?... 时,我仍然收到 No route matches [GET] "/new_password/2" 错误。
  • 我已经尝试过我的应用程序,它的工作原理,如http://lvh:3000/new_password.2?reset_password_token=wDyeksCcdXxk8WufMDvd 的url 我已经一步一步地正确地给出了
猜你喜欢
  • 2023-04-04
  • 1970-01-01
  • 1970-01-01
  • 2012-05-22
  • 2013-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-24
相关资源
最近更新 更多