标签: pundit

具有权威的视图中的属性级别授权

我正在使用Pundit在Rails应用中进行授权。对于某些模型,我需要属性级授权。例如,允许普通用户更改其电话号码,但不能将其状态设置为“管理员”。

根据Pundit文档建议,我正在使用permitted_attributes

现在,我想在视图中访问这些属性,以决定在表单中显示或启用哪些字段。是否有一种(优雅的)方式来执行此操作,而基本上不在那里重复授权字段?

authorization ruby-on-rails pundit

4
推荐指数
1
解决办法
695
查看次数

在Pundit中使用策略助手,没有可用的实例变量

所以我决定尝试权威的用户授权解决方案.我想知道如何policy在视图中使用帮助器,实例变量可能是nil,如下面的简单情况:

应用程序/视图/项目/ index.html.slim

h1 Projects
(...)
- if policy(@project).create?
  = link_to 'New Project', new_project_path
Run Code Online (Sandbox Code Playgroud)

应用程序/控制器/ projects_controller.rb

(...)
def index
  @projects = Project.all
end
(...)
Run Code Online (Sandbox Code Playgroud)

应用程序/政策/ project_policy.rb

class ProjectPolicy < Struct.new(:user, :project)
  def create?
    user.has_role? :admin
  end
Run Code Online (Sandbox Code Playgroud)

我想在Projects #index页面上显示一个"New Project"链接,但是我在这个视图中没有@project实例变量,但是收到错误:

Pundit :: Projects#index中的NotDefinedError

无法找到策略NilClassPolicy

错误显然是因为我传递了@projectnil的实例变量,因此有一个NilClass,显然我没有必要授权.

我找到了2个解决这个问题的方法,使它运行正常,但它们似乎都不合适:

  1. 在视图中使用现有的@projects变量,即: policy(@projects[0])
  2. 向项目添加一行#index controller action定义此实例变量,例如.@project = Project.new(或直接在视图类似于上文:policy(Project.new))

第一个解决方案将导致@projects数组中的相同错误为空,而第二个解决方案将创建冗余实例变量.所有策略帮助程序需要知道的是我希望在哪个类上强制执行授权逻辑.

有关正确实现方法的任何建议吗?

ruby authorization ruby-on-rails ruby-on-rails-3 pundit

3
推荐指数
1
解决办法
7853
查看次数

user.admin在哪里?在rails-devise-pundit starter app中定义?

我使用RailsApps rails-composer创建了rails- devise-pundit starter应用程序.我仍然对铁轨上的红宝石有点新意,而且更新设计,专家和导轨4.

我正在查看代码以了解它是如何工作的.控制器和策略类中有很多地方user.admin?叫做.但我找不到管理员?方法.我希望它在用户模型中,但它不存在.这是用户类:

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable, :confirmable,
         :recoverable, :rememberable, :trackable, :validatable
  enum role: [:user, :vip, :admin]
  after_initialize :set_default_role, :if => :new_record?

  def set_default_role
    self.role ||= :user
  end
end
Run Code Online (Sandbox Code Playgroud)

在users_controller.rb的一部分中使用:

def show
  @user = User.find(params[:id])
  unless current_user.admin?
    unless @user == current_user
      redirect_to root_path, :alert => "Access denied."
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

权威或设计是否会以某种方式创建此方法?我已经看到它在专家文档中使用,但它只是以它为例.它没有说明需要创建方法或者它处理它.它是否以某种方式使用角色枚举,其中:admin作为可能的值?如果有人能解释这是如何工作的,我会很感激.

我打算尽快添加使用rolify gem来处理角色,而不是用户类中的角色枚举.也许我会因为某些原因想要制作完全不同的角色名称.我想确保我理解如何保持一切正常.谢谢.

ruby-on-rails devise pundit railsapps

3
推荐指数
1
解决办法
4040
查看次数

使用Pundit并获取渲染和/或重定向被多次调用

当不允许用户通过权威人员查看具有授权规则的页面时,我收到以下错误:

在此操作中多次调用渲染和/或重定向.请注意,您只能调用渲染或重定向,每次操作最多一次.另请注意,重定向和呈现都不会终止操作的执行,因此如果要在重定向后退出操作,则需要执行类似"redirect_to(...)并返回"的操作.

这是application_controller.rb:

class ApplicationController < ActionController::Base    
  # Includes Authorization mechanism
    include Pundit

  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception

  # Globally rescue Authorization Errors in controller.
  # Returning 403 Forbidden if permission is denied
  rescue_from Pundit::NotAuthorizedError, with: :permission_denied

  # Enforces access right checks for individuals resources
  # after_filter :verify_authorized, :except => :index

  # Enforces access right checks for collections
  # after_filter :verify_policy_scoped, :only …
Run Code Online (Sandbox Code Playgroud)

ruby-on-rails-4 pundit

3
推荐指数
1
解决办法
1742
查看次数

如何创建验证Pundit拒绝未登录用户的规范?

我在我的封闭系统Ruby on Rails应用程序上使用Pundit gem进行授权(使用Rails 4.1.5和Rspec 3.0)

我已经将我的应用程序策略配置为在未按照Pundit文档中的建议定义用户时引发异常:

class ApplicationPolicy
  attr_reader :user, :record

  def initialize(user, record)
    raise Pundit::NotAuthorizedError, "must be logged in" unless user
    @user = user
    @record = record
  end
end
Run Code Online (Sandbox Code Playgroud)

如何编写一个规范来验证每个Pundit策略是否拒绝零用户?

我做了以下尝试:

RSpec.describe PostPolicy do
  it "should raise an exception when users aren't logged in" do
    expect(AccountFolderPolicy.new(nil, record)).to  raise_error(Pundit::NotAuthorizedError)
  end
end
Run Code Online (Sandbox Code Playgroud)

但它出错了

 Failure/Error: expect(PostPolicy.new(nil, record)).to raise_error(Pundit::NotAuthorizedError)
 Pundit::NotAuthorizedError:
   must be logged in
Run Code Online (Sandbox Code Playgroud)

关于如何正确测试这个的任何建议?

ruby rspec ruby-on-rails pundit

3
推荐指数
1
解决办法
1140
查看次数

授权用户在 Rails 中使用 Pundit 编辑特定字段

我正在我的 Rails 应用程序中运行 Pundit 进行授权。我似乎已经掌握了这一切,但想知道如何将编辑或更新操作限制到某个字段。

例如,用户可以编辑他们的 user.first_name、user.mobile 或 user.birthday 等,但不能编辑他们的 user.role。基本上我的逻辑是,让用户编辑任何装饰性的东西,但不是功能性的。

这些字段应该只能由具有“super_admin”角色的用户进行编辑(我在 user.rb 上使用如下方法进行了设置)。

  def super_admin?
    role == "super admin"
  end

  def account?
    role == "account"
  end

  def segment?
    role == "segment"
  end

  def sales?
    role == "sale"
  end

  def regional?
    role == "regional"
  end

  def national?
    role == "national"
  end

  def global?
    role == "global"
  end 
Run Code Online (Sandbox Code Playgroud)

我几乎有一个干净的石板user_policy.rb文件,其中更新和编辑操作是默认的

  def update?
    false
  end

  def edit?
    update?
  end
Run Code Online (Sandbox Code Playgroud)

也许我对此的想法完全错误,应该只包装一个 user.super_admin?用户显示页面上的角色字段周围的 if 语句,但如果我只是为了安全而使用该策略,这感觉是错误的。

authorization ruby-on-rails pundit

3
推荐指数
1
解决办法
1654
查看次数

为什么专家在控制器测试中找不到策略?

控制器:

class UsersController < ApplicationController
  def index
    ...
    authorize User
  end
  ...
Run Code Online (Sandbox Code Playgroud)

政策:

class UserPolicy < ApplicationPolicy
  def index
    @user.admin?
  end
end
Run Code Online (Sandbox Code Playgroud)

考试:

class UsersControllerAuthorizationTest < ActionController::TestCase
  tests :users

  def user
    @user ||= create(:user)
  end

  test 'should not authorize ordinary users to access the page' do
    sign_in user
    get :index
    assert_response :error
  end
end
Run Code Online (Sandbox Code Playgroud)

该应用程序Pundit::NotAuthorizedError (not allowed to index? this User)按预期失败.但测试说:

Pundit::NotDefinedError: unable to find policy UserPolicy for User
Run Code Online (Sandbox Code Playgroud)

我做错了吗?我可以让它找到政策吗?

UPD必须与rails'自动加载'有关.调用constantize'UserPolicy'使得它自动加载 …

ruby testing bdd automated-tests pundit

3
推荐指数
1
解决办法
972
查看次数

Pundit:在嵌套资源中使用auhorize Index

使用Rails 4.2.4与Devise(3.5.2)和Pundit(1.0.1).Decent_exposure(2.3.2).

我有一个简单的嵌套关联用户和想法:

class User < ActiveRecord::Base
has_many :ideas
...

class Idea < ActiveRecord::Base
belongs_to :user
...
Run Code Online (Sandbox Code Playgroud)

在routes.rb中

devise_for :users

resources :users do
  resources :ideas
end
Run Code Online (Sandbox Code Playgroud)

然后我只是试图禁止访问users/1/ideas如果current_user不是Ideas的所有者(在本例中,如果current_user.id!= 1).我无法弄清楚该怎么做.我能够在Index视图中只显示current_user Ideas:

[创意控制器]

def show
  authorize idea
end
Run Code Online (Sandbox Code Playgroud)

[思想政策]

def show?
  @current_user == @idea.user
end
Run Code Online (Sandbox Code Playgroud)

但是,如何阻止用户只是导航到其他用户的Idea索引页面?我想在Ideas控制器中我应该使用类似的东西:

def index
  authorize user
end
Run Code Online (Sandbox Code Playgroud)

但那又怎样?如何向用户政策发送有关Idea集合的信息?或者我应该通过创意政策本身进行授权?

authorization nested ruby-on-rails-4 pundit

3
推荐指数
1
解决办法
1350
查看次数

如何在 Rspec 中测试 Pundit Scopes?

我有一个非常简单的 Pundit 策略,适用于不同的用户角色。我不知道如何在 Rspec 中测试它。具体来说,我不知道如何在访问范围之前告诉范围哪些用户登录。

这是我尝试过的:

let(:records) { policy_scope(Report) } 

context 'admin user' do
  before(:each) { sign_in(admin_user) }
  it { expect(reports.to_a).to match_array([account1_report, account2_report]) }
end

context 'client user' do
  before(:each) { sign_in(account2_user) }
  it { expect(reports.to_a).to match_array([account2_report]) }
end
Run Code Online (Sandbox Code Playgroud)

当我运行 Rspec 时,我得到:

NoMethodError: undefined method `sign_in' for #<RSpec::ExampleGroups::ReportPolicy::Scope:0x00007f93241c67b8>
Run Code Online (Sandbox Code Playgroud)

sign_in在控制器测试中广泛使用,但我想这不适用于策略测试。

Pundit 文档只说:

Pundit 不提供用于测试范围的 DSL。只需像常规 Ruby 类一样对其进行测试即可!

那么...是否有人有针对特定用户测试 Pundit 范围的示例?我如何告诉范围 current_user 是什么?


FWIW,这是我政策的精髓:

class ReportPolicy < ApplicationPolicy
  def index?
    true
  end

  class Scope < Scope
    def resolve
      if user.role …
Run Code Online (Sandbox Code Playgroud)

ruby rspec ruby-on-rails pundit

3
推荐指数
1
解决办法
2401
查看次数

当访问取决于父模型时使用 Pundit 的正确方法

我有一个客户端模型,其中有_many 联系人

用户是否可以创建、更新或编辑取决于客户端而不是联系人,而销毁取决于联系人本身。

在 ContactPolicy 类中,我可以简单地检查 @contact.client 以查看用户是否可以访问,这很好。

但是,对于 List 方法,我没有一个联系人,而是一个 @client.contacts 列表,因此没有简单的方法可以告诉 Pundit 允许什么。

我不确定 Pundit 应该如何处理这个问题。

请注意,我不想要范围,因为它是是或否取决于客户记录

ruby-on-rails pundit

2
推荐指数
1
解决办法
832
查看次数