跳转到内容

API 规则与访问控制

PocketBase 的 API 规则(API Rules)系统让你能够以声明式的方式控制数据访问权限。每个集合都有 5 个独立的规则,对应不同的 API 操作。

规则对应操作说明
viewGET /api/…/:id查看单条记录
listGET /api/…列表查询
createPOST /api/…创建新记录
updatePATCH /api/…/:id更新记录
deleteDELETE /api/…/:id删除记录

规则是布尔表达式,返回 true 允许访问,false 拒绝访问。

规则表达式 → 评估为 true 或 false
true → 允许所有
false → 拒绝所有
空字符串 "" → 允许所有(等同于 true)
变量类型说明
@request.auth.idstring当前登录用户的 ID
@request.auth.emailstring当前登录用户的邮箱
@request.auth.usernamestring当前登录用户的用户名
@request.auth.verifiedbool当前登录用户是否已验证邮箱
@request.auth.<field>any当前登录用户的自定义字段
@request.methodstring请求方法 (GET/POST/PATCH/DELETE)
@request.query.<param>any查询参数值
@request.data.<field>any请求数据字段值
@request.idstring请求的记录 ID (update/delete 时)
变量类型说明
@collection.idstring当前集合的 ID
@collection.namestring当前集合的名称
变量类型说明
@nowstring当前时间戳 (ISO)
@dateobject日期时间辅助函数

允许所有用户(包括未登录)访问:

{
"view": "",
"list": "",
"create": "",
"update": "",
"delete": ""
}

仅管理员可以访问:

{
"view": "id = @request.auth.id && @request.auth.role = 'admin'",
"list": "id = @request.auth.id && @request.auth.role = 'admin'",
"create": "id = @request.auth.id && @request.auth.role = 'admin'",
"update": "id = @request.auth.id && @request.auth.role = 'admin'",
"delete": "id = @request.auth.id && @request.auth.role = 'admin'"
}

任何已登录用户都可以操作:

{
"view": "@request.auth.id != ''",
"list": "@request.auth.id != ''",
"create": "@request.auth.id != ''",
"update": "@request.auth.id != ''",
"delete": "@request.auth.id != ''"
}

用户只能操作自己创建的记录:

{
"view": "owner = @request.auth.id || id = @request.auth.id",
"list": "owner = @request.auth.id || id = @request.auth.id",
"create": "@request.auth.id != ''",
"update": "owner = @request.auth.id || id = @request.auth.id",
"delete": "owner = @request.auth.id || id = @request.auth.id"
}
{
"view": "status = 'published' || author = @request.auth.id || @request.auth.role = 'admin'",
"list": "status = 'published' || author = @request.auth.id || @request.auth.role = 'admin'",
"create": "@request.auth.id != ''",
"update": "author = @request.auth.id || @request.auth.role = 'admin'",
"delete": "author = @request.auth.id || @request.auth.role = 'admin'"
}

说明:

  • 已发布的文章所有人可见
  • 作者可以查看自己的草稿
  • 管理员可以查看和编辑所有文章
{
"view": "owner = @request.auth.id",
"list": "owner = @request.auth.id",
"create": "@request.auth.id != ''",
"update": "owner = @request.auth.id",
"delete": "owner = @request.auth.id"
}
{
"view": "status = 'approved'",
"list": "status = 'approved'",
"create": "@request.auth.id != ''",
"update": "author = @request.auth.id || @request.auth.role = 'admin'",
"delete": "author = @request.auth.id || @request.auth.role = 'admin'"
}
{
"view": "customer = @request.auth.id || @request.auth.role = 'admin'",
"list": "customer = @request.auth.id || @request.auth.role = 'admin'",
"create": "@request.auth.id != ''",
"update": "@request.auth.role = 'admin'",
"delete": "@request.auth.role = 'admin'"
}
{
"view": "tenantId = @request.auth.tenantId || @request.auth.role = 'admin'",
"list": "tenantId = @request.auth.tenantId || @request.auth.role = 'admin'",
"create": "@request.auth.id != ''",
"update": "tenantId = @request.auth.tenantId || @request.auth.role = 'admin'",
"delete": "tenantId = @request.auth.tenantId || @request.auth.role = 'admin'"
}
运算符说明示例
=等于status = 'active'
!=不等于status != 'deleted'
>大于views > 100
>=大于等于views >= 100
<小于price < 1000
<=小于等于price <= 1000
~包含title ~ 'keyword'
!~不包含title !~ 'spam'
// AND (空格分隔)
"status = 'published' && featured = true";
// OR
"status = 'draft' || status = 'archived'";
// 分组
"(status = 'published' && featured = true) || author = @request.auth.id";
// NOT
"!(status = 'deleted')";
// 字段为空
"publishedAt = null";
// 字段不为空
"publishedAt != null";
// 字段为空字符串
"title = ''";
// tags 包含某个值
"tags ~ 'javascript'";
// categories 是多选字段,包含某个值
"categories ~ 'tech'";
// 发布时间在未来
"publishedAt > @now";
// 发布时间在过去
"publishedAt <= @now";
// 使用日期函数
"@date.before(@now, publishedAt)";
// 7 天内的记录
"created > @date.now(-7)";
// 关联的用户已验证
"expand.author.verified = true";
// 文章分类已激活
"category.expand.status = 'active'";

在 Auth Collection 中添加 role 字段:

{
"name": "role",
"type": "select",
"options": {
"values": ["guest", "user", "author", "admin"],
"default": "user"
}
}
// 只有作者和管理员可以创建
"create": "@request.auth.role = 'author' || @request.auth.role = 'admin'"
// 管理员可以删除所有,作者只能删除自己的
"delete": "@request.auth.role = 'admin' || (@request.auth.role = 'author' && author = @request.auth.id)"
// 超级管理员
"update": "@request.auth.role = 'superadmin'"
// 分级权限
"create": "(@request.auth.role = 'author' && status = 'draft') || @request.auth.role = 'admin'"
// 发布权限仅管理员
"update": "!(status = 'published' && @request.auth.role != 'admin') || author = @request.auth.id"
// 只允许已验证用户操作
"create": "@request.auth.verified = true"
"update": "@request.auth.verified = true || id = @request.auth.id"
// 注册 24 小时后才能发布
"create": "(@request.auth.created < @date.now(-24) || @request.auth.role = 'admin')"
// 用户只能操作自己部门的记录
"view": "department = @request.auth.department || @request.auth.role = 'admin'"
// 管理员可以操作所有,用户只能操作自己的
"update": "@request.auth.role = 'admin' || id = @request.auth.id"
// 父级所有者
"parent.owner = @request.auth.id || @request.auth.role = 'admin'"
// create 规则允许所有
"create": "@request.auth.id != ''"
// 使用 Hooks 强制设置 owner
onRecordCreateRequest((e) => {
e.record.set("owner", e.authInfo.id);
});
// 不允许用户修改自己的角色
"update": "!(@request.data.role) || @request.auth.role = 'admin'"
// 在前端使用确认,后端可以添加额外检查
onRecordBeforeDeleteRequest((e) => {
const count = e.dao.findRecordsByExpr(
e.record.collection(),
`id = '${e.record.id}'`,
);
if (count.length > 100) {
throw new BadRequestError("Cannot delete more than 100 records");
}
});
  1. 使用 Admin UI 的「规则测试器」
  2. 创建测试账号,不同角色分别测试
  3. 使用浏览器开发者工具查看请求
// 错误:缺少空格
"status='published'"; // ❌
"status = 'published'"; // ✓
// 错误:单引号嵌套
"status = 'it's ok'"; // ❌
"status = 'it''s ok'"; // ✓ 使用双单引号转义
// 错误:数字比较字符串
"views > '100'"; // ❌
"views > 100"; // ✓
// 错误:未定义字段
"@request.auth.role = 'admin'"; // ❌ 如果没有 role 字段

将最可能拒绝的条件放在前面:

// 好的做法:先检查最严格的条件
"@request.auth.role = 'admin' || owner = @request.auth.id";
// 避免:复杂的嵌套
"((status = 'published' && featured = true) || author = @request.auth.id) || @request.auth.role = 'admin'";

确保规则中使用的字段有索引:

{
"name": "author_idx",
"type": "index",
"options": {
"fields": ["author"]
}
}
  1. 最小权限原则:默认拒绝,明确允许
  2. 规则可读性:使用有意义的字段名和注释
  3. 测试覆盖:为每种角色编写测试
  4. 审计日志:记录敏感操作
  5. 定期审查:定期检查规则是否符合需求
  6. 文档化:在代码或文档中记录规则意图
// 旧代码:在业务逻辑中检查
if (user.role !== 'admin') {
throw new Error('Forbidden');
}
// 新方式:使用规则
"delete": "@request.auth.role = 'admin'"
// 规则处理简单权限
"create": "@request.auth.id != ''"
// Hooks 处理复杂业务逻辑
onRecordCreateRequest((e) => {
if (e.record.get("type") === "premium" && !hasSubscription(e.authInfo)) {
throw new BadRequestError("Premium subscription required");
}
});

规则在 API 请求处理前执行,先于 Hooks。如果规则检查失败,请求会被直接拒绝,不会到达 Hooks。

Q: 如何实现”仅本人和管理员可见”?

Section titled “Q: 如何实现”仅本人和管理员可见”?”
{
"view": "id = @request.auth.id || @request.auth.role = 'admin'",
"list": "id = @request.auth.id || @request.auth.role = 'admin'"
}
{
"list": "userId = @request.auth.id"
}

不能直接,但可以通过 expand 访问关联字段。复杂场景建议使用 Hooks。

添加临时令牌字段,在规则中检查:

{
"view": "token != '' && tokenExpire > @now || id = @request.auth.id"
}