用途
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:编写策略 spec(RED)
- 步骤 2:运行 spec(失败)
- 步骤 3:实现策略
- 步骤 4:运行 spec(GREEN)
- 步骤 5:将策略添加到控制器
- 步骤 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 错误