对我而言,似乎ActiveAdmin应该主要在两种情况下检查创建授权:
UI需要显示“创建新票证”按钮:此处,检查current_user是否有权创建通用票证是很有用的。
Cancancan语法如下所示:
user.can?(:create, Ticket)
ActiveAdmin需要了解资源是否可以在表单提交后实际存储在数据库中:此处检查当前用户是否可以使用票证“输入”值来存储该票证是否有用形成。
Cancancan语法如下所示:
user.can?(:create, Ticket.new({author_id: user.id, some: "x", other: "y", values: "z"}))
就是这样!那么为什么ActiveAdmin会在为用户显示生成的“创建表单”之前检查以下内容?
user.can?(:create, Ticket.new({author_id: nil, some: nil, other: nil, values: nil}))
如果当前用户仅拥有创建author_id = own_user_id
?
即使在查看表单之前,授权也会失败。
答案 0 :(得分:0)
我无法解释为什么ActiveAdmin是以这种方式编写的,但我可以告诉你我是如何解决类似问题的。
首先,您需要授予您的用户ability以在所有条件下创建所需的记录:
# app/models/ability.rb
...
can :create, Ticket
...
这将获得您过去的ActiveAdmin can?
检查,并允许用户查看表单。但我们需要确保author_id
属于当前用户。为此,您可以在保存之前使用before_create
回调设置正确的author_id
:
# app/admin/ticket.rb
ActiveAdmin.register Ticket do
...
before_create do |ticket|
ticket.author_id = own_user_id
end
...
end
以上假设您有一个辅助方法或一个名为own_user_id
的变量,可供ActiveAdmin模块使用并返回正确的用户ID。如果您使用的是Devise,则可以将current_user.id
替换为own_user_id
。
我承认,这不是最干净的解决方案,但它确实有效。我在自己的项目中实现了类似的东西。
答案 1 :(得分:0)
我确实按如下方式覆盖了数据访问类,以使其正常工作。
我:
在保存资源之前授权之前强制验证
ActiveAdmin::ResourceController::DataAccess.module_eval do
def build_resource
get_resource_ivar || begin
resource = build_new_resource
resource = apply_decorations(resource)
run_build_callbacks resource
# this authorization check is the one we don't need anymore
# authorize_resource! resource
set_resource_ivar resource
end
end
end
ActiveAdmin::ResourceController::DataAccess.module_eval do
def save_resource(object)
run_save_callbacks object do
return false unless object.validate # added it
authorize_resource! resource # added it
object.save(validate: false) # disabled validation since i do it 2 lines up
end
end
end