Sử dụng gem Sorcery để gửi mail (P.2)
Bài đăng này đã không được cập nhật trong 8 năm
1. Giới thiệu
Như ở phần trước, mình đã giới thiệu về chức năng khi tạo mới 1 user sẽ gửi mail để xác nhận tài khoản của gem Sorcery. Vậy khi sử dụng 1 thời gian, vào một ngày đẹp trời bạn bỗng quên password, vậy làm thế nào để bạn đăng nhập vào tài khoản thì ở bài viết này mình sẽ giới thiệu về chức năng ResetPassword
2. Cài đặt
Cài gem trong gemfile, sau đó chạy lệnh
Sử dụng
rails g sorcery:install reset_password --only-submodules
lênh này sẽ tạo ra
class SorceryResetPassword < ActiveRecord::Migration
def change
add_column :users, :reset_password_token, :string, :default => nil
add_column :users, :reset_password_token_expires_at, :datetime, :default => nil
add_column :users, :reset_password_email_sent_at, :datetime, :default => nil
end
end
sau đó:
rake db:migrate
Vậy bước chuẩn bị để thêm những trường cần thiết cho chức năng reset password đã xong.
Tiếp theo, chúng ta tạo medthod reset_password_email (cái này để gửi mail khi mình muốn reset_password) bằng Sorcery nhé.
rails g mailer UserMailer reset_password_email
class UserMailer < ActionMailer::Base
default from: "hehe@gmail.com"
def reset_password_email(user)
...
end
end
Đừng quên file config của sorcery nhé
# config/initializers/sorcery.rb
Rails.application.config.sorcery.submodules = [:reset_password, blabla, blablu, ...]
Rails.application.config.sorcery.configure do |config|
config.user_config do |user|
user.reset_password_mailer = UserMailer
end
end
Chúng ta cần 1 controller để xử lý tất cả những action password
rails g controller PasswordResets create edit update
Sau 1 hồi biến đổi cải tạo thì nó sẽ trông như dưới đây
# app/controllers/password_resets_controller.rb
class PasswordResetsController < ApplicationController
skip_before_filter :require_login
# request password reset.
# you get here when the user entered his email in the reset password form and submitted it.
def create
@user = User.find_by_email(params[:email])
# This line sends an email to the user with instructions on how to reset their password (a url with a random token)
@user.deliver_reset_password_instructions! if @user
# Tell the user instructions have been sent whether or not email was found.
# This is to not leak information to attackers about which emails exist in the system.
redirect_to(root_path, :notice => 'Instructions have been sent to your email.')
end
# This is the reset password form.
def edit
@token = params[:id]
@user = User.load_from_reset_password_token(params[:id])
if @user.blank?
not_authenticated
return
end
end
# This action fires when the user has sent the reset password form.
def update
@token = params[:id]
@user = User.load_from_reset_password_token(params[:id])
if @user.blank?
not_authenticated
return
end
# the next line makes the password confirmation validation work
@user.password_confirmation = params[:user][:password_confirmation]
# the next line clears the temporary token and updates the password
if @user.change_password!(params[:user][:password])
redirect_to(root_path, :notice => 'Password was successfully updated.')
else
render :action => "edit"
end
end
end
cài config/routes
resources :password_resets
nội dung mail
# app/views/user_mailer/reset_password_email.text.erb
Hello, <%= @user.email %>
===============================================
You have requested to reset your password.
To choose a new password, just follow this link: <%= @url %>.
Have a great day!
# app/mailers/user_mailer.rb
def reset_password_email(user)
@user = User.find user.id
@url = edit_password_reset_url(@user.reset_password_token)
mail(:to => user.email,
:subject => "Your password has been reset")
end
ta tạo views của edit.html.erb của controller trên, đơn giản chỉ là form gửi đến action update của controller vừa tạo
# app/views/password_resets/edit.html.erb
<h1>Choose a new password</h1>
<%= form_for @user, :url => password_reset_path(@token), :html => {:method => :put} do |f| %>
<% if @user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% @user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :email %><br />
<%= @user.email %>
</div>
<div class="field">
<%= f.label :password %><br />
<%= f.password_field :password %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Cơ chế hoạt động như sau:
Khi click vào link "tôi thích reset password", sẽ gọi đến action create của controller vừa tạo, tiếp theo dựa vào lệnh "@user.deliver_reset_password_instructions! if @user" sorcery sẽ tạo 1 token và update vào user này đồng thời gửi mail với nội dung như trên.
Bạn vào mail, click vào đường link (method get) để có thể đến action edit => trên màn hình hiển thị form vừa tạo. Điền password, password_confirmation mới và sub mit để gọi đến action update (method put) tiến hành update cho @user.
3. Kết luận
Qua bài viết mình đã giới thiệu với các bạn về Sorcery một công cụ khá hữu ích với đủ các chức năng cần thiết đối với vấn đề về password, email của bạn. Hãy thử và cảm nhận sự tiện ích của nó đối với project của các bạn nhé.
4. Tài liệu tham khảo
https://github.com/NoamB/sorcery/wiki/User-Activation https://github.com/NoamB/sorcery/wiki/Reset-password
All rights reserved