Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Filter Constraints

Read access functions can return a filter table instead of a boolean. The filters are merged as AND clauses into the query, restricting which documents the user can see.

Basic Usage

function M.own_posts(ctx)
    if ctx.user == nil then return false end
    if ctx.user.role == "admin" then return true end
    -- Regular users can only see their own posts
    return { author = ctx.user.id }
end

When this function returns { author = ctx.user.id }, the query gets an additional WHERE author = ? clause. The user only sees documents where author matches their ID.

Filter Format

The returned table uses the same format as crap.collections.find() filters:

-- Simple equality
return { status = "published" }

-- Operator-based filter
return { status = { not_equals = "archived" } }

-- Multiple constraints (AND)
return {
    status = "published",
    department = ctx.user.department,
}

How Constraints Are Merged

Constraints from access functions are merged with any existing query filters using AND:

Final WHERE = (user's filters) AND (access constraints)

This means constraints can only narrow results, never expand them.

Example: Multi-Tenant Access

function M.tenant_read(ctx)
    if ctx.user == nil then return false end
    -- Users can only see documents in their tenant
    return { tenant_id = ctx.user.tenant_id }
end

Example: Published-Only for Anonymous

function M.public_or_own(ctx)
    if ctx.user == nil then
        return { status = "published" }
    end
    if ctx.user.role == "admin" then
        return true  -- admins see everything
    end
    -- Authors see their own + published
    -- (Note: complex OR logic isn't supported in filter returns)
    return { author = ctx.user.id }
end