用 CanCanCan 时遇到的一些情况
在使用 CanCanCan 做权限设计的时候,有几个地方需要注意。
当用户系统不止一个的时候
如果项目中的用户系统不止一个,比如说后台的系统用的是 admin
,前台用的是 user
;又如果后台的 admin
又分超级管理员和普通管理员,前台的 user
又分前台管理员、VIP、普通用户等,要利用 CanCanCan 做权限设计,就应该分开来设计。也就是说,分成 AdminAbility
和 UserAbility
来分别设置。
官方文档是用 rails g cancan:ability
来生成权限管理模型的,但是 rails g cancan:admin_ability
会报错。不过没关系,在 model 层手动新建一个admin_ability.rb
就好。
比如说,这样。
class AdminAbility
include CanCan::Ability
def initialize(admin)
admin ||= Administrator.new
if admin.superadmin?
can :manage, :all
else
can [ :edit, :update ], Administrator, id: admin.id
can :read, Administrator
end
end
因为自定义了 ability
类,所以还需要改动另外一些默认设置,比如说 current_ability
,默认的方法是这样的
def current_ability
@current_ability ||= Ability.new(current_user)
end
也就是说,CanCanCan 的正常工作需要依赖两个默认值,一个是 Ability
类,另一个就是 current_user
,所以这里需要把这个默认值覆盖掉,在相应的 Controller 里重定义 current_ability
def current_ability
@current_ability ||= AdminAbility.new(current_admin)
end
这里 current_admin
是因为本来自定义了这个变量。
然后就可以在 controller 层或者 view 层使用 CanCanCan 的各种方法了。
当使用 rails-api 时
用类似的方法定义 user
的权限,总是提示找不到 authorize!
的方法。Google 之后,找到了原因:
If you’re using the rails-api gem, you’ll need to manually include the controller methods for CanCan
class ApplicationController < ActionController::API include CanCan::ControllerAdditions end
因为这是一个小程序项目,去查 User 的 controller,果然是也是继承了 API,手动加上 CanCanCan 的 controller 方法就好了。
class API::V1::BaseController < ActionController::API
include CanCan::ControllerAdditions
end