Authorizing your Rails app with Authority and Rolify
Bài đăng này đã không được cập nhật trong 3 năm
Bài viết này mình xin giới tiệu 1 cách phân quyền mới mạnh mẽ và có thể sử dụng linh hoạt bằng cách sử dụng :
- Devise: Cung cấp chứng thực(authentication): cho phép người dùng đăng kí và đăng nhập, để bạn biết họ là ai.
- Rolify: Giúp bạn chỉ định vai trò cho người dùng và kiểm tra vai trò mà họ có.
- Authority: Điều khiển các role quản lí chúng sao cho phù hợp. Giúp bạn sử dụng các role hoặc bất kỳ logic nào bạn thích) để kiểm soát ai có thể làm những gì.
Installation
Ta thêm 3 gem vào trong gemfile rồi install:
gem 'devise'
gem 'authority'
gem 'rolify'
Bước 1: Cài đặt devise cho user
rails generate devise:install
rails generate devise User
Bước 2: Cài đặt gem Authority
rails generate authority:install
Bước 3: Cài đặt gem Rolify
rails generate rolify:role
Sau đó rake db:migrate
ta được 2 model: 1 model chứa các role, và 1 model quản lý role của user
Configuration
Sau khi cài đặt, ta có được file /config/initializers/authority.rb
chứa định nghĩa các quyền
Authority.configure do |config|
// Định nghĩa các quyền tương ứng với các action trong controler. Bạn có thể tùy chỉnh theo cách bạn muốn. Mặc định là:
config.controller_action_map = {
:index => 'read',
:show => 'read',
:new => 'create',
:create => 'create',
:edit => 'update',
:update => 'update',
:destroy => 'delete'
}
// Định nghĩa các abiliies
config.abilities = {
:create => 'creatable',
:read => 'readable',
:update => 'updatable',
:delete => 'deletable'
}
//user ta dùng để sử dụng để phân quyền. có thể là current_user hoặc current_admin
config.user_method = :current_user
end
Chỉnh sửa ApplicationAuthorizer
được tạo mặc định khi cài gem authority. cập nhập default method để check xem có role admin không?
def self.default(adjective, user)
user.has_role? :admin
end
Điều này cho thấy rằng tất cả các action đều yêu cầu vai trò role admin theo mặc định. Sau đó bạn có thể bắt đầu thêm logic cụ thể hơn.
# To update a specific resource instance, you must either own it or be an admin
def updatable_by?(user)
resource.author == user || user.has_role?(:admin)
end
Sử dụng phương thức rolify's resourcify trên tất cả model bạn muốn thêm role cho nó. Ví dụ ta thêm role cho model Post
class Post < ActiveRecord::Base
resourcify
belongs_to :author, class_name: 'User'
end
Thêm Authority::UserAbilities vào trong model uer(để thêm method như can_update?) và thêm Authority::Abilities vào trong model khác(để thêm method như updatable_by?)
class User < ActiveRecord::Base
include Authority::UserAbilities
has_many :posts, foreign_key: :author_id
end
...
class Post < ActiveRecord::Base
resourcify
include Authority::Abilities
end
Usage
Ở controler ta tạo 1 authorizer định nghĩa quyền truy cập của user tại model User
class UserAuthorizer < ApplicationAuthorizer
def self.updatable_by?(user)
user.has_role?(:admin) || user.has_role?(:editor)
end
def self.creatable_by?(user)
user.has_role?(:admin) || user.has_role?(:editor)
end
def self.readable_by?(user)
user.has_role?(:admin) || user.has_role?(:editor)
end
def self.deletable_by?(user)
user.has_role?(:admin)
end
end
Ở model /app/models/user.rb
class User < ActiveRecord::Base
# creatable_by?(user)
include Authority::Abilities
# can_create?(resource)
include Authority::UserAbilities
# Tương ứng với /app/authorizers/user_authorizer.rb
self.authorizer_name = 'UserAuthorizer'
resourcify
rolify
after_create :assign_default_role
def assign_default_role
self.add_role(:editor)
end
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable#, :confirmable
end
Ở controller: /app/controllers/admins/users_controller.rb
class Admins::UsersController < AdminsController
alias :user_for_this_request :current_admins_user
# ngoại trừ action show tất quả đều được phân quyền đã được định nghĩa ở user_authorizer.rb
authorize_actions_for User, except: :show
def index
@users = User.all
end
def show
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
@user = User.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def user_params
params
.require(:user)
.permit(:email, :password, :password_confirmation)
end
end
Ở application_controller
ta render ra trang lỗi và báo với người dùng khi không có quyền truy cập
class ApplicationController < ActionController::Base
rescue_from Authority::SecurityViolation, with: :authority_forbidden
def authority_forbidden(error)
Authority.logger.warn(error.message)
render file: "#{Rails.root}/public/403.html", status: 403, layout: 'error'
end
end
Một vài câu lệnh hay dùng:
Ta vào rails c
. Tạo vài user bằng cách
> alice = User.new
> alice.email = "alice@example.com"
> alice.password = "test1234"
> alice.save
> bob = User.new
> bob.email = "bob@example.com"
> bob.password = "test1234"
> bob.save
> cathy = User.new
> cathy.email = "cathy@example.com"
> cathy.password = "test1234"
> cathy.save
Thêm role admin cho user
> alice.add_role "admin"
Tạo Post cho user
> post = bob.posts.new
> post.title = 'Test Post'
> post.name = 'Test Post'
> post.content = 'Nothing to see here'
> post.save
Check xem ai có thể update Post
> bob.can_update?(post) #=> true; he is the author
> alice.can_update?(post) #=> true; she is an admin
> cathy.can_update?(post) #=> false
Kiếm tra xem user có role admin không
user.has_role? :admin #=> true or false
Xóa role admin của user
user.remove_role :admin
Hi vọng bài viết có thể giúp ích cho bạn!
Nguồn tham khảo:
http://qiita.com/keisukemizuno@github/items/9c079c275118fa7a0f36 https://github.com/RolifyCommunity/rolify/wiki/Using-rolify-with-Devise-and-Authority
All rights reserved