Skip to content

Permissions and visibility

An action is shown for a record when the user has its permission for this record and visible() returns true. Both are checked again on the server when it runs.

Action::make('approve')->permission('orders.approve'),
  • Default: <slug>.update of the resource.
  • The gate checks the permission with the record as subject, so policies apply: a policy can allow “approve” only for orders of the user’s cost center.
  • Own permissions such as orders.approve are listed in the role editor when you add them to Config\Anvil::$permissions:
app/Config/Anvil.php
public array $permissions = [
'Orders' => ['orders.approve' => 'Approve orders'],
];
->visible(fn ($order): bool => $order->status === 'open')

visible() decides by the state of the record: an action that makes no sense (approve an approved order) is not shown. It is not a permission – use permission() and policies for who may run it.

A button from a stale page, or a request crafted by hand, cannot run an action the user may no longer run on this record:

  • the record is loaded again through the resource (404 outside the scope),
  • the permission with policy and visible() are checked again (403),
  • for actions in rows, the server also checks that the action is marked inRow(),
  • with a workflow, records in a locked state can still run actions; check the state in visible() when an action must not run then.

Link actions are shown with their permission and visible() as well, but hiding a link is not access control: what the user may see on the opened page is decided by that page or the other system. See Links to pages.