SuperAPI AI 工具集

authorization-pundit

安全与审计

查看项目

更新于 10-16 04:01

技能介绍

用途

authorization-pundit 用于在 Rails 8 中实现基于策略的授权(Pundit),对资源访问进行控制。适用场景包括:添加授权规则、检查权限、限制操作等。

主要能力

Pundit 提供基于策略的授权方式,具有以下特点:

  • 纯 Ruby 策略对象
  • 约定优于配置
  • 易于测试
  • 支持集合的 scoped 查询
  • 可与任何认证系统配合

安装与生成

在 Gemfile 中添加 Pundit:

bundle add pundit

生成基础文件:

bin/rails generate pundit:install

为模型生成策略:

bin/rails generate pundit:policy Event

项目结构

app/
├── policies/
│   ├── application_policy.rb    # Base policy
│   ├── event_policy.rb
│   ├── vendor_policy.rb
│   └── user_policy.rb
spec/policies/
├── event_policy_spec.rb
├── vendor_policy_spec.rb
└── user_policy_spec.rb

TDD 工作流

授权开发进度:

  1. 步骤 1:编写策略 spec(RED)
  2. 步骤 2:运行 spec(失败)
  3. 步骤 3:实现策略
  4. 步骤 4:运行 spec(GREEN)
  5. 步骤 5:将策略添加到控制器
  6. 步骤 6:测试集成

基础策略

# app/policies/application_policy.rb
class ApplicationPolicy
  attr_reader :user, :record

  def initialize(user, record)
    @user = user
    @record = record
  end

  # Default: deny all
  def index?
    false
  end

  def show?
    false
  end

  def create?
    false
  end

  def new?
    create?
  end

  def update?
    false
  end

  def edit?
    update?
  end

  def destroy?
    false
  end

  class Scope
    def initialize(user, scope)
      @user = user
      @scope = scope
    end

    def resolve
      raise NotImplementedError, "Define #resolve in #{self.class}"
    end

    private

    attr_reader :user, :scope
  end
end

策略实现

有四种策略模式可用(完整实现见 policies.md):

  • 基础策略(Basic Policy):基于所有者的访问,Scope 按 account_id 过滤
  • 角色策略(Role-Based Policy):组合 owner?、admin?、member_or_above? 谓词;admin 在 Scope 中可见全部
  • 带状态条件的策略(Policy with State Conditions):根据记录状态(locked?、destroyable?、can_cancel?)控制操作
  • 无记录策略(Headless Policy):策略不绑定到某条记录(如仪表盘、管理面板)

policies.md 中还包含:

  • 允许属性(Permitted Attributes):基于角色的 permitted_attributes,用于 strong params
  • 嵌套资源策略(Nested Resource Policies):委托到父资源策略,例如 EventPolicy.new(user, record.event).show?

控制器集成

controller-integration.md 提供以下完整示例:

  • ApplicationController 设置,包括 include Pundit::Authorization、after_action :verify_authorized 与 rescue_from Pundit::NotAuthorizedError
  • 完整 CRUD 控制器,使用 authorize @event 和 policy_scope(Event)
  • 自定义操作授权:authorize @event, :publish?
  • 对公开页面使用 skip_after_action 跳过授权

视图集成

views-and-testing.md 中包含:

  • 使用 policy(@event).edit? 进行 ERB 条件渲染
  • 使用 EventPolicy.new(@user, @event) 集成 ViewComponent

测试

views-and-testing.md 中包含:

  • 使用 permissions :show? 块与 permit/not_to permit 匹配器的策略 spec
  • pundit-matchers gem 的用法,使用 permit_actions / forbid_actions
  • 测试 HTTP 状态与重定向行为的 request spec
  • I18n 错误消息配置与自定义 rescue_from 处理器

检查清单

  • 首先编写策略 spec(RED)
  • 策略继承自 ApplicationPolicy
  • 为集合定义 Scope
  • 控制器使用 authorize 与 policy_scope
  • 启用 verify_authorized after_action
  • 视图使用 policy(@record).action?
  • 配置错误处理
  • 在 Scope 中强制多租户
  • 所有 spec 为 GREEN

参考文件

  • policies.md:策略模式:基础、角色、状态条件、无记录、嵌套、允许属性
  • controller-integration.md:ApplicationController 设置、CRUD、自定义操作、跳过授权
  • views-and-testing.md:ERB 视图、ViewComponent、策略 spec、pundit-matchers、request spec、I18n 错误