权限定义在实际项目中,我们对于权限的定义较为复杂,比如某些情况下我们需要定义,用户只能修改他自己创建的资源。那么对于资源权限的定义,也就变得不那么简单,一般情况下,定义有以下几种,每种定义之间略有差异。
基础权限定义基础权限定义就是在 cancan 原有的基础权限基础上进行定义,这种定义方式比较简单,示例代码为 清单12. 在 Ability.rb 中定义每种角色的权限 ,本章不再重复叙述。
自定义权限集合自定义权限集合是基于用 alias_action 声明的自定义权限集合,示例代码如下:
清单13. 自定义权限集合def initialize(user)
user ||= User.new
alias_action :create, :read, :update, :destroy, to: :crud
end
利用 hash 条件筛选定义权限对于需要多条件筛选的资源权限定义,我们可以利用 hash 条件来进行,示例代码如下:
清单14. 利用 hash 条件筛选定义权限def initialize(user)
user ||= User.new
1
2
| # 用户只能对 owner 是他们自己的 Paper 资源进行 read 操作
can :read, Paper, owner: user.email
|
end
利用代码块定义权限当 hash 条件筛选仍然满足不了需求的时候,我们就可以利用代码块来完成权限的定义,示例代码如下:
清单15. 利用代码块定义权限def initialize(user)
user ||= User.new
1
| # 用户只能对 content 长度小于500且内容不为空的 Paper 的资源进行 eidt 和 update 操作
|
can :update, Paper do |paper|
paper.content.length < 500 && paper.content != nil
end
end
在 RESTful controller 中进行权限控制对于 RESTful 的 controller ,我们可以利用 cancan 提供的 authorize_resource 或 load_and_authorize_resource 来做整个 controller 的权限控制,但也可以逐个在方法中利用 authorize! 来做权限控制。关于 authorize! 的使用将会在下一章在 Non-RESTful controller 中进行权限控制 中进行介绍。
如果 controller 和 resource 的名字相同,那么就不需要为 controller 指定 resource,cancan 会自动将它们关联起来。load_and_authorize_resource 方法会为 controller 中的每个方法都自动加载一个实例,并对这个 controller 作权限控制。而 authorize_resource 则不会自动加载实例。load_and_authorize_resource 其实就相当于是 authorize_resource 和 load_resource 的组合。
清单16. 在有同名资源的 RESTful controller 中进行权限控制1
| class PapersController < ActionController::Base
|
load_and_authorize_resource
end
class PapersController < ActionController::Base
load_resource
authorize_resource
end
但是如果 controller 没有同名的 resource ,那么我们就需要指定需要加载的资源类。
清单17. 在无同名资源的 RESTful controller 中进行权限控制1
| class LogController < ApplicationControlle
|
load_and_authorize_resource :class => "Papers"
end
在 Non-RESTful controller 中进行权限控制由于 Non-RESTful controller 没有资源需要加载,所以我们就不可以用 load_and_authorize_resource 进行控制,我们需要在这个 controller 中的每一个方法中进行手动的权限控制。cancan 提供了 authorize! 方法。
首先不要忘记在 Ability.rb 中定义好角色的权限。
注意 authorize! 后面的两个参数都必须是 ruby 的符号对象(Symbol)。
清单18. 在 Non-RESTful controller 中进行权限控制class Ability
include CanCan::Ability
def initialize(user)
1
2
3
4
| user ||= User.new
if user.has_role? :admin
authorize! :info, :logs
end
|
end
end
class LogController < ActionController::Base
def info_logs
authorize! :info, :logs
# roll the logs here
end
end
在页面上进行权限控制当定义好所有权限,我们在页面上也需要做权限控制,cancan 提供了 can? 方法来判断用户的权限。假设我们在 Ability.rb 中对权限的定义为 can :edit, Paper, owner: user.email,那么我们在页面上想对 Paper 的 owner 展示 edit 按钮,可以在页面上作如下控制。
清单19. 在页面上进行权限控制<% if can? :edit, @Paper %>
<%= link_to "Edit Paper", edit_paper_path %>
<% end %> |