【问题标题】:Rails 5: permission for user to create record through permission table with PunditRails 5:用户通过 Pundit 权限表创建记录的权限
【发布时间】:2016-09-25 16:14:07
【问题描述】:

在我的应用程序中,我有权限表,其中存储了用户可以执行的所有逻辑。 如果权限表允许,我希望通过 Pundit 允许用户创建新的活动。如果权限表包含此信息,用户可以访问活动并创建新的:

  • permitable_type: Sysmodule // 我存储系统部分信息的另一个表,其中 Campaigns 是其中之一
  • permitable_id: 2 // 表示来自 Sysmodule 的活动
  • 级别:3 // 表示用户可以在广告系列部分编辑内容

到目前为止,我一直收到错误“Pundit::NotDefinedError”,无法找到 nil 的策略,policies/application_policy.rb 是标准的,没有变化。 显然我做错了什么。如何正确进行此授权?非常感谢您的帮助!我在 Rails 5 + Pundit 上。

models/permission.rb

class Permission < ApplicationRecord
  belongs_to :permitable, polymorphic: true
  belongs_to :user
  enum level: {owner: 1, view: 2, edit: 3}
end

models/user.rb

has_many :permissions
has_many :campaigns, through: :permissions, source: :permitable, source_type: 'Campaign' do
  def owner_of
  where('`permissions`.`level` & ? > 0', Permission::owner )
  end
end

has_many :sysmodules, through: :permissions, source: :permitable, source_type: 'Sysmodule' do
  def can_access
  where('`permissions`.`level` & ? > 1', Permission::can_access )
  end
end

控制器/campaigns_controller.rb

def new
  @campaign = Campaign.new
  authorize @campaign
end

政策/campaign_policy.rb

class CampaignPolicy < ApplicationPolicy
attr_reader :user, :campaign, :permission
  @user = user
  @permission = permission
end
def new?
  user.permission? ({level: 3, permitable_type: "Sysmodule", permitable_id: 2})
end

视图/广告系列/index.html.erb

<% if policy(@campaign).new? %>
</li>
   <li><%= link_to "New campaign", new_campaign_path(@campaign) %></li>
</li>
<% end %>

【问题讨论】:

  • 通过permissions 表上的多态关系加入所有内容将是一个巨大的性能问题。虽然 :: (Permission::owner) 在 Ruby 中不是很好的风格,但也调用类方法,因为它看起来像是在访问模块常量。
  • 我认为你想要做的是Permission.levels[:owner]Permission::owner 实际上等于Permission.where(level: :owner)
  • @max 对于能够为任何用户设置任何对象(例如广告系列)的权限(查看/编辑/删除),您有什么建议?假设,从数据库中的 10 个活动中,用户可以查看两个,编辑两个,是两个的所有者,但不能访问四个。
  • 基于角色的基本访问系统可能是更好的选择。 github.com/RolifyCommunity/rolify

标签: ruby-on-rails permissions pundit


【解决方案1】:

与其直接处理用户应该拥有的权限,不如试着想想用户在系统中可以拥有哪些角色。

这使得创建映射到现实世界问题的授权规则变得更加容易。

让我们想象一个我们有用户和组的例子。规则如下:

  • 任何用户都可以创建群组
  • 创建组的用户自动成为管理员
  • 群组是私有的
  • 只有管理员或成员才能查看群组
  • 只有管理员可以修改组

模型:

class User < ApplicationRecord
  rolify 
end

class Group < ApplicationRecord
  resourcify
end

政策:

class GroupsPolicy < ApplicationPolicy

  class Scope < Scope
    def resolve
      scope.with_roles([:admin, :member], current_user)
    end
  end

  def show?
    user.has_role?([:member, :admin], record)
  end

  def index?
    true
  end

  def create?
    true # any user can create
  end

  def new? 
   create?
  end

  def update?
    user.has_role?(:admin, record)
  end

  def edit?
    update?
  end

  def destroy?
    update?
  end
end

控制器

class GroupsController < ApplicationController

  respond_to :html

  before_action :autenticate!
  before_action :set_group!, only: [:show, :edit, :update, :destroy]

  def show
    respond_with(@group)
  end

  def index
    @groups = policy_scope(Group.all)
    respond_with(@groups)
  end

  def new
    @group = authorize( Group.new )
  end

  def create
    @group = authorize( Group.new(group_attributes) )
    if @group.save
      current_user.add_role(:member, @group)
      current_user.add_role(:admin, @group)
    end
    respond_with(@group)
  end

  def edit
  end

  def update
    @group.update(group_params)
    respond_with(@group)
  end

  def destroy
    @group.destroy
    respond_with(@group)
  end

  private 
    def set_group!
       @group = authorize( Group.find(params[:id]) )
    end

    def group_params
       params.require(:group).permit(:name)
    end
end

【讨论】:

  • 感谢您提供此示例。我可能可以将 Rolify 用于我的应用程序中的几个一般角色。但是,我需要允许在记录级别为某些对象分配权限。如果我为此目的离开 Permissions 表并将其他所有内容移至角色,您认为这是否可以提高性能?我的意思是,我可能会优化 Permissions 表,例如,permitable_type 可以是 Enum。可能我还必须优化一些查询。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-17
  • 2013-01-15
  • 1970-01-01
  • 2010-09-18
  • 2018-08-01
  • 2011-03-09
  • 1970-01-01
相关资源
最近更新 更多