2.6 KiB
2.6 KiB
title, impact, impactDescription, tags
| title | impact | impactDescription | tags |
|---|---|---|---|
| Use @collection for Cross-Collection Lookups | HIGH | Enables complex authorization without denormalization | api-rules, security, cross-collection, relations |
Use @collection for Cross-Collection Lookups
The @collection reference allows rules to query other collections, enabling complex authorization patterns like role-based access, team membership, and resource permissions.
Incorrect (denormalizing data for access control):
// Duplicating team membership in every resource
const documentsSchema = [
{ name: 'title', type: 'text' },
{ name: 'team', type: 'relation' },
// Duplicated member list for access control - gets out of sync!
{ name: 'allowedUsers', type: 'relation', options: { maxSelect: 999 } }
];
// Rule checks duplicated data
listRule: 'allowedUsers ?= @request.auth.id'
// Problem: must update allowedUsers whenever team membership changes
Correct (using @collection lookup):
// Clean schema - no duplication
const documentsSchema = [
{ name: 'title', type: 'text' },
{ name: 'team', type: 'relation', options: { collectionId: 'teams' } }
];
// Check team membership via @collection lookup
listRule: '@collection.team_members.user ?= @request.auth.id && @collection.team_members.team ?= team'
// Alternative: check if user is in team's members array
listRule: 'team.members ?= @request.auth.id'
// Role-based access via separate roles collection
listRule: '@collection.user_roles.user = @request.auth.id && @collection.user_roles.role = "admin"'
Common patterns:
// Team-based access
// teams: { name, members (relation to users) }
// documents: { title, team (relation to teams) }
viewRule: 'team.members ?= @request.auth.id'
// Organization hierarchy
// orgs: { name }
// org_members: { org, user, role }
// projects: { name, org }
listRule: '@collection.org_members.org = org && @collection.org_members.user = @request.auth.id'
// Permission-based access
// permissions: { resource, user, level }
updateRule: '@collection.permissions.resource = id && @collection.permissions.user = @request.auth.id && @collection.permissions.level = "write"'
// Using aliases for complex queries
listRule: '@collection.memberships:m.user = @request.auth.id && @collection.memberships:m.team = team'
Performance considerations:
- Cross-collection lookups add query complexity
- Ensure referenced fields are indexed
- Consider caching for frequently accessed permissions
- Test performance with realistic data volumes
Reference: PocketBase Collection Reference