Skip to content

Users resource (/admin/users)

Manages App\Models\User — the human accounts that access the admin panel.

Model attributes

Attribute Type Notes
id UUID Primary key via HasUuids
name string Display name
email string Unique; used for login
password string Bcrypt-hashed
is_active boolean When false the user cannot log in to the admin panel
deleted_at timestamp Soft deletes enabled

Role

Managed by Spatie Laravel Permission via HasRoles. Each user has exactly one role from the SystemRole enum:

Role Value
SuperAdmin super_admin
PlatformSupport platform_support
Viewer viewer

Operated systems

BelongsToMany via the system_user pivot table, using the App\Models\SystemUser pivot class. The relation is User::operatedSystems(); its inverse is System::supportUsers(). Only systems whose driver is an internal consuming platform may have members at all, enforced by the System::canHaveSupportUsers() scope.

Only meaningful for PlatformSupport and Viewer — the set of tenants those users reach is derived from this membership rather than assigned to them. See Tenant reach is derived and ADR-0007.

List view columns

Column Source Behaviour
Name users.name Searchable, sortable
Email users.email Searchable
Role roles.name (first role) Badge; shows — when no role is assigned
Active users.is_active IconColumn boolean

Filters: TernaryFilter on is_active (Active / Inactive / All).

Bulk actions: DeleteBulkAction (soft delete).

Row actions

Edit

Navigates to the user edit page.

Deactivate

Visible when is_active === true, the record is not the authenticated user's own account, and the authenticated user can update the record per UserPolicy. Requires confirmation. Sets is_active = false.

Activate

Visible when is_active === false and the authenticated user can update the record per UserPolicy. Requires confirmation. Sets is_active = true.

Both actions require users.update on top of users.viewAny, which only gates seeing the Users list at all — being able to see the list is not enough on its own to toggle another user's active status.

Form fields (create / edit)

Field Validation Notes
Name Required —
Email Required, unique Uniqueness check ignores the current record on edit
Password Required on create Optional on edit; only persisted when the field is filled
Role Required Select of SystemRole enum; disabled when the authenticated user edits their own account
Operated systems Required when visible Select with ->multiple(), bound to operatedSystems; options come from System::canHaveSupportUsers()->pluck('name', 'id'), not from a ->relationship(); visible and required for PlatformSupport and Viewer

Edit page header actions: DeleteAction (soft delete).

Edit page behaviour

  • mutateFormDataBeforeFill pre-populates the Role select from the first assigned role, and the Operated systems multi-select from operatedSystems()->pluck('id').
  • afterSave (edit) and afterCreate (create) both call syncRoles only when the changeRole policy gate passes — this prevents a SuperAdmin from demoting their own account and gates role assignment on create the same way it gates role changes on edit. On denial, both pages show a danger notification and call $this->halt() instead of silently skipping the sync. operatedSystems is synced unconditionally, on both create and edit, so it is never blocked by a denied role change.

Source files

File Purpose
app/Filament/Resources/Users/UserResource.php Resource definition
app/Filament/Resources/Users/Schemas/UserForm.php Form schema
app/Filament/Resources/Users/Tables/UserTable.php Table columns, filters, actions
app/Filament/Resources/Users/Pages/ListUsers.php List page
app/Filament/Resources/Users/Pages/CreateUser.php Create page with afterCreate role and operated-systems sync
app/Filament/Resources/Users/Pages/EditUser.php Edit page with role and operated-systems pre-fill and afterSave hook

See also

  • Roles & Permissions — SystemRole enum, gate definitions, and permission matrix
  • Policies — UserPolicy and the changeRole gate used by the create and edit pages