2014-09-05 85 views
-3

我跟随Michael Hartl的教程达到了某一点,然后跟随Ryan Bates的Railcast添加重置密码(#274)。也许“试图遵循”更准确,因为尽管经过了许多小时的努力/搜索/修改错误,我仍无法获得重置密码的工作。向Rails应用程序添加电子邮件确认

不得不偏离Ryan的调用:@ user.update_attributes(params [:user])to:@ user.update_attributes(user_params),因为我正在获取ForbiddenAttributesError。

由于提交失败(即使提交的密码长度大于6),我还必须在用户类中注释掉#validates:password,长度:{minimum:6}。

该代码当前不会生成任何错误,并且redirect_to root_url::notice =>“密码已被重置!”作品。但是,密码不在数据库中更新。

任何洞察力非常感激地收到。

应用/模型/ user.rb

class User < ActiveRecord::Base 
    before_save { self.email = email.downcase } 
    validates :name, presence: true, length: { maximum: 50 } 
    VALID_EMAIL_REGEX = /\A[\w+\-.][email protected][a-z\d\-.]+\.[a-z]+\z/i 
    validates :email, presence: true, format:  { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false } 
    has_secure_password 
    #validates :password, length: { minimum: 6 } 

    before_create :create_remember_token 

    def send_password_reset 
    generate_token(:password_reset_token) 
    self.password_reset_sent_at = Time.zone.now 
    save! 
    UserMailer.password_reset(self).deliver 
    end 

    def User.new_remember_token 
    SecureRandom.urlsafe_base64 
    end 

    def User.digest(token) 
    Digest::SHA1.hexdigest(token.to_s) 
    end 

    private 
    def generate_token(column) 
     begin 
     self[column] = SecureRandom.urlsafe_base64(40) 
     end while User.exists?(column => self[column]) 
    end 

    def create_remember_token 
     self.remember_token = User.digest(User.new_remember_token) 
    end 

end 

应用程序/控制器/ users_controller.rb

class UsersController < ApplicationController 
    before_action :signed_in_user, only: [:index, :edit, :update] 
    before_action :correct_user, only: [:edit, :update] 

    def index 
    @users = User.paginate(page: params[:page]) 
    end 

    def show 
    @user = User.find(params[:id]) 
    end 

    def new 
    @user = User.new 
    end 

    def create 
    @user = User.new(user_params)  if @user.save 
     sign_in @user 
     flash[:success] = "Welcome!" 
     redirect_to @user 
    else 
     render 'new' 
    end 
    end 

    def edit 
    end 

    def update 
    if @user.update_attributes(user_params) 
     flash[:success] = "Profile updated" 
     redirect_to @user 
    else 
     render 'edit' 
    end 
    end 

    private 

    def user_params 
     params.require(:user).permit(:name, :email, :password, :password_confirmation, :password_reset_token) 
    end 

    def signed_in_user 
     unless signed_in? 
     store_location 
     redirect_to signin_url, notice: "Please sign in." 
     end 
    end 

    def correct_user 
     @user = User.find(params[:id]) 
     redirect_to(root_url) unless current_user?(@user) 
    end 

end 

应用程序/控制器/ password_resets_controller.rb

class PasswordResetsController < ApplicationController 
    def new 
    end 

    def create 
    user = User.find_by_email(params[:email]) 
    user.send_password_reset if user 
    redirect_to root_url, :notice => "Email sent with password reset instructions." 
    end 

    def edit 
    @user = User.find_by_password_reset_token!(params[:id]) 
    end 

    def update 
    @user = User.find_by_password_reset_token!(params[:id]) 
    if @user.password_reset_sent_at < 2.hours.ago 
     redirect_to new_password_reset_path, :alert => "Password reset has expired." 
    elsif @user.update_attributes(user_params) 
     redirect_to root_url, :notice => "Password has been reset!" 
    else 
     render :edit 
    end 
    end 

    private 
    def user_params 
     params.require(:user).permit(:id, :name, :email, :created_at, :updated_at, :password_digest, :remember_token, :admin, :auth_token, :password_reset_token, :password_reset_sent_at) 
    end 

end 

应用/视图/ password_resets/edit.html.erb

<%= form_for @user, :url => password_reset_path(params[:id]) do |f| %> 
    <% if @user.errors.any? %> 
    <div class="error_messages"> 
     <h2>Form is invalid</h2> 
     <ul> 
     <% for message in @user.errors.full_messages %> 
      <li><%= message %></li> 
     <% end %> 
     </ul> 
    </div> 
    <% end %> 
    <div class="field"> 
    <%= f.label :password %> 
    <%= f.password_field :password %> 
    </div> 
    <div class="field"> 
    <%= f.label :password_confirmation %> 
    <%= f.password_field :password_confirmation %> 
    </div> 
    <div class="actions"><%= f.submit "Update Password" %></div> 
<% end %> 

应用程序/视图/ password_resets/new.html.erb

<h1>PasswordReset#new</h1> 

<%= form_tag password_resets_path, :method => :post do %> 
    <div class="field"> 
    <%= label_tag :email %> 
    <%= text_field_tag :email, params[:email] %> 
    </div> 
    <div class="actions"><%= submit_tag "Reset Password" %></div> 
<% end %> 

没有为password_resets没有模型。

+0

你如何验证密码没有改变? – 2014-09-06 18:44:11

回答

0

app/views/password_resets/edit.html.erb,您的表单描述了:password:password_confirmation。但是,在您的PasswordResetsController中,您使用user_params进行更新,其中描述了:id, :name, :email, :created_at, :updated_at, :password_digest, :remember_token, :admin, :auth_token, :password_reset_token, :password_reset_sent_at。请注意缺少您尝试设置的属性。在控制台中,您可能会看到一条消息,指出所需的属性已被丢弃。您添加到user_params的许多属性在任何情况下都没有意义,因为在任何情况下它们都不会由用户设置,如:id, :created_at, :updated_at, :password_digest, :remember_token, :admin, :auth_token, :password_reset_token, :password_reset_sent_at。事实上,这些可能是公然的安全风险(您是否希望用户决定他们是否是管理员?)。你可能有更好的运气,如果你改变PasswordResetsController的user_params方法是这样的:

def user_params 
    params.require(:user).permit(:password, :password_confirmation) 
end 

有意义吗?

+0

是的,它确实有道理。我很愚蠢。非常感谢您花时间阅读代码并解释这一点。 – user2093191 2014-09-06 11:48:04

+1

@ user2093191欢迎来到Stack Overflow!如果我的答案有助于解决您的问题,请考虑[将其标记为已接受](http://stackoverflow.com/help/someone-answers)。这是表示你的问题“已解决”并感谢帮助你的人的习惯方式。 – 2014-09-06 15:34:24

+0

感谢Brad的欢迎,除了真正有用的答案。我只看到你最后的帖子。我也只是“接受”它 - 没有意识到我应该这样做 - 呃! – user2093191 2014-12-23 19:00:23