Skip to content

Users and roles

Anvil stores roles and their permissions in the database, per tenant. Users and roles are managed in the panel under Access. Login, sessions and passwords are CodeIgniter Shield; Anvil adds roles, authorization, single sign-on and two-factor authentication.

use Anvil\Access\Access;
public function resources(): array
{
return [InvoiceResource::class, ...Access::resources()];
}
public function pages(): array
{
return [Dashboard::class, ...Access::pages()];
}
Method Returns
Access::resources() UserResource, RoleResource; ApiClientResource as well when the API is used (Config\Anvil::$apiEndpoints or $apiPanels not empty, see API)
Access::pages() InboxPage (tasks), ProfilePage, WorkflowsPage (see Workflows)

A role belongs to one tenant and has

  • a list of permissions, e.g. invoices.view, or a wildcard like invoices.* (everything before the first dot),
  • or full access (is_super), which grants every permission, including permissions of resources added later.

A user can have several roles. Their permissions in a tenant are the union of the permissions of their roles in that tenant. Roles of other tenants have no effect.

The role editor lists

  • the panel permissions (Panel::permission(), e.g. admin.access, needed to enter a panel at all),
  • the abilities of every resource (view, create, update, delete, history, and export for exportable resources),
  • the permissions of actions, bulk actions and relation actions,
  • the permissions of workflows (overrides and transition actors),
  • the permissions of pages,
  • the custom permissions from Config\Anvil::$permissions:
public array $permissions = [
'Invoices' => ['invoices.export_datev' => 'Export to DATEV'],
];

php spark anvil:permissions prints the same list, e.g. to plan roles or for a review.

With single sign-on configured, the role editor also has a field per provider for the groups of the identity provider that grant the role.

Rule Error
A user can only add permissions to a role that they hold themselves permissions
Only users with full access can create, change or grant full access roles is_super
A role can only be deleted by users who could grant all of its permissions 403
A user can only assign roles whose permissions they hold themselves roles
Users cannot deactivate or remove their own account active, record
Users with permissions the editor does not hold (or full access) cannot be edited, removed or have TOTP reset roles, 403
Username and active state apply in every tenant of the user: they change only if the editor may manage the user in each of them username
Mapping SSO groups to a role needs the right to grant the whole role sso_<provider>

Permissions a role already has can be kept when editing, even if the editor does not hold them.

The user list shows the members of the current tenant. Creating a user

  1. creates the Shield account with e-mail and initial password,
  2. adds the user to the current tenant,
  3. marks the password for change at the first sign-in,
  4. assigns the selected roles.

The minimum length of the initial password is Config\Auth::$minimumPasswordLength. The e-mail address cannot be changed afterwards.

Removing a user removes their roles and membership in the current tenant. The account itself is only deleted when the user belongs to no other tenant.

The action Reset two-factor authentication on a user disables their TOTP, see Two-factor authentication.

All changes are written to the audit log, e.g. user.created, user.roles_changed, role.permissions_changed, role.sso_groups_changed, tenant.member_added, tenant.member_removed and the record changes.

The profile page (/<panel>/profile) shows the account and the roles in the current tenant, and lets every user change their password and set up two-factor authentication.

While a password change is pending (initial password, or forced by an administrator), the anvil-password filter (part of every panel’s filters) redirects every page to the profile page, and the component endpoint only accepts the password form.

The password policy is Shield’s (Config\Auth::$minimumPasswordLength, $passwordValidators). The AppStarter sets the minimum length to 12 characters. Consider enabling PwnedValidator – it sends a hash prefix of the password to haveibeenpwned.com, so check that this is acceptable for your environment.

Anvil reads Shield’s settings from the application’s Config\Auth (Anvil\Support\ShieldConfig::auth()), so the views and layout configured there also apply to the login and the TOTP pages.

With Config\Anvil::$shieldGroupFallback = true (default), the groups and permissions of Config\AuthGroups are granted in addition to the database roles. This helps while setting up an application. Disable it once all permissions are maintained as roles, so that there is only one source of truth. With Config\Anvil::$rbac = false the database roles are not used at all and only Shield’s groups apply.

php spark anvil:install creates the first administrator (in the Shield group superadmin, option --group) and the role Administrator with full access in the first tenant, and assigns it to them.