关于 implement-authorization
implement-authorization 是面向 Rails 开发者的授权实现与审查技能,涵盖 Pundit 和 CanCanCan。它强调复用现有框架、使用策略对象、限定查询范围,并验证不同角色的权限。
主要功能
- 01识别并沿用现有授权框架
- 02使用 Pundit 策略或 CanCanCan Ability
- 03在控制器动作中执行授权
- 04为索引查询添加权限范围
- 05覆盖角色的策略与请求测试
- 06输出拒绝访问的验证记录
适用场景
- 01为 Rails 资源实现按角色授权
- 02审查控制器是否遗漏授权调用
- 03限制索引页仅显示可访问记录
- 04验证未授权请求及其 HTTP 响应
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ igmarin/ rails-agent-skills --skill implement-authorization安装后在 Claude Code 中输入/implement-authorization确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
EXAMPLES.mdreferences/output-style.mdworkflow.md详细介绍
实现授权
快速参考
| Gem | 模式 | 适用场景 |
|---|---|---|
| Pundit | 显式策略类 | 复杂的资源级规则 |
| CanCanCan | 集中式 Ability 类 | 简单的基于角色的权限 |
核心流程
实施工作流
- 检查现有授权机制 — 复用已安装的策略框架;仅当任务需要新框架且项目惯例允许时,才添加
pundit或cancancan - 仅在需要时生成基础文件 — 只有在不存在受支持的框架且项目允许使用生成器时,才运行 Gem 的安装程序(
rails g pundit:install或rails g cancan:ability);否则,使用检测到的框架继续操作,不调用生成器 - 定义策略/能力 — 创建策略类(Pundit)或填充 Ability 类(CanCanCan);始终使用策略对象,切勿在控制器中内联授权逻辑
- 在控制器中授权 — 在每个操作中调用
authorize @record(Pundit)或authorize! :action, @record(CanCanCan) - 验证授权 — 在浏览器或控制台中尝试未授权操作,并确认它按预期引发
Pundit::NotAuthorizedError或CanCan::AccessDenied;使用已持久化的记录(例如User.create!),而非尚未保存的记录 - 限定查询范围 — 在 index 操作中使用
policy_scope(Model)或accessible_by(current_ability) - 测试所有角色 — 编写策略规格和请求规格,覆盖管理员、所有者和访客;检查具体权限,绝不能只检查是否存在
模式
Pundit
class PostPolicy < ApplicationPolicy
def update?
user.admin? || record.user_id == user.id
end
end
CanCanCan
class Ability
include CanCan::Ability
def initialize(user)
can :update, Post, user_id: user.id
can :manage, :all if user.admin?
end
end
故障排查
| 错误 | 可能原因 | 修复方法 |
|---|---|---|
Pundit::NotDefinedError | 未找到该记录对应的策略类 | 创建继承自 ApplicationPolicy 的 app/policies/model_policy.rb |
Pundit::AuthorizationNotPerformedError | 控制器操作中未调用 authorize | 在操作中添加 authorize @record,或添加 after_action :verify_authorized 以捕获遗漏 |
意外引发 CanCan::AccessDenied | 能力规则与当前用户/角色不匹配 | 在控制台中检查 current_ability.can?(:action, @record),以调试规则评估 |
测试
在策略规格和请求规格中覆盖所有角色(管理员、所有者、访客)。
最简 Pundit 策略规格
RSpec.describe PostPolicy do
subject { described_class.new(user, post) }
let(:post) { create(:post, user: owner) }
let(:owner) { create(:user) }
context 'as admin' do
let(:user) { create(:user, :admin) }
it { is_expected.to permit_action(:update) }
end
context 'as owner' do
let(:user) { owner }
it { is_expected.to permit_action(:update) }
end
context 'as guest' do
let(:user) { create(:user) }
it { is_expected.not_to permit_action(:update) }
end
end
输出样式
实现或审查授权时,输出文件 answer.md 必须包含:
- 手动验证拒绝的操作 — 设置专门的章节,提供实际的 Rails 控制台输出;或者明确标示未运行,并说明尝试未授权操作时引发的授权异常。始终使用已持久化的记录(
User.create!、Post.create!),绝不使用尚未保存的记录。 - HTTP 和策略验证 — 提供具体的
curl请求或控制器测试命令,并注明拒绝访问时预期的 HTTP 响应代码(例如403 Forbidden或302 Found)。 - 语言 — 除非明确要求使用其他语言,否则使用英语。
完整格式示例(包括 Pundit 和 CanCanCan 控制台输出模板)请参阅 references/output-style.md。
集成
| 技能 | 何时串联 |
|---|---|
| write-tests | 实现授权测试时。 |
扩展资源(渐进式披露)
仅在需要相关内容时加载以下文件:
- EXAMPLES.md — 需要完整的 Pundit 或 CanCanCan 实施示例,而非内联示例时使用
- references/workflow.md — 需要授权实施工作流的分步示意图时使用
- references/output-style.md — 需要控制台验证输出的完整格式模板时使用
评论
支持 Markdown