返回 Skill 列表
extension
分类: 开发与工程无需 API Key

"PocketBase API Rules"

PocketBase访问控制的API规则和过滤表达式。在设置权限、编写过滤表达式、配置谁可以访问什么内容或调试403/404响应时使用。涵盖了所有5种规则类型、过滤语法、操作符、请求/集合宏以及字段修饰符。

person作者: jakexiaohubgithub

PocketBase API Rules & Filter Expressions

Rule Types

Each collection has 5 rule types. Each rule is a filter expression that must evaluate to true for the request to proceed.

| Rule | Controls | Locked = | Empty string = | |------|----------|----------|----------------| | List | GET /api/collections/{name}/records | superusers only | everyone can list | | View | GET /api/collections/{name}/records/{id} | superusers only | everyone can view | | Create | POST /api/collections/{name}/records | superusers only | everyone can create | | Update | PATCH /api/collections/{name}/records/{id} | superusers only | everyone can update | | Delete | DELETE /api/collections/{name}/records/{id} | superusers only | everyone can delete |

Critical: null/locked means only superusers can perform the action (regular users and guests are denied). Empty string "" means EVERYONE including guests. Superusers always bypass API rules entirely — see below.

Superuser Bypass

Superusers (formerly admins) always bypass API rules. Rules only apply to regular auth records and guests.

Filter Syntax

Operators

| Operator | Meaning | Example | |----------|---------|---------| | = | Equal | status = "active" | | != | Not equal | status != "draft" | | > | Greater than | count > 5 | | >= | Greater or equal | count >= 5 | | < | Less than | count < 10 | | <= | Less or equal | count <= 10 | | ~ | LIKE (contains) | title ~ "hello" | | !~ | NOT LIKE | title !~ "spam" | | ?= | Any/has (array contains) | tags ?= "TAG_ID" | | ?!= | None (array not contains) | tags ?!= "TAG_ID" | | ?> | Any greater than | scores ?> 90 | | ?>= | Any greater or equal | scores ?>= 90 | | ?< | Any less than | scores ?< 10 | | ?<= | Any less or equal | scores ?<= 10 | | ?~ | Any LIKE | emails ?~ "@gmail.com" | | ?!~ | Any NOT LIKE | emails ?!~ "@test.com" |

Critical: use ?= (not =) for multi-valued fields (multi-select, multi-relation, multi-file). = checks the raw JSON string, ?= checks individual values.

Logical Operators

status = "active" && author = @request.auth.id
status = "active" || status = "featured"

Parentheses for grouping: (a = 1 || b = 2) && c = 3

Values

  • Strings: "value" or 'value'
  • Numbers: 123, 45.67
  • Booleans: true, false
  • null — empty/missing value
  • Identifiers: field names, macros

Request Macros (@request.*)

Access the current request context in rules:

| Macro | Type | Description | |-------|------|-------------| | @request.auth.id | string | Current auth record ID (empty if guest) | | @request.auth.email | string | Current auth record email | | @request.auth.verified | bool | Whether email is verified | | @request.auth.collectionId | string | Auth collection ID | | @request.auth.collectionName | string | Auth collection name | | @request.auth.* | any | Any field from the auth record | | @request.body.fieldName | any | Field value from request body | | @request.query.paramName | string | URL query parameter | | @request.headers.name | string | Request header (lowercase key) | | @request.method | string | HTTP method (GET/POST/PATCH/DELETE) |

Auth record relations

You can traverse relations on the auth record:

@request.auth.team.owner = @request.auth.id

Collection Macros (@collection.*)

Cross-collection lookups without explicit joins:

@collection.memberships.user ?= @request.auth.id &&
@collection.memberships.team ?= team

This checks if a record exists in the memberships collection where the user matches the current auth user and the team matches the current record's team field.

Note: @collection.* performs an implicit EXISTS subquery. It's powerful but can be slow on large datasets — add indexes.

Field Modifiers

Use in create/update rules to validate specific field behaviors:

| Modifier | Works on | Description | |----------|----------|-------------| | :isset | @request.body.* | True if the field was sent in the request (even if empty) | | :changed | record field | True if the field value differs from current stored value (update only) | | :length | string/array | Returns the length | | :each | array | Applies the condition to each element | | :lower | string | Lowercased value |

Examples

// Only allow changing status if user is owner
status:changed = false || author = @request.auth.id

// Prevent setting role on create
@request.body.role:isset = false

// Require at least 2 tags
@request.body.tags:length >= 2

// Check each tag is from allowed list
@request.body.tags:each ?= @collection.allowed_tags.id

Datetime Macros

| Macro | Example output | |-------|----------------| | @now | 2024-01-15 10:30:00.000Z | | @second | 2024-01-15 10:30:00.000Z | | @minute | 2024-01-15 10:30:00.000Z | | @hour | 2024-01-15 10:00:00.000Z | | @day | 2024-01-15 00:00:00.000Z | | @month | 2024-01-01 00:00:00.000Z | | @year | 2024-01-01 00:00:00.000Z | | @todayStart | 2024-01-15 00:00:00.000Z | | @todayEnd | 2024-01-15 23:59:59.999Z | | @monthStart | 2024-01-01 00:00:00.000Z | | @monthEnd | 2024-01-31 23:59:59.999Z | | @yearStart | 2024-01-01 00:00:00.000Z | | @yearEnd | 2024-12-31 23:59:59.999Z |

Arithmetic: @now - 7d, @now + 1h, @now - 30m

geoDistance()

For location-based filtering:

geoDistance(lat, lon, 40.7128, -74.0060) <= 10000

Arguments: geoDistance(latField, lonField, targetLat, targetLon) — returns meters.

Common Patterns

Owner-only access

// View/Update/Delete rule:
author = @request.auth.id

Authenticated users only

@request.auth.id != ""

Verified users only

@request.auth.verified = true

Role-based access

@request.auth.role = "admin" || author = @request.auth.id

Team membership

@collection.team_members.user ?= @request.auth.id &&
@collection.team_members.team ?= team

Public read, owner write

// List/View: ""  (empty = everyone)
// Create: @request.auth.id != ""
// Update/Delete: author = @request.auth.id

Prevent field modification

// Update rule: prevent changing `owner` after creation
owner:changed = false

Time-limited access

expires > @now