将电子邮件确认添加到Rails应用程序

时间:2014-09-05 16:53:54

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

我遵循Michael Hartl的教程,然后跟随Ryan Bates的Railcast添加重置密码(#274)。也许“试图遵循”更准确,因为尽管经过了数小时的努力/搜索/ tial&错误,我仍然无法获得重置密码。

不得不偏离Ryan的调用:@ user.update_attributes(params [:user]):@ user.update_attributes(user_params),因为我收到了ForbiddenAttributesError。

我还必须在User类中注释#validates:password,length:{minimum:6},因为它在提交时失败(即使提交的密码长度大于6)。

代码目前不会产生任何错误,redirect_to root_url,:notice => “密码已被重置!”作品。但是,密码不会在db中更新。

非常感谢任何见解。

应用程序/模型/ user.rb

class User < ActiveRecord::Base
  before_save { self.email = email.downcase }
  validates :name, presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[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没有型号。

1 个答案:

答案 0 :(得分:0)

app / views / password_resets / edit.html.erb 中,您的表单会说明:password:password_confirmation。但是,在PasswordResetsController中,使用描述:id, :name, :email, :created_at, :updated_at, :password_digest, :remember_token, :admin, :auth_token, :password_reset_token, :password_reset_sent_at的user_params进行更新。请注意缺少您尝试设置的属性。在控制台中,您可能会看到一条消息,指示已丢弃所需的属性。您添加到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

有意义吗?