美文网首页
Role-based Authorization with Pu

Role-based Authorization with Pu

作者: 丿丶生若只如初见 | 来源:发表于2015-11-04 11:41 被阅读0次

    参考: http://www.xyyz.me/2015/07/24/role-based-authorization-with-pundit.html

    本文将介绍: 在 Rails 应用中, 如何使用 Pundit 实现一个基于角色的授权系统.
    数据模型
    +------+ +------+ +------------+| | N N | | 1 N | || User |<-------->| Role |<-------->| Permission || | | | | |+------+ +------+ +------------+

    User 和 Role 是多对多的关系, Role 和 Permission 是一对多的关系. Permission 的定义包含两个字段: action
    和 resource
    , 分别与 Rails 的 Controller Action 和 Model 对应.
    Model 关系定义:
    class User < ActiveRecord::Base has_and_belongs_to_many :roles has_many :permissions, through: :rolesend

    class Role < ActiveRecord::Base has_many :permissions, dependent: :destroy has_and_belongs_to_many :usersend

    class Permission < ActiveRecord::Base belongs_to :role has_many :users, through: :roleend

    权限定义
    为了方便在角色管理时能够列出可选择的权限点, 权限点的定义需要通过某种方式存储起来:
    class ApplicationPolicy class << self def actions @actions ||= [] end def permit(action_or_actions) acts = Array(action_or_actions).collect(&:to_s) acts.each do |act| define_method("#{act}?") { can? act } end actions.concat(acts) end end private def can?(action) permission = { action: action, resource: record.is_a?(Class) ? record.name : record.class.name } user.permissions.exists?(permission) endend

    在 ApplicationPolicy
    里定义一个 permit
    方法 (类方法) 用来定义和保存权限点,can?
    方法用来做权限检查.
    然后就可以像这样声明权限点:
    class ResourcePolicy < ApplicationPolicy permit [:read, :create, :update, :destroy]end

    这些 Action 就会被保存到 ResourcePolicy.actions
    里.
    另外还需要两个方法 policies
    和 resource
    :
    class ApplicationPolicy class << self def policies @policies ||= Dir.chdir(Rails.root.join('app/policies')) do Dir['*/_policy.rb'].collect do |file| file.chomp('.rb').camelize.constantize unless file == File.basename(FILE) end.compact end end def resource name.chomp('Policy') end endend

    分别用来获取所有的 Policy 和 每个 Policy 对应的 resource (这两个方法是通过简单的命名规则实现的, 灵活性会差一点).
    角色与权限
    在角色管理中, 可以像这样列出所有可选择的权限点:
    <% ApplicationPolicy.policies.each do |policy| %> <% resource = policy.resource %> <div> <span><%= resource %></span> <% policy.actions.each do |action| %> <% checked = role.permissions.exists?(action: action, resource: resource) %> <% value = "#{action}##{resource}" %> <%= f.check_box :permissions, { multiple: true, checked: checked }, value, nil %> <%= f.label :permissions, value, value: value %> <% end %> </div><% end %>

    角色与用户
    在用户管理中, 可以这样为用户指定角色:
    <div> <%= f.label :roles %><br /> <%= f.collection_check_boxes :role_ids, Role.all, :id, :name %></div>

    参考项目
    这个系统的完整实现请参考此项目 (mxyzm/oh_my_user) 的后台管理部分.
    参考资料
    利用 cancan 实现一个优雅可扩展的角色管理系统

    相关文章

      网友评论

          本文标题:Role-based Authorization with Pu

          本文链接:https://www.haomeiwen.com/subject/wdnqhttx.html