gpt4 book ai didi

ruby-on-rails - 在Pundit中实现范围

转载 作者:行者123 更新时间:2023-12-04 13:27:06 25 4
gpt4 key购买 nike

我正在使用Pundit gem(带有Devise和Rolify)来限制基于登录用户角色的信息访问。

目前,我为用户模型定义了三个角色:Admin,Client Admin和Customer Admin。

用户属于客户。
客户has_many个用户。

索引客户模型时,我已经成功实现了Pundit策略。管理员和客户端管理员可以查看所有客户。客户管理员只能看到他们的OWN记录。

问题出在我试图限制Customer Controller 的 show 方法时。管理员和客户端管理员可以查看所有客户。但是,客户管理员只能看到自己的记录。但就目前情况而言,客户管理员可以在URL中输入任何ID并查看任何客户记录。

我在范围界定上很模糊。我的理解是,政策方法(即索引?和显示?)将限制WHO可以执行这些操作,而范围界定方法将限制哪些记录。我在为上述情况编写正确的范围时遇到了麻烦。

这是客户 Controller :

class CustomersController < ApplicationController
before_action :set_customer, only: [:show, :edit, :update, :destroy]
after_action :verify_authorized

# GET /customers
# GET /customers.json
def index
@customers = policy_scope(Customer)
authorize Customer
end

# GET /customers/1
# GET /customers/1.json
def show
authorize @customer
end

# GET /customers/new
def new
@customer = Customer.new
authorize @customer
end

# GET /customers/1/edit
def edit
authorize @customer
end

# POST /customers
# POST /customers.json
def create
@customer = Customer.new(customer_params)
authorize @customer

respond_to do |format|
if @customer.save
format.html { redirect_to @customer, notice: 'Customer was successfully created.' }
format.json { render :show, status: :created, location: @customer }
else
format.html { render :new }
format.json { render json: @customer.errors, status: :unprocessable_entity }
end
end
end

# PATCH/PUT /customers/1
# PATCH/PUT /customers/1.json
def update
authorize @customer
respond_to do |format|
if @customer.update(customer_params)
format.html { redirect_to @customer, notice: 'Customer was successfully updated.' }
format.json { render :show, status: :ok, location: @customer }
else
format.html { render :edit }
format.json { render json: @customer.errors, status: :unprocessable_entity }
end
end
end

# DELETE /customers/1
# DELETE /customers/1.json
def destroy
authorize @customer
@customer.destroy
respond_to do |format|
format.html { redirect_to customers_url, notice: 'Customer was successfully destroyed.' }
format.json { head :no_content }
end
end

private
# Use callbacks to share common setup or constraints between actions.
def set_customer
@customer = Customer.find(params[:id])
end

# Never trust parameters from the scary internet, only allow the white list through.
def customer_params
params.require(:customer).permit(:name, :parent_customer_id, :customer_type, :active, :currency)
end
end

这是客户政策:
class CustomerPolicy < ApplicationPolicy

def index?
# Admins, ClientAdmins, and CustomerAdmins can index customers (see Scope class for filters)
@user.has_role? :admin or @user.has_role? :client_admin or @user.has_role? :customer_admin
end

def show?
# Admins, ClientAdmins, and CustomerAdmins can see any customer details
@user.has_role? :admin or @user.has_role? :client_admin or @user.has_role? :customer_admin
end

def update?
# Only Admins and ClientAdmins can update customer details
@user.has_role? :admin or @user.has_role? :client_admin
end

def destroy?
@user.has_role? :admin or @user.has_role? :client_admin
end

class Scope < Struct.new(:user, :scope)
def resolve
if (user.has_role? :admin or user.has_role? :client_admin)
# Admins and ClientAdmins can see all Customers
scope.where(:parent_id => nil)
elsif user.has_role? :customer_admin
# Customer Admins can only see their own Customer
scope.where(:id => user.customer) # THIS DOES NOT APPEAR TO GET INVOKED BY THE SHOW METHOD OF THE CONTROLLER
end
end

def show?
# NOT SURE WHAT TO PUT IN HERE
end
end
end

成功!!感谢railscard给我的领先优势,诀窍是修改演出吗?客户策略文件中的方法如下所示:
  def show?
# Admins, ClientAdmins, and CustomerAdmins can see any customer details
# Students cannot see customer details

return true if user.has_role?(:admin) || user.has_role?(:client_admin)
return true if user.customer_id == @record.id && user.has_role?(:customer_admin)
false
end

请注意,我必须使用@record实例变量,因为那是应用程序策略类用来引用authorize方法传递的记录的方式。

谢谢!!

最佳答案

我认为您不需要限制show操作访问的范围。

def show?
return true if user.has_role? :admin || user.has_role? :client_admin
return true if user.customer_id == customer.id && user.has_role? :customer_admin
false
end

Pundit范围通常用于获取用户有权访问的记录列表。如果是 show方法(或 Controller 中的其他任何方法,在其中调用 authorize),Pundit会使用当前用户和给定的客户实例化策略类,然后简单地调用 show?方法来检查用户权限,即 CustomerPolicy.new(current_user, @customer).show?

关于ruby-on-rails - 在Pundit中实现范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24616608/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com