0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Rails チュートリアル 第12章 まとめ

Posted at

login(forgot password) =>
(rooting ->) password_resets controller new action -> new view
パスワード再設定のためのフォーム画面
form_forを使って、メールアドレスを入力してもらい、params[:email]に格納
params[:email]の送信先は、POST /password_resets であり、createアクションに送られる

-> create action

password_resets.controller
def create
    @user = User.find_by(email: params[:password_reset][:email].downcase)
# userのemailからUser情報を取得
    if @user # もしそのemailをもつUserが存在したら
      @user.create_reset_digest #token発行、tokenのハッシュ化、reset_digestに保存
      @user.send_password_reset_email #emailを送信
      flash[:info] = "Email sent with password reset instructions"
      redirect_to root_url
    else # email情報がDBになければ
      flash.now[:danger] = "Email address not found"
      render 'new' #もう一度フォームに戻ってもらう
    end
  end

create_reset_digestメソッドは、前章ではbefore_actionでsignup前に作動させていたが、今回はcreateアクションに組み込んでいる、場所は違うが、順序や機能は同じ

def create_reset_digest
    self.reset_token = User.new_token
    update_attribute(:reset_digest,  User.digest(reset_token))
    update_attribute(:reset_sent_at, Time.zone.now)
end

send_password_reset_emailメソッドは、新たにpassword_reset()メソッドを実装する必要がある

def send_password_reset_email
    UserMailer.password_reset(self).deliver_now
end
app/mailers/user_mailer.rb
 def password_reset(user)
    @user = user
    mail to: user.email, subject: "Password reset" #送信先とサブタイトル
 end

メールの文面は

app/views/user_mailer/password_reset.text.erb
To reset your password click the link below:

<%= edit_password_reset_url(@user.reset_token, email: @user.email) %>

# reset_tokenとemailをUrlに埋め込む、edit_pass-なのでedit actionへのリンク

This link will expire in two hours.

If you did not request your password to be reset, please ignore this email and
your password will stay as it is.

=> Password_resets controllerの edit action
Userに新しいpasswordを入力してもらうフォーム
edit viewに難しい内容はないが、
前章と違い、edit actionだけでなく、update actionまでUserのemail情報を渡す必要がある
Userにもう一度emailを打ち込んでもらうのは面倒なので、
<%= hidden_field_tag :email, @user.email %>
としてUserには見えない形で、update actionまでつなげる

before_action で正しいユーザーだけがedit,update actionへ行けるように
ここで認証を行う

def valid_user
# nilチェックが失敗する、有効化してなかった、認証できなかった場合はTopページへ
      unless (@user && @user.activated? &&
              @user.authenticated?(:reset, params[:id]))
        redirect_to root_url
      end
end

=> update action
updateアクションでしたいことは

def update
  @user = User.find_by(email: params[:email])
  params[:id] == self.reset_token
  params[:email] == user.email
  @user.password_digest = User.digest(params[:password]) 
# userが入力したpasswordをハッシュ化して、password_digestに保存
# passwordの再設定が完了
  @user.save
end

このようなことだが、再設定に際し、対策することがあるので、書き方は以下のようになる

def update
    if params[:user][:password].empty? #passwordが空だったら            
      @user.errors.add(:password, :blank) #allow_nilがかかる前に強制的にerror
      render 'edit'
    elsif @user.update_attributes(user_params)# user_paramsでセキュリティ対策  下
      log_in @user
      flash[:success] = "Password has been reset."
      redirect_to @user
    else
      render 'edit'                               
    end
end
    def user_params
      params.require(:user).permit(:password, :password_confirmation)
# 渡されるパラメータで適切なものはpass,confirの二つだけ
# digestへ保存されるのは、どうやってしている?
    end

パスワードの有効期限が切れていないかチェックをbeforeフィルターで

def check_expiration
      if @user.password_reset_expired?
        flash[:danger] = "Password reset has expired."
        redirect_to new_password_reset_url
      end
end
user.rb
def password_reset_expired?
    reset_sent_at < 2.hours.ago
# <をより早いと読むと、2時間よりも早い、つまりまだ2時間経ってないなら
# 有効期限なので、trueが返ってくる
end
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?