2014-09-05 26 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