2

想知道使用 acl9 管理用户角色的最佳方法是什么?

这是需求:

  • 管理员应该能够更新用户的角色。

以下是问题:

  1. 我们如何列出所有主题角色?:管理员,:经理
  2. 为了保持 api 端点 RESTful,我想理想地在 user_controller 的更新方法中传递角色参数。
  3. 我怎样才能只为角色属性授权,以便用户对象的所有者仍然可以修改他们的名字、姓氏字段,但不能修改他们的角色字段?只允许管理员。

access_control我可以在块外手动检查参数:

def secure_params
    if current_user.has_role?(:admin)
        params.require(:user).permit(:first_name, :last_name, :role)
    else
        params.require(:user).permit(:first_name, :last_name)
    end
end

但我想我会检查一下是否有更清洁的解决方案。

最后,使用RoleTypes.ADMIN,RoleTypes.MANAGER而不是:admin? 如果是这样,最好的方法是什么?该类是否可以在整个 Rails 应用程序中访问?

4

2 回答 2

2

我们如何列出所有主题角色?:管理员,:经理

Role模型只是一个普通模型,因此您可以像查询其他任何内容一样查询它:

Role.uniq.pluck :name

为了保持 api 端点 RESTful,我想理想地在 user_controller 的更新方法中传递角色参数。

通常,您最好使用单独的控制器来执行管理,并将其放在Admin::名称空间中,并使用namespace :admin do路由等。

然后在该控制器中,您可以使用普通access_control块来确保没有其他人可以进入:

class Admin::UsersController < ApplicationController

  access_control do
    allow :admin
  end

  # ...

end

那么,是的,您可以通过多种方式设置/更新角色,但鉴于用户可以拥有许多角色,最好不要使用单个:role参数,而是使用:

class User < ActiveRecord::Base
  acts_as_authorization_subject
  accepts_nested_attributes_for :roles
end

因此,在您的控制器中,您将拥有:

def user_params
  params.require(:user).permit(:first_name, :last_name, roles_attributes: [:name])
end

然后在您的表单中,您可以执行以下操作:

= form_for :user do |f|
  = f.text_field :first_name
  = f.text_field :last_name
  = f.fields_for :roles do |fr|
    = fr.text_field :name

请注意,我假设您在这里只有简单的角色,而不是对象上的角色,如果您有对象角色,那么您将需要一些更棘手的东西来捕获authorizable_id每个authorizable_type角色,以及一些选择要在其上的对象的方法行为。

我怎样才能只为角色属性授权,以便用户对象的所有者仍然可以修改他们的名字、姓氏字段,但不能修改他们的角色字段?只允许管理员。

希望您现在已经自己回答了这个问题 - 通过对管理界面和用户自己的界面使用不同的控制器。

最后,使用 RoleTypes.ADMIN、RoleTypes.MANAGER 代替 :admin 是否可行且明智?

不,这些符号更简单更好,尽管这样做很常见:

class Role < ActiveRecord::Base
  def self.permitted_roles
    %i/admin manager foo bar wee/
  end
end

这样你就可以Role.permitted_roles用来构造一个复选框数组,或者一个下拉列表,或者类似的东西。

于 2015-03-25T22:28:10.783 回答
-1

编辑:完全错过了第一句话中的 acl9 位 - 抱歉!

话虽如此,我的回答仍然适用;我会有一个辅助方法或使用 acl9 的has_role?方法并基于此更改视图。IE:

>> <% if @user.has_role?(:foo, nil) %> 
>>    <p>
>>    <%= f.label :usertype %><br />
>>    <%= f.check_box :usertype %>
>>   </p>
>> <% end %>

我会使用辅助方法来实际设置用户角色,.has_role!即:user.has_role!:som​​e_role, [可选范围],其中 user 是被分配角色的用户。

有关更多信息,请查看此内容(来自 acl9 文档): https ://github.com/be9/acl9/wiki/Tutorial%3A-securing-a-controller


好的,所以如果我认为你说的是​​正确的,你想要一种方法让用户可以编辑内容和/或个人资料信息,但管理员可以编辑用户角色。

首先,我将假设角色是您的用户模式的一部分(如果不是,我建议您考虑将其移至那里)。如果是这样,我建议向您的用户模型添加一个方法,该方法may_edit?(content)根据用户角色或 id 返回一个布尔值。IE:

def may_edit?(content) item.user.id == self.id end

find_by(id)通过控制器中的a 找到内容的位置。然后,您可以if在控制器中使用 an 来指示哪些内容将出现在节目中:

<% if current_user.role == admin %> <%= some button or link or dropdown render %> <% end %>

<% if current_user.may_edit?(content) %> <%= some button or link or dropdown render %> <% end %>

或类似的规定。您还可以将 anif..else作为单独的辅助方法或在may_edit?方法中编写(我建议将其/它们作为模型方法)。理想情况下,控制器不应该是决定谁可以和不能执行这种事情的人。如果您打算在控制器中执行此操作,则可能需要查看:before_filter控制器的顶部,即:

:before_filter admin?, except [:foo, :bar]

我不确定您要在参数中传递哪个用户 id,但可以找到编辑/管理员或原始发帖人的 id - current_user 将作为 session[:user_id] 登录会话,原始发帖人可以是通过正在编辑的内容找到,因为它属于用户并且可以通过 ``User.find_by(content.user_id) 找到。

最后,您是在问如何查看所有用户角色的列表吗?如果是这样,您可以使用下拉菜单,但您必须在项目中的某个位置对它们进行硬编码,或者遍历每个用户并聚合他们的角色,尽管后者远非理想且效率非常低。

希望这会有所帮助,祝你好运!

于 2015-03-20T05:22:44.317 回答