Features

Users & groups

Admin Users and Groups manage who can sign in and how they inherit roles. Both support soft-delete, restore, force-delete, and bulk actions. Groups attach members and Spatie roles so permissions (and role-tied collection/file ACL) flow through EffectivePermissionResolver.

Related

How group roles become effective permissions: Effective permissions. Role assignment UI: Roles & permissions. Drawer URLs: Routing — deep-links (?edit= / ?new=1).

Permissions

Exact PermissionEnum strings (do not invent others):

AreaPermissions
Userscan-show-users, can-create-users, can-edit-users, can-delete-users, can-restore-users, can-force-delete-users
Groupscan-show-groups, can-create-groups, can-edit-groups, can-delete-groups, can-restore-groups, can-force-delete-groups

Route middleware uses permission:… for most endpoints. Bulk actions authorize inside BulkUserActionRequest / BulkUserGroupActionRequest (maps delete / restore / force_delete to the matching permission).

Users

Controller & page

ItemDetail
ControllerApp\Http\Controllers\Admin\UserController
ModelApp\Models\User (SoftDeletes, Spatie HasRoles, Fortify TwoFactorAuthenticatable + PasskeyAuthenticatable)
Frontendresources/js/pages/admin/users/index.tsx
Routesroutes/admin.php under auth + verified

Lifecycle

ActionRoutePermission
List / search / trash filterGET /userscan-show-users
CreatePOST /userscan-create-users
UpdatePUT /users/{user}can-edit-users
Soft-deleteDELETE /users/{user}can-delete-users
RestorePOST /users/{user}/restorecan-restore-users
Force-deleteDELETE /users/{user}/forcecan-force-delete-users
BulkPOST /users/bulk-actionsPer action in FormRequest

Route binding uses withTrashed() so restore/force-delete can target soft-deleted users.

Bulk actions (BulkUserActionRequest): actiondelete | restore | force_delete, plus ids[].

Create / update fields

Validated by StoreUserRequest / UpdateUserRequest:

FieldNotes
first_nameRequired
last_nameOptional
emailRequired, unique
usernameOptional
passwordRequired on create; optional on update
is_activeOptional boolean
role_idsOptional array — synced via Spatie
group_idsOptional array — synced on groups() pivot

last_login

On Illuminate\Auth\Events\Login, AppServiceProvider::registerAuthActivityListeners updates:

  • last_login_at
  • last_login_ip

via forceFill(...)->saveQuietly() on the user.

UI exposure

Those columns exist and are maintained on login. They are not currently exposed in UserResource or the admin users table (not listed/sortable in the UI).

Groups

Why groups (not Directus-style teams)

Groups are a thin inheritance layer for large user bases: attach Spatie roles to a group, add members, and every member inherits:

  1. Admin Spatie permissions from those roles (via EffectivePermissionResolver)
  2. Collection / file ACL tied to the same roles (collection_permissions / file_permissions matrices on the role)

There is no separate group → collection_permissions matrix. Configure access on the role; scale membership via the group.

Controller & page

ItemDetail
ControllerApp\Http\Controllers\Admin\UserGroupController
ModelApp\Models\UserGroup (SoftDeletes, resolveRouteBinding includes trash)
Pivotsuser_group_user (members), user_group_role (roles)
Frontendresources/js/pages/admin/groups/index.tsx

Routes

ActionRoutePermission
List / search / trash filterGET /groupscan-show-groups
CreatePOST /groupscan-create-groups
UpdatePUT /groups/{group}can-edit-groups
Soft-deleteDELETE /groups/{group}can-delete-groups
RestorePOST /groups/{group}/restorecan-restore-groups
Force-deleteDELETE /groups/{group}/forcecan-force-delete-groups
BulkPOST /groups/bulk-actionsPer action in FormRequest

Bulk actions (BulkUserGroupActionRequest): actiondelete | restore | force_delete, plus ids[].

Members + role attachment

Store/update accept:

FieldRole
nameRequired
descriptionOptional
user_idsOptional — sync group members when present (omit to leave members unchanged; empty array clears)
role_idsOptional — sync Spatie roles onto the group when present

Index payloads include user_ids and users (id / name / email) so the edit drawer can hydrate the member multi-select.

Permission inheritance: EffectivePermissionResolver unions:

  1. Roles assigned directly on the user
  2. Roles attached to each of the user’s groups

effectiveRoleIds() feeds the same set into admin collection field ACL (CollectionPermissionGuard::rulesForUser). See Effective permissions.

Source map

ConcernLocation
Users controllerapp/Http/Controllers/Admin/UserController.php
Groups controllerapp/Http/Controllers/Admin/UserGroupController.php
Admin routesroutes/admin.php
Client route helpersresources/js/lib/admin-routes.ts
Auth login timestampAppServiceProvider::registerAuthActivityListeners
Post-login homeApp\Support\Auth\HomePath (uses EffectivePermissionResolver)
Previous
Dashboard