Rails 5:允许用户通过Pundit通过权限表创建记录

时间:2016-09-25 16:14:07

标签: ruby-on-rails permissions pundit

在我的应用程序中,我有Permission表,它存储用户可以执行的所有逻辑。 使用Pundit我想允许用户在权限表允许的情况下创建新的广告系列。如果权限表包含此信息,用户可以访问广告系列并创建新广告:

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

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

模型/ permission.rb

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

模型/ 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 %>

1 个答案:

答案 0 :(得分:0)

不要直接处理用户应该拥有的权限,而应该考虑用户在系统中可以拥有的角色。

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

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

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

模特:

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