用cancancan 来构建权限管理系统 - tianlu1677/tianlu1677.github.io GitHub Wiki
这里的权限管理主要以cms_admin的权限管理做介绍 同时,注意这里使用的是device与cancancan
- 1.修改gemfile, 安装gem
gem 'device'
gem 'cancancan'
-2. 建立权限model
rails g cancan:ability
会生成以下文件 app/models/ability.rb以及以下代码
class Ability
include CanCan::Ability
def initialize(user)
end
end
-3. 创建数据库,因为这里采用的是
Administrator ——n * m———— roles ——n * m———— permissions
class DeviseCreateAdministrators < ActiveRecord::Migration
def change
create_table(:administrators) do |t|
t.string :username
t.string :name
t.string :gender
t.string :mobile
t.string :phone
t.string :status
t.boolean :admin
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, default: 0, null: false
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
t.timestamps
end
add_index :administrators, :email, unique: true
add_index :administrators, :reset_password_token, unique: true
end
create_table :roles do |t|
t.string :name
t.timestamps
end
create_table :administrators_roles, id: false do |t|
t.belongs_to :administrator
t.belongs_to :role
end
add_index :administrators_roles, [:administrator_id, :role_id]
create_table :permissions do |t|
t.string :name
t.string :subject_name
t.string :subject_class
t.integer :subject_id
t.string :action
t.text :desc
t.timestamps
end
create_table :permissions_roles, id: false do |t|
t.belongs_to :permission
t.belongs_to :role
end
add_index :permissions_roles, [:permission_id, :role_id]
end
然后执行 rake db:migrate
-4. 修改model中的关联关系
用户
class Administrator < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_and_belongs_to_many :roles
accepts_nested_attributes_for :roles
end
角色
class Role < ActiveRecord::Base
has_and_belongs_to_many :administrators
has_and_belongs_to_many :permissions
accepts_nested_attributes_for :permissions
validates :name, presence: true
end
权限
class Permission < ActiveRecord::Base
has_and_belongs_to_many :roles
end
-5. 编写controller
class AdministratorsController < ResourceController
has_scope :search , :only => [:index] , :type => :hash
def my
@administrator = current_administrator
render "show"
end
private
def permitted_params
if params[:administrator].present? and params[:administrator][:password].blank?
params.permit(:administrator => [:username, :email, :name, :admin, role_ids: [], :roles_attributes => [:name]])
else
params.permit(:administrator => [:username, :email, :name, :admin, :password, :password_confirmation, role_ids: [], :roles_attributes => [:name]])
end
end
def attributes
%w(email username name roles admin)
end
end
class RolesController < ResourceController
private
def permitted_params
params.permit(role: [:name, permission_ids: []])
end
def attributes
%w(name)
end
end
# -*- encoding : utf-8 -*-
class PermissionsController < ResourceController
private
def permitted_params
params.permit(:subject_name, :name, :subject_class, :subject_class, :subject_id, :action, :desc)
end
def attributes
[:subject_name, :name, :subject_class, :subject_id, :action, :desc]
end
end
- 6. 编写views
参见 views/administrators views/roles
-7. 修改具体的权限分配,与步骤1做对比后
class Ability
include CanCan::Ability
def initialize(user)
return unless user.present?
can :manage, :all and return if user.admin?
user.roles.each do |role|
role.permissions.each do |permission|
if permission.subject_id.nil?
can permission.action.to_sym, permission.subject_class.constantize
else
can permission.action.to_sym, permission.subject_class.constantize, :id => permission.subject_id
end
end
end
end
end
-8. 在seed中初始化各个model的权限
['Administrator', 'Role', 'Permission',
'User', 'Collection', 'LearningRecord', 'MicroSpecialtiesUser',
'InstructiveCourse', 'OpenCourse', 'Instructor', 'Institution', 'Syllabus',
'Certificate', 'CertificateBackground', 'CertificateInstructor', 'CertificateInstitution',
'CertificateInstitutionsCertificate', 'CertificateInstructorsCertificate',
'Evaluation', 'Article', 'Category', 'Tag',
'Specialty', 'MicroSpecialty',
'Feedback', 'Faq', 'CommonLog', 'Bug',
'Score', 'ScoreLog',
'School', 'Student',
'Navigation', 'CoursesNavigation', 'Banner', 'News', 'Advertisement'].each do |model|
{manage: '管理', read: '查看', create: '添加', update: '修改', destroy: '删除'}.each do |k, v|
Permission.create_with(name: v,
desc: "#{I18n.t("activerecord.models.#{model.underscore}")}",
subject_name: I18n.t("activerecord.models.#{model.underscore}")
).find_or_create_by!(action: k.to_s,
subject_class: model,
subject_id: nil
)
end