Phân quyền người dùng với gem Administrate và Rolify
Bài đăng này đã không được cập nhật trong 7 năm
Administrate là một thư viện Rails tự động tạo ra trang quản lý admin. Trang quản lý này sẽ tạo ra giao diện mặc định cho phép người dùng có thể thêm, sửa hoặc xóa các bạn ghi của tất cả các model trong ứng dụng.
Hệ thống nào cũng cần phải có chức năng phân quyền, ở đây tôi giới thiệu một thư viện hỗ trợ phân quyền khá hay đó là gem Rolify. Và chúng ta sẽ có một giao diện quản lý phân quyền cho tất cả người dùng một cách rất nhanh và linh hoạt.
Cài đặt Rolify
Thêm vào trong Gemfile
gem 'rolify'
Sau đó bundle install
chạy lệnh sau để kích hoạt:
$ rails g rolify Role User
và migrate
$ rake db:migrate
Một model role sẽ được tạo ra hỗ trợ admin phân quyền Chúng ta tạo những quyền truy cập khác nhau để lưu vào database
Role.create name: :normal
Role.create name: :staff
Role.create name: :admin
Cài đặt Administrate
Thêm vào trong Gemfile
gem 'administrate'
tiếp theo
$ bundle install
chạy lệnh sau để cài đặt vào hệ thống
$ rails generate administrate:install
Cài đặt giao diện quản lý phân quyền:
$ rails generate administrate:dashboard Role
Bạn nên cài đặt routes cho Users và Roles ví dụ như sau:
# config/routes.rb
namespace :admin do
resources :users
resources :roles, only: [:index, :show]
root to: "users#index"
end
Chỉ cho phép người dùng có quyền admin mới được thực hiện:
# app/controllers/admin/application_controller.rb
module Admin
class ApplicationController < Administrate::ApplicationController
before_action :authenticate_user!
before_action :authenticate_admin
def authenticate_admin
redirect_to root_path, alert: 'Not authorized.' unless current_user.has_role?(:admin)
end
end
end
Bây giờ chúng ta sẽ cấu hình giao diện phân quyền để chỉ nhìn thấy tên quyền:
# app/dashboards/role_dashboard.rb
class RoleDashboard < Administrate::BaseDashboard
ATTRIBUTE_TYPES = {
name: Field::String,
}.freeze
COLLECTION_ATTRIBUTES = [
:name,
].freeze
SHOW_PAGE_ATTRIBUTES = [
:name,
].freeze
FORM_ATTRIBUTES = [
:name,
].freeze
end
Để chỉnh sửa giao diện quản lý phân quyền, chúng ta cần tạo một CustomField kế thừa HasManyField
$ rails generate administrate:field HasManyRoles
Những file bên dưới phải được sửa như sau:
# fields/has_many_roles_field.rb
# https://github.com/thoughtbot/administrate/issues/192
require "administrate/field/base"
class HasManyRolesField < Administrate::Field::HasMany
end
# app/views/fields/has_many_roles_field/_form.html.erb
<div class="field-unit__label">
<%= f.label field.attribute_key, field.attribute %>
</div>
<div class="field-unit__field">
<%= f.select(field.attribute_key, nil, {}, multiple: true) do %>
<%= options_for_select(field.associated_resource_options, field.selected_options) %>
<% end %>
</div>
# app/views/fields/has_many_roles_field/_index.html.erb
<%= field.data.pluck(:name).join(' ') %>
# app/views/fields/has_many_roles_field/_show.html.erb
<%= field.data.pluck(:name).join(' ') %>
Bây giờ chúng ta tiến hành sửa để hiển thị quyền truy cập
# app/dashboards/user_dashboard.rb
class UserDashboard < Administrate::BaseDashboard
ATTRIBUTE_TYPES = {
id: Field::Number,
email: Field::String,
roles: HasManyRolesField,
}.freeze
COLLECTION_ATTRIBUTES = [
:roles,
:id,
:email,
].freeze
SHOW_PAGE_ATTRIBUTES = [
:roles,
:id,
:email,
].freeze
FORM_ATTRIBUTES = [
:roles,
:email,
].freeze
end
Restart server và vào đường dẫn http://localhost:3000/admin/users để xem giao diện quản lý mới
Bonus: Phân quyền mặc định cho người dùng mới
# app/models/user.rb
class User < ApplicationRecord
...
after_initialize :set_default_role, if: :new_record?
validates :roles, presence: true
def set_default_role
self.add_role(:normal)
end
end
Extra bonus: validate quyền truy cập:
# app/models/role.rb
class Role < ApplicationRecord
...
validates :name,
inclusion: { in: ["admin", "normal", "staff"] },
uniqueness: true
end
Sử dụng Administrate, chúng ta có thể dễ dàng thực hiện được phân quyền một cách linh hoạt chỉ bởi một số dòng code đơn giản.
All rights reserved