基于部门的 Rails CanCanCan 资源能力
Posted
技术标签:
【中文标题】基于部门的 Rails CanCanCan 资源能力【英文标题】:Rails CanCanCan resource abilities based on department 【发布时间】:2019-06-28 13:31:44 【问题描述】:我有两种用户类型 Admin 和 Normal User
我有以下部门
前台(例如,id 为 1) 后台(例如,id 为 2) 管理员(例如,id 为 3)我有一个名为 Entry 的模型,它采用 user_id、department_id、customer_id
管理员用户对所有部门和所有条目
完全控制CRUD普通用户是为各个部门创建的,并且 CRU 可以控制各个部门的条目
当我从 普通用户(例如,id 为 2)帐户创建 条目 时,我得到了正确的 customer_id、department_id、user_id 集 em> 在表中。此用户的权限只有一个条目 can_create_entry(current_user.id, customer_id, department_id) 例如,(1, 1, 2) 用于前台普通用户帐户。
当我从 Admin(例如,id 为 1)帐户创建 entry 时,我得到 customer_id、department_id、user_id 为 (1,1,1)在表中,我尝试为 id 为 2 的后台部门创建一个条目。
当我检查 Admin 用户的能力列表时;我发现条目能力有重复项,即,
#<CanCan::Rule:0x0000000b61fd18 @match_all=false, @base_behavior=true, @actions=[:create], @subjects=[Entry(Table doesn't exist)], @conditions=:user_id=>1, :customer_id=>2, :department_id=>1, @block=nil>
#<CanCan::Rule:0x0000000b61fd18 @match_all=false, @base_behavior=true, @actions=[:create], @subjects=[Entry(Table doesn't exist)], @conditions=:user_id=>1, :customer_id=>2, :department_id=>2, @block=nil>
#<CanCan::Rule:0x0000000b61fd18 @match_all=false, @base_behavior=true, @actions=[:create], @subjects=[Entry(Table doesn't exist)], @conditions=:user_id=>1, :customer_id=>2, :department_id=>3, @block=nil>
对于普通用户我只有一个条目
#<CanCan::Rule:0x0000000b61fd18 @match_all=false, @base_behavior=true, @actions=[:create], @subjects=[Entry(Table doesn't exist)], @conditions=:user_id=>2, :customer_id=>2, :department_id=>1, @block=nil>
请帮我解决管理员角色的问题。
已编辑: ability_base.rb
class AbilityBase
include CanCan::Ability
...
def can_read_entries(customer_id, department_id)
can :read, Entry, :customer_id => customer_id, :department_id => department_id
end
def can_create_entries(customer_id, department_id,user_id)
can :create, Entry, :customer_id => customer_id, :department_id => department_id, :user_id => user_id
end
def can_update_entries(customer_id, department_id, user_id)
can :update, Entry, :customer_id => customer_id, :department_id => department_id, :user_id => user_id
end
def can_destroy_entries(customer_id, department_id)
can :destroy, Entry, :customer_id => customer_id, :department_id => department_id
end
...
end
user_ability.rb
class UserAbility < AbilityBase
def initialize(current_user)
if current_user
user_department_type_names =
@customer = current_user.customer
@user_type = current_user.user_type
current_user_dept = current_user.departments
@user_department_ids = current_user_dept.collect(&:id)
@user_department_type_ids = current_user_dept.collect |dept|
dept_type = dept.department_type
user_department_type_names["#dept_type.type_name"] = dept.id
dept_type.id
...
if user_department_type_names.has_key?("FRONT_OFFICE")
dept_id = user_department_type_names["FRONT_OFFICE"]
if @user_type == "NORMAL_USER"
can_read_entries(customer.id, dept_id)
can_create_entries(customer.id, dept_id, user_id)
can_update_entries(customer.id, dept_id, user_id)
elsif @user_type == "ADMIN"
can_read_entries(customer.id, dept_id)
can_create_entries(customer.id, dept_id, user_id)
can_update_entries(customer.id, dept_id, user_id)
can_destroy_entries(customer.id, dept_id)
end
elsif user_department_type_names.has_key?("BACK_OFFICE")
dept_id = user_department_type_names["BACK_OFFICE"]
if @user_type == "NORMAL_USER"
can_read_entries(customer.id, dept_id)
can_create_entries(customer.id, dept_id, user_id)
can_update_entries(customer.id, dept_id, user_id)
elsif @user_type == "ADMIN"
can_read_entries(customer.id, dept_id)
can_create_entries(customer.id, dept_id, user_id)
can_update_entries(customer.id, dept_id, user_id)
can_destroy_entries(customer.id, dept_id)
end
elsif user_department_type_names.has_key?("ADMIN")
dept_id = user_department_type_names["ADMIN"]
if @user_type == "NORMAL_USER"
can_read_entries(customer.id, dept_id)
can_create_entries(customer.id, dept_id, user_id)
can_update_entries(customer.id, dept_id, user_id)
elsif @user_type == "ADMIN"
can_read_entries(customer.id, dept_id)
can_create_entries(customer.id, dept_id, user_id)
can_update_entries(customer.id, dept_id, user_id)
can_destroy_entries(customer.id, dept_id)
end
end
...
end
end
end
【问题讨论】:
您的 userability.rb 文件在哪里?将其添加到问题中 已相应编辑 【参考方案1】:我为此使用了一些不同的方法:
class UserAbility
include CanCan::Ability
attr_accessor :user
def initialize(user)
@user = user
can :read, Entry, do |entry|
is_admin || (is_normal_user && Entry.where(id, entry.id, customer_id: @user.customer_id, dept_id: user.departments.ids).exists?
end
private
def is_normal_user
user.user_type == 'NORMAL_USER'.freeze
end
def is_admin
user.user_type == 'ADMIN'.freeze
end
end
当然只是一个模板
【讨论】:
感谢您的快速回复。我会试试这个。我遇到的问题是,当我们创建条目记录时,该记录应该具有相应的部门 ID。对于普通用户,分配给他一个部门;这里没问题。对于管理员,将分配多个部门;因此,加载了多个部门能力记录。并且当管理员创建条目记录时,总是可以分配能力列表中的第一个部门 id 而不是我打算做的。 当您创建条目时,您需要从用户记录中传递 dept_id 和 customer。 你不应该使用 cancan 来创建记录。 如果您是管理员,只需在表单中将其 deps 列表显示为选项即可。 注意到您的回复。谢谢以上是关于基于部门的 Rails CanCanCan 资源能力的主要内容,如果未能解决你的问题,请参考以下文章
Rails 设计角色模型和 CanCanCan - 定义能力
Rails、Devise、Role Model 和 CanCanCan - 定义能力