Thêm tính năng xác thực người dùng (authentication) với Devise
Viết bởi Piotr Steininger, @polishprince Cập nhật bởi Ernesto Jimenez, @ernesto_jimenez
Hướng dẫn này giả định rằng bạn đã xây dựng một ứng dụng Rails Girl bằng cách làm theo hướng dẫn phát triển ứng dụng
1. Thêm devise gem
Mở Gemfile
của bạn và thêm vào dòng sau
gem 'devise'
Và chạy lệnh sau
bundle install
để cài đặt devise
gem.
Và nhớ bạn cần phải khởi động lại server
2. Thiết lập devise cho ứng dụng của bạn
Chạy lệnh sau trên terminal
rails g devise:install
3. Cấu hình Devise
Hãy chắc chắn rằng bạn đã định nghĩa một default_url_options
trong các tập tin môi trường của bạn. Mở tập tin config/environments/development.rb
và thêm vào dòng sau
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
trước từ khóa end
ở cuối tập tin đó.
Mở tập tin app/views/layouts/application.html.erb
và thêm vào
<% if notice %>
<p class="alert alert-success"><%= notice %></p>
<% end %>
<% if alert %>
<p class="alert alert-danger"><%= alert %></p>
<% end %>
ngay phía trên
<%= yield %>
Mở tập tin app/views/ideas/show.html.erb
và xóa dòng có nội dung như sau
<p id="notice"><%= notice %></p>
Thực hiện tương tự với tập tin app/views/comments/show.html.erb
. Những dòng thông báo này là không cần thiết vì chúng ta đã đưa chúng vào tập tin app/views/layouts/application.html.erb
4. Thiết lập User model
Chúng ta sẽ sử dụng một generator script để khởi tạo User model
rails g devise user
rails db:migrate
Và nhớ bạn cần phải khởi động lại server
Coach: Giải thích về user model đã được tạo ra. Các trường (fields) nào được tạo ra và nó là gì?
5. Tạo user đầu tiên
Bây giờ, khi mà bạn đã thiết lập xong tất cả mọi thứ bạn có thể tạo user đầu tiên. Devise đã tạo ra tất cả các đoạn code cũng như routes cần thiết để bạn có thể tạo mới accounts, đăng nhập hay đăng xuất v.v.
Hãy chắc chắn rằng rails server của bạn vẫn đang chạy. Mở http://localhost:3000/users/sign_up (lưu ý đây là địa chỉ server của bạn. Hiện tại hướng dẫn này sử dụng c9.io nên đường dẫn sẽ khác) và tạo tài khoản cho bạn.
6. Thêm vào liên kết đăng kí và đăng nhập
Tất cả những điều chúng ta cần làm bây giờ là thêm liên kết (links) hoặc là thông báo (notice) thích hợp thông báo về tình trạng đăng nhập của người dùng đặt ở góc bên phải của thanh navigation.
Để làm được điều đó, mở tập tin app/views/layouts/application.html.erb
và thêm vào
<p class="navbar-text pull-right">
<% if user_signed_in? %>
Logged in as <strong><%= current_user.email %></strong>.
<%= link_to "Edit profile", edit_user_registration_path, :class => 'navbar-link' %> |
<%= link_to "Logout", destroy_user_session_path, method: :delete, :class => 'navbar-link' %>
<% else %>
<%= link_to "Sign up", new_user_registration_path, :class => 'navbar-link' %> |
<%= link_to "Login", new_user_session_path, :class => 'navbar-link' %>
<% end %>
vào ngay dưới những dòng sau
<ul class="nav">
<li class="active"><a href="/ideas">Ideas</a></li>
</ul>
Cuối cùng, chúng ta sẽ buộc người dùng chuyển hướng đến trang đăng nhập nếu người dùng chưa đăng nhập vào ứng dụng. Mở tập tin app/controllers/application_controller.rb
và thêm vào dòng sau
before_action :authenticate_user!
ngay sau dòng
protect_from_forgery with: :exception
Mở trình duyệt của bạn và hãy thử đăng nhập, đăng xuất.
Coach: Nói về các helpersuser_signed_in?
và current_user
. Tại sao chúng lại hữu ích?
Tiếp theo là gì?
- Bổ sung thêm các trường khác cho model User
- Thêm các quan hệ giữa users và ideas
- Hạn chế chỉ cho phép người dùng được xóa những ideas và comments của mình
- Mở rộng thêm về việc dùng roles và permissions (sử dụng một gem phổ biến về authorization như CanCan)
Những câu hỏi nâng cao
A Dễ
- Thêm trường tên và số điện thoại cho model User
rails generate migration AddUserNameToUsers user_name:string telephone:string
rails db:migrate
- Cấu hình mail server để gửi mail thông báo quên password cho User
config/environments/development.rb
và thêm vào đonaj code sau trước từ khóa end
ở cuối tệp tin:
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: 'smtp.gmail.com',
port: 587,
user_name: '<gmail username>',
password: '<gmail password>',
authentication: 'plain',
enable_starttls_auto: true }
B Bình thường
-
Cho phép user sửa đổi thông tin cá nhân của họ (tên, số điện thoại) (bước này gắn liền với bước 1 trong phần dễ)
Tạo một controller tên là
UsersController
bằng dòng lệnh
rails generate scaffold_controller Users
config/routes.rb
và thêm vào
resource :user, only: [:edit, :update]
app/controllers/users_controller.rb
với nội dung như sau
class UsersController < ApplicationController
def edit
@user = current_user
end
def update
@user = current_user
if @user.update(user_params)
redirect_to root_path, notice: 'Profile was successfully updated.'
else
render :edit
end
end
private
def user_params
params.require(:user).permit(:user_name, :telephone)
end
end
app/views/users/edit.html.erb
với nội dung sau
<h1>Editing Profile</h1>
<%= form_for @user do |f| %>
<% if @user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@user.errors.count, "error") %> prohibited this idea from being saved:</h2>
<ul>
<% @user.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :user_name %><br>
<%= f.text_field :user_name %>
</div>
<div class="field">
<%= f.label :telephone %><br>
<%= f.text_field :telephone %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
app/views/layouts/application.html.erb
và thay đổi các dòng
Logged in as <strong><%= current_user.email %></strong>.
<%= link_to 'Edit profile', edit_user_registration_path, :class => 'navbar-link' %> |
Logged in as <strong><%= current_user.user_name || current_user.email %></strong>.
<%= link_to 'Edit Password', edit_user_registration_path, :class => 'navbar-link' %> |
<%= link_to 'Edit Profile', edit_user_path, :class => 'navbar-link' %> |
http://localhost:3000/user/edit
xem sao?
- Thêm quan hệ giữa user và ideas (mỗi 1 user có thể có nhiều ideas)
user_id
cho bảng ideas
rails generate migration AddUserIdToIdeas user_id:integer
rails db:migrate
app/models/user.rb
và thêm vào dòng sau
has_many :ideas
app/models/idea.rb
và thêm vào dòng sau
belongs_to :user
app/views/ideas/_form.html.erb
bạn thêm vào dòng sau
<%= form.hidden_field :user_id, value: current_user.id %>
user_id
cho ideas_params
. Trong tệp tin app/controllers/ideas_controller.rb
tìm hàm ideas_params
và thay thế dòng code trong hàm bằng dòng dưới đây
params.require(:idea).permit(:name, :description, :picture, :user_id)
- Thêm quan hệ giữa user và comments (mỗi 1 user có thể có nhiều comments)
user_id
cho bảng comments
rails generate migration AddUserIdToComments user_id:integer
rails db:migrate
app/models/user.rb
và thêm vào dòng sau
has_many :comments
app/models/comment.rb
và thêm vào dòng sau
belongs_to :user
app/views/comments/_form.html.erb
bạn thêm vào dòng sau
<%= form.hidden_field :user_id, value: current_user.id %>
user_id
cho comments_params
. Trong tệp tin app/controllers/comments_controller.rb
tìm hàm comments_params
và thay thế dòng code trong hàm bằng dòng dưới đây
params.require(:comment).permit(:user_name, :body, :idea_id, :picture, :reply_id, :user_id)
:picture
và reply_id
ở trên là những phần mở rộng cho các câu hỏi trong phần 5, nếu bạn nào bỏ qua phần đó thì ta có thể bỏ 2 trường đó đi.
C Khó
- Phân quyền, hoặc vai trò cho mỗi user (ví dụ như admin user có quyền được thêm, xóa hay sửa user, người dùng bình thường chỉ có thể xem được thông tin). Bạn có thể sử dụng những gem phân quyền phổ biến như là
cancancan
haythe_role
- Chỉ cho phép user sửa, xóa những ideas và comments do họ tạo ra
- Thêm tính năng đăng nhập thông qua các mạng xã hội (Facebook)