我已经在我的 Rails 应用程序中安装了 gem Pundit,并仔细按照自述文件中的说明进行操作。
但是,当我在任何控制器中使用授权时,我收到错误消息“未定义的方法‘授权’为 .
此外,当我尝试在视图中使用“policy”时,我收到错误“未定义的方法‘policy’”。
就好像根本没有安装 Pundit 一样!
我在我的应用程序控制器中包含了 Pundit。
我有一个包含我所有策略的 ApplicationPolicy 文件,然后是从应用程序策略继承的每种记录类型的策略文件。
出于某种原因,我无法将我的任何代码粘贴到这个问题中,所以我希望我已经包含了足够的信息!
我很感激任何想法。
我已经向我的应用程序添加了配置pundit addapter授权
config.authorization_adapter = ActiveAdmin::PunditAdapter
Run Code Online (Sandbox Code Playgroud)
当我使用admin@example.com凭据登录时,出现此错误。
Pundit::NotDefinedError in Admin::Dashboard#index
unable to find policy AdminUserPolicy
Extracted source (around line #2):
insert_tag active_admin_application.view_factory["page"]
Run Code Online (Sandbox Code Playgroud)
所以我在我的policy / active_admin文件夹中创建了这些文件
adminuser_policy.rb
module ActiveAdmin
class AdminUserPolicy < ApplicationPolicy
class Scope < Struct.new(:user, :scope)
def resolve
scope
end
end
def home?
true
end
def index?
true
end
def show?
true
end
def new?
true
end
def create?
true
end
def update?
true
end
def destroy?
true
end
end
Run Code Online (Sandbox Code Playgroud)
结束
page_policy.rb
module ActiveAdmin
class PagePolicy < ApplicationPolicy
class Scope …
Run Code Online (Sandbox Code Playgroud) 我有一个Rails 4应用程序使用Active Admin 1.0.0.pre1和pundit 0.3.0进行授权,到目前为止一直运行良好,但我很难找到一个好的方法根据用户的角色自动定制表单.
鉴于这些模型:
ActiveAdmin.register AdminUser do
permit_params do
Pundit.policy(current_admin_user, resource).permitted_attributes
end
form do |f|
f.inputs "Admin Details" do
f.input :role, as: :select, collection: [:manager, :admin]
f.input :email, as: :email
f.input :password
f.input :password_confirmation
end
f.actions
end
end
class AdminUserPolicy < ApplicationPolicy
def permitted_attributes
attributes = [:email, :password, :password_confirmation]
attributes += [:role] if user.has_role? :super_admin
attributes
end
end
Run Code Online (Sandbox Code Playgroud)
我想将role
输入从表单中自动删除.
一种选择可能是:
permitted_attributes = Pundit.policy(current_admin_user, resource).permitted_attributes
form do |f|
f.inputs "Admin Details" do
f.input :role if permitted_attributes.include? :role …
Run Code Online (Sandbox Code Playgroud) 我使用rails 4,设计用于身份验证,Pundit用于授权.我已经限制我的应用程序通过以下代码检查每个控制器上的授权.
class ApplicationController < ActionController::Base
include Pundit
after_action :verify_authorized
#.....
end
Run Code Online (Sandbox Code Playgroud)
但是,我想在我的应用程序中跳过对两个特定控制器的授权(它们向公众开放,用户无需登录).如何在不删除ApplicationController中的verify_authorized的情况下实现它?
默认情况下:paperclip gem存储公共目录中的所有附件.
出于安全原因,我不想将附件存储在公共目录中,因此我将它们保存uploads
在应用程序根目录下的目录中:
class Post < ActiveRecord::Base
belongs_to :user
has_attached_file :some_image, path: ":rails_root/uploads/:attachment/:id/:style/:filename"
do_not_validate_attachment_file_type :some_image
end
Run Code Online (Sandbox Code Playgroud)
我没有指定url
选项,因为我不想为每个图像附件添加网址.如果指定了url:那么具有该url的任何人都可以访问该图像.这不安全.
在user#show
页面中:我想实际显示图像.如果我使用所有的回形针默认值,那么我可以这样做,因为图像将在公共目录中,图像将有一个网址:
<p>
<strong>Some image:</strong>
<%= image_tag @post.some_image %>
</p>
Run Code Online (Sandbox Code Playgroud)
看来如果我将图像附件保存在公共目录之外并且没有指定URL(再次:这样做以保护图像),那么图像将不会在视图中呈现.
我知道如何通过pundit gem 在整个应用程序中进行授权.但是,当该图像可公开访问时,授权图像是无用的.因此,我尝试通过删除URL并将图像保存在公共目录之外来使图像无法公开访问,但随后图像不再在视图中呈现.
更新:我的问题归结为:我的图像保存在我的rails应用程序中.使用回形针:有没有办法在视图中安全地显示图像?换句话说:设置它使图像没有自己独立的URL(因为带有该URL的任何人都可以访问该图像,使该图像不安全).以下是安全显示图像的一些示例:
其他更新:我知道我可以安全地发送一个send_file
允许用户下载图像的文件,但这不是我想要做的.我不希望用户下载图像.相反:我希望用户能够在网页上实际看到图像.我想在页面上安全地显示/渲染图像.使用send_file
(据我所知)允许用户下载文件.它不会在页面上呈现图像.
我最近一直在阅读pundit gem的自述文件,并注意到他们从未在控制器中授权索引视图.(相反,他们使用范围).
他们给出了很好的推理,因为索引页面通常包含元素列表,通过控制生成的列表,您可以有效地控制页面上的数据.但是,偶尔也可能希望阻止访问索引页面本身.(而不是允许访问空白索引页.)我的问题是,执行此操作的正确方法是什么?
到目前为止,我已经提出了几种可能性,并且有以下几个类:
MyModel
MyModelsController
MyModelPolicy
在我的控制器的索引方法中,解决此问题的推荐方法如下:
def index
@my_models = policy_Scope(MyModel)
end
Run Code Online (Sandbox Code Playgroud)
然后,这将允许访问索引页面,但会将结果过滤到该用户可以看到的内容.(EG没有结果无法访问.)
但是为了阻止对索引页面本身的访问,我得到了两种不同的可能性:
def index
@my_models = policy_Scope(MyModel)
authorize @my_models
end
Run Code Online (Sandbox Code Playgroud)
要么
def index
@my_models = policy_Scope(MyModel)
authorize MyModel
end
Run Code Online (Sandbox Code Playgroud)
哪一个是正确的路径,还是有一个不同的替代选择?
关于获得 Rails 5 和 Pundit 授权使用命名空间的问题。
对于 Pundit,在我想要使用的控制器中policy_scope([:admin, @car]
,它将使用位于以下位置的 Pundit 策略文件:app/policies/admin/car_policy.rb
。我在尝试 Pundit 使用此名称空间时遇到问题 - 没有名称空间,它工作正常。
应用程序正在运行:
admins
例如我的命名空间。
该route.rb
文件如下所示:
# config/routes.rb
devise_for :admins
root: 'cars#index'
resources :cars
namespace :admin do
root 'cars#index'
resources :cars
end
Run Code Online (Sandbox Code Playgroud)
我已经设置了 PunditApplicationPolicy
并让命名空间与 Pundit 的authorize
方法一起使用:@record = record.is_a?(Array) ? record.last : record
# app/policies/application_policy.rb
class ApplicationPolicy
attr_reader :user, :record
def initialize(user, record)
@user = user
@record = …
Run Code Online (Sandbox Code Playgroud) 我想使用 RSpec 彻底测试 Rails 应用程序授权设置 (Pundit)。
Pundit 文档和其他值得尊敬的来源建议为 Pundit 策略类编写单元测试。这些测试是测试行为(好)还是实施细节(坏)?
如果我们实际上正在测试行为,那么如果我们最终从 Pundit 切换到另一个授权 gem 或滚动我们自己的授权,我们的测试难道不应该仍然通过吗?
假设对该authorize
方法的调用被意外地从控制器操作中删除,使其开放供公共访问。权威人士的政策测试将不断通过。如果我们没有其他测试涵盖这一点,我们的测试套件可能都是绿色的,而我们的应用程序存在严重的安全漏洞。我们怎样才能避免这种情况呢?也许为 Pundit 控制器类编写单元测试,为控制器单独进行单元测试并模拟authorize
控制器测试中的方法以确保调用它们?
编辑:再想一想,我对类的实现细节和公共 API 之间的差异做出了判断。调用特定的公共方法、传递特定的参数并期望特定的返回值是对任何类进行单元测试(和使用)的要求。请忽略第3项,因为我原来的论点是无效的。
authorize
不调用该方法,它们也会失败。然而,这些将是集成测试,并且应该比单元测试 Pundit 策略类慢。这是否是测试授权设置的更好方法?提前致谢。
我有一个关于Clearance和Pundit的Rails应用程序,我正在尝试创建"团队","团队负责人"可以邀请其他用户加入他们的团队.我愿做类似的东西来devise_invitable,但间隙.
以下是我的计划:
通过注册表单注册该站点的用户将自动分配一个唯一的团队ID,并成为"团队负责人".他们在表单上看不到此ID.(可以这样做的另一种方法是创建一个在注册时保存的唯一团队名称.)最好的方法是创建一个before_filter,用于在注册时分配团队ID和团队负责人吗?
团队ID或名称将是唯一的,每个用户只能属于一个团队.协会看起来像这样:
球队
has_many :users
Run Code Online (Sandbox Code Playgroud)
用户
belongs_to :team
Run Code Online (Sandbox Code Playgroud)一旦这个"团队领导"创建帐户,此用户可以邀请其他用户通过填写用户#新形式类似于间隙注册表单(姓名,电子邮件等),这种形式会造成用户加入团队,将他们分配给团队领导团队.可以为它们分配一个随机密码以提供给Clearance,以便新用户通过验证.
一旦用户由团队负责人创建,他们将使用随机生成的密码保存在数据库中,并将Mailer发送给与标准清除密码重置邮件程序类似的受邀用户.它只是给他们一个通知,他们已被邀请加入团队,并提供重置密码然后登录的链接.它基本上是清除密码重置梅勒与不同的副本.
这是一个不错的策略还是有一个更广泛使用的模式,我缺少用Clearance和Pundit来解决这个问题?我从来没有用Rails做过这样的事情,所以我不知道这是否是一种使用Clearance的管道式磁带方式.
我正在使用 Pundit 在我的 Rails 应用程序上进行授权,并且正在对我的请求进行单元测试。我已经成功测试了该策略,但现在我想验证我的请求是否正在使用该策略。我想以通用的方式做到这一点,我可以在任何请求规范中使用它(无论控制器、操作和策略如何)。老实说,在这一点上,我会遵循一种对所有请求通用的“期望任何策略都能获得授权”的说法。
对于索引操作(使用策略范围)很简单:
在请求描述中我说
RSpec.describe 'GET /companies', type: :request do
include_context 'invokes policy scope'
end
Run Code Online (Sandbox Code Playgroud)
然后我将共享上下文定义为:
RSpec.shared_context 'invokes policy scope', shared_context: :metadata do
before do
expect(Pundit).to receive(:policy_scope!) do |user_context, relation|
expect(user_context.user).to eq(user)
expect(user_context.current_group).to eq(group)
relation
end
end
end
Run Code Online (Sandbox Code Playgroud)
但我该如何对授权方法做同样的事情呢?我不知道哪个具体策略将接收它,也不知道哪个具体控制器将调用authorize
.
我不明白为什么 pundit 不提供自定义匹配器来验证某个请求实际上正在调用给定的策略,或者“模拟”授权/未授权的场景,因此我测试我的请求是否返回正确的状态代码。
有任何想法吗?
pundit ×10
ruby ×4
activeadmin ×2
rspec ×2
clearance ×1
devise ×1
paperclip ×1
rspec-rails ×1
tdd ×1
testing ×1