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

Field-Level Access Control

Field-level access controls which fields are visible or writable per-user.

Configuration

crap.fields.select({
    name = "status",
    access = {
        read = "hooks.access.everyone",
        create = "hooks.access.admin_only",
        update = "hooks.access.admin_only",
    },
    -- ...
})
PropertyControls
readWhether the field appears in API responses
createWhether the field can be set on create
updateWhether the field can be changed on update

Omitted properties default to allowed (no restriction).

How It Works

Write Access (create/update)

Before a write operation, denied fields are stripped from the input data. The operation proceeds with the remaining fields. This means:

  • On create: denied fields get their default value (or NULL)
  • On update: denied fields keep their current value

Read Access

After a query, denied fields are stripped from the response. The field still exists in the database, but the user doesn’t see it.

Example

-- hooks/access.lua
local M = {}

-- Only admins can see the internal_notes field
function M.admin_read(ctx)
    return ctx.user ~= nil and ctx.user.role == "admin"
end

-- Only admins can change the status field
function M.admin_write(ctx)
    return ctx.user ~= nil and ctx.user.role == "admin"
end

return M
-- In collection definition
crap.fields.textarea({
    name = "internal_notes",
    access = {
        read = "hooks.access.admin_read",
    },
}),
crap.fields.select({
    name = "status",
    access = {
        update = "hooks.access.admin_write",
    },
    -- ...
}),

Error Behavior

If a field access function throws an error, the field is treated as denied (fail-closed) and a warning is logged.