CanCanCan 仅显示用户所属的模型实例
CanCanCan show only instance of model that user belongs to
我目前正在使用 Devise、CanCan 和 Rolify 来处理我的 rails 应用程序的身份验证和授权,我真的很难理解如何使 user
只能 :show
和 :update
user 所属模型的特定实例(又名我的 user
有一个 client_id
列,而不是相反)。
我为具有 :client
角色的 user
定义的 Abilities.rb
的更新部分工作正常,即如果 current_user.client_id = 3
那么他只能更新客户端Client.id = 3
,但是,同一用户可以看到 Client
模型的任何实例,我似乎无法理解如何限制它。
Ability.rb
...
if user.has_role? :client
can [:read, :update], [Property, Order], client_id: user.client_id
can [:read, :update], Owner
can :create, [Property, Order, Owner]
can :manage, User, id: user.id
can [:show, :update], Client, id: user.client_id
end
...
每个用户都没有一个index
全部Clients
,所以研究后我把can [:read, :update], Client, ..
改成了:show
但是用户仍然可以看到另一个clients
但是 :update
部分如果它工作正常,所以我真的很茫然。过去几个小时一直在谷歌上搜索并通读了所有 CanCan 文档,我承认它可能已解决但我无法弄清楚。
我试过从控制器端限制它,如下所示,但这也不起作用:
external/clients_controller.rb
class External::ClientsController < ApplicationController
load_and_authorize_resource
before_filter :client_only
def index
@clients = Client.paginate(page: params[:page], per_page: 15)
end
def show
@clients = Client.find(params[:id])
@client_users = User.where(client_id: params[:id])
@client_orders = Order.where(client_id: params[:id]).includes(:property, :owners)
can? :show, @clients
end
def edit
@clients = Client.find(params[:id])
respond_to do |format|
format.html { @clients.save }
format.js
end
end
def update
@clients = Client.find(params[:id])
@clients.update_attributes(client_params)
respond_to do |format|
format.html { if @clients.save
flash[:success] = "Client Updated Successfully"
redirect_to client_path(@clients)
else
render 'edit'
end
}
format.js
end
end
private
def client_params
params.require(:client).permit(:uuid, :company, :first_name, :last_name, :phone, :email, :address1, :address2, :city, :state, :zip, :notes)
end
def client_only
redirect_to root_path unless current_user.is_client?
end
end
因此,如果有人可以帮助我完全理解 CanCan 如何处理模型实例的基于角色的授权,那么我将不胜感激。提前致谢!
更新代码
删除了 external/clients_controller.rb
中的所有 @client
实例加载
class External::ClientsController < ApplicationController
load_and_authorize_resource
before_filter :client_only
def show
@client_users = User.where(client_id: params[:id])
@client_orders = Order.where(client_id: params[:id]).includes(:property, :owners).paginate(page: params[:page], per_page: 15).order("order_number DESC")
end
def edit
respond_to do |format|
format.html
format.js
end
end
def update
if params[:client][:state].blank?
params[:client][:state] = @client.try(:state)
end
@client.update_attributes(client_params)
respond_to do |format|
format.html { if @client.save
flash[:success] = "Client Updated Successfully"
redirect_to external_client_path(@client)
else
render 'edit'
end
}
format.js
end
end
private
def client_params
params.require(:client).permit(:uuid, :company, :first_name, :last_name, :phone, :email, :address1, :address2, :city, :state, :zip, :notes)
end
def client_only
redirect_to root_path unless current_user.is_client?
end
end
满ability.rb
class Ability
include CanCan::Ability
def initialize(user)
alias_action :show, :to => :view
alias_action :open_external_orders, :completed_external_orders, :to => :client_order_views
user ||= User.new
if user.has_role? :admin
can :manage, :all
can :assign_roles, User
else
can :read, :all
end
if user.has_role? :executive
can :manage, [Property, Deed, Mortgage, Order, Owner, Client, AttachedAsset, User]
cannot :assign_roles, User
end
if user.has_role? :management
can :manage, [Property, Deed, Mortgage, Order, Owner, Client, AttachedAsset]
can :read, User
can :manage, User, id: user.id
cannot :destroy, [Property, Order, Client, User]
end
if user.has_role? :analyst
can :manage, [Property, Deed, Mortgage, Order, Owner, Client, AttachedAsset]
can :manage, User, id: user.id
cannot :destroy, [Property, Order, Client, User]
end
if user.has_role? :it
can :manage, [Property, Deed, Mortgage, Order, Owner, Client, AttachedAsset]
can :manage, User, id: user.id
can :read, User
cannot :destroy, [Property, Order, Client, User]
end
if user.has_role? :client
can [:read, :update], Client, id: user.client_id
can [:read, :update, :client_order_views], [Property, Order], client_id: user.client_id
can [:read, :update], Owner
can :create, [Property, Order, Owner]
can :manage, User, id: user.id
end
end
end
CanCanCan 与 "increasing permissions" 合作。
每个规则都可以增加前一个。
如果你写:
can :show, User
can :edit, User
这两个权限将结合在一起,您将能够显示和编辑用户。
在您的 ability.rb 中,您定义 can :read, :all
您授予读取(显示和索引)所有对象的权限。
我建议你按照"increasing permisssions"的概念来写你的能力文件。这意味着您不会开始定义管理员的能力,而是在最后定义,将管理员需要的能力添加到您已经提供给每个人的能力中。
我目前正在使用 Devise、CanCan 和 Rolify 来处理我的 rails 应用程序的身份验证和授权,我真的很难理解如何使 user
只能 :show
和 :update
user 所属模型的特定实例(又名我的 user
有一个 client_id
列,而不是相反)。
我为具有 :client
角色的 user
定义的 Abilities.rb
的更新部分工作正常,即如果 current_user.client_id = 3
那么他只能更新客户端Client.id = 3
,但是,同一用户可以看到 Client
模型的任何实例,我似乎无法理解如何限制它。
Ability.rb
...
if user.has_role? :client
can [:read, :update], [Property, Order], client_id: user.client_id
can [:read, :update], Owner
can :create, [Property, Order, Owner]
can :manage, User, id: user.id
can [:show, :update], Client, id: user.client_id
end
...
每个用户都没有一个index
全部Clients
,所以研究后我把can [:read, :update], Client, ..
改成了:show
但是用户仍然可以看到另一个clients
但是 :update
部分如果它工作正常,所以我真的很茫然。过去几个小时一直在谷歌上搜索并通读了所有 CanCan 文档,我承认它可能已解决但我无法弄清楚。
我试过从控制器端限制它,如下所示,但这也不起作用:
external/clients_controller.rb
class External::ClientsController < ApplicationController
load_and_authorize_resource
before_filter :client_only
def index
@clients = Client.paginate(page: params[:page], per_page: 15)
end
def show
@clients = Client.find(params[:id])
@client_users = User.where(client_id: params[:id])
@client_orders = Order.where(client_id: params[:id]).includes(:property, :owners)
can? :show, @clients
end
def edit
@clients = Client.find(params[:id])
respond_to do |format|
format.html { @clients.save }
format.js
end
end
def update
@clients = Client.find(params[:id])
@clients.update_attributes(client_params)
respond_to do |format|
format.html { if @clients.save
flash[:success] = "Client Updated Successfully"
redirect_to client_path(@clients)
else
render 'edit'
end
}
format.js
end
end
private
def client_params
params.require(:client).permit(:uuid, :company, :first_name, :last_name, :phone, :email, :address1, :address2, :city, :state, :zip, :notes)
end
def client_only
redirect_to root_path unless current_user.is_client?
end
end
因此,如果有人可以帮助我完全理解 CanCan 如何处理模型实例的基于角色的授权,那么我将不胜感激。提前致谢!
更新代码
删除了 external/clients_controller.rb
@client
实例加载
class External::ClientsController < ApplicationController
load_and_authorize_resource
before_filter :client_only
def show
@client_users = User.where(client_id: params[:id])
@client_orders = Order.where(client_id: params[:id]).includes(:property, :owners).paginate(page: params[:page], per_page: 15).order("order_number DESC")
end
def edit
respond_to do |format|
format.html
format.js
end
end
def update
if params[:client][:state].blank?
params[:client][:state] = @client.try(:state)
end
@client.update_attributes(client_params)
respond_to do |format|
format.html { if @client.save
flash[:success] = "Client Updated Successfully"
redirect_to external_client_path(@client)
else
render 'edit'
end
}
format.js
end
end
private
def client_params
params.require(:client).permit(:uuid, :company, :first_name, :last_name, :phone, :email, :address1, :address2, :city, :state, :zip, :notes)
end
def client_only
redirect_to root_path unless current_user.is_client?
end
end
满ability.rb
class Ability
include CanCan::Ability
def initialize(user)
alias_action :show, :to => :view
alias_action :open_external_orders, :completed_external_orders, :to => :client_order_views
user ||= User.new
if user.has_role? :admin
can :manage, :all
can :assign_roles, User
else
can :read, :all
end
if user.has_role? :executive
can :manage, [Property, Deed, Mortgage, Order, Owner, Client, AttachedAsset, User]
cannot :assign_roles, User
end
if user.has_role? :management
can :manage, [Property, Deed, Mortgage, Order, Owner, Client, AttachedAsset]
can :read, User
can :manage, User, id: user.id
cannot :destroy, [Property, Order, Client, User]
end
if user.has_role? :analyst
can :manage, [Property, Deed, Mortgage, Order, Owner, Client, AttachedAsset]
can :manage, User, id: user.id
cannot :destroy, [Property, Order, Client, User]
end
if user.has_role? :it
can :manage, [Property, Deed, Mortgage, Order, Owner, Client, AttachedAsset]
can :manage, User, id: user.id
can :read, User
cannot :destroy, [Property, Order, Client, User]
end
if user.has_role? :client
can [:read, :update], Client, id: user.client_id
can [:read, :update, :client_order_views], [Property, Order], client_id: user.client_id
can [:read, :update], Owner
can :create, [Property, Order, Owner]
can :manage, User, id: user.id
end
end
end
CanCanCan 与 "increasing permissions" 合作。 每个规则都可以增加前一个。
如果你写:
can :show, User
can :edit, User
这两个权限将结合在一起,您将能够显示和编辑用户。
在您的 ability.rb 中,您定义 can :read, :all
您授予读取(显示和索引)所有对象的权限。
我建议你按照"increasing permisssions"的概念来写你的能力文件。这意味着您不会开始定义管理员的能力,而是在最后定义,将管理员需要的能力添加到您已经提供给每个人的能力中。