Download the PHP package mortalkiller/filament-complete-user-profile without Composer
On this page you can find all versions of the php package mortalkiller/filament-complete-user-profile. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download mortalkiller/filament-complete-user-profile
More information about mortalkiller/filament-complete-user-profile
Files in mortalkiller/filament-complete-user-profile
Package filament-complete-user-profile
Short Description A complete, modular user account center for Filament 5.
License MIT
Homepage https://github.com/mortalkiller/filament-complete-user-profile
Informations about the package filament-complete-user-profile
Filament Complete User Profile
A complete, modular account center for Filament 5 and Laravel 13.
Why
Filament provides a solid native profile page, but real applications often need more than name, email and password changes. MFA, active sessions, API tokens, locale, application-specific profile fields and other account tools can quickly become separate pages with different navigation and interaction patterns.
This package keeps those concerns in one native Filament account experience. Built-in capabilities are opt-in where they need extra infrastructure, while application-specific data stays in the application through extension points such as custom profile fields and custom account sections. The goal is to avoid published-view forks and one-off profile pages without taking ownership of your domain models or persistence.
Documentation
Full documentation: https://docs.pedromonteiro.dev/filament-complete-user-profile/
- Getting Started
- Configuration
- API Reference
- Extension examples
Contents
- Why
- Documentation
- Features
- Screenshots
- Requirements
- Installation
- Default experience
- Navigation layout
- Account Security summary
- Enable MFA
- Enable Sessions
- Enable API Tokens
- Tenant-scoped tokens
- Customize Profile fields
- Custom account sections
- AccountSection API reference
- Structural config
- Diagnostics
- Advanced contracts
- Roadmap
- Development
- Security
- License
Features
- Native Filament account page with header sub-navigation.
- Avatar, name, email and locale profile fields.
- Application-owned custom fields saved through the existing Profile form.
- First-class custom account sections composed from native Filament schema components.
- Custom sections backed by external storage, application services or Eloquent relationships.
- Authenticator-app and email MFA.
- Database-backed browser session management.
- Laravel Sanctum API token management, including optional tenant scoping.
- User-table or separate package profile storage.
- Installation diagnostics for optional infrastructure.
Screenshots
Real captures of the package's full local workbench with every built-in account feature enabled. The demo uses fictional user data and real Filament components.
| Area | Light | Dark |
|---|---|---|
| Overview | ||
| Profile | ||
| Security | ||
| Sessions | ||
| API Tokens | ||
| Mobile Profile |
Run the full demo locally to explore every area and regenerate the screenshots.
Requirements
Version 1 supports:
- PHP
^8.3 - Laravel 13
- Filament
>=5.8.3 <6.0.0 mortalkiller/filament-page-header^2.3.1(required automatically via Composer; the plugin registers it on your panel for you)
The workbench also installs spatie/laravel-settings as a development-only dependency to demonstrate that a custom account section can use application-owned external persistence. Consuming applications do not need that package unless they choose the same integration.
Filament 4 and Filament 6 are not supported by the 1.x package line. The minimum Filament version
is 5.8.3. Filament 5.8.1 and 5.8.2 contain an upstream DataStore binding bug that can lose
Livewire per-component state when Filament's support provider is registered after Livewire; Filament
5.8.3 includes the upstream singleton fix. This baseline also remains above the earlier Filament 5
releases affected by the MFA security advisories relevant to this package.
Installation
Install the package:
Publish the registered styles after installation and package updates (or through your deployment's filament:upgrade step):
The security-card styles load through Filament's asset registry; a custom theme rebuild is not required.
Publish translations
The package includes translations for English, Portuguese, Spanish and French. To publish them into the host application, run:
The provider publishes the package translation files to lang_path('vendor/filament-complete-user-profile') — normally lang/vendor/filament-complete-user-profile (for example, pt/profile.php). A custom application language path is respected. Application translations take precedence over the package defaults; keys that are not defined by the application fall back to the package translations.
The published files initially contain all package keys. Keep only the keys you customize where possible, so future package translation improvements remain available for the other keys.
Publishing without --force preserves translation files that already exist in the application. Use --force only when you intentionally want to overwrite those files, because it replaces application customizations.
The default storage mode is user. If that is what you want, run the migrations:
If you want separate profile storage, publish the config and select that mode before the first package migration run:
Then run:
Storage mode is structural. Package migrations are only executed once by Laravel, so changing between user and separate after installation requires an application-owned migration/data migration for the transition.
Register the plugin on the Filament panel where you want to expose the account page:
The package registers its account page in Filament's native profile slot with the standard panel layout, so the sidebar, topbar, workspace switcher, notifications, and user menu remain available.
You do not need to publish the config for the default setup. The package migrations are defensive: application-owned user columns are created only when missing and are intentionally preserved on rollback.
Default experience
With only CompleteUserProfilePlugin::make(), the package enables:
- Overview
- Profile
- Avatar
- Name
- Locale
- Password management
Authenticator-app MFA, email MFA, browser sessions, and API tokens are disabled by default because each requires additional application infrastructure.
You can enable or disable the main areas from the panel provider:
Infrastructure and storage belong in the package config; feature behaviour belongs in the panel provider.
To publish the optional config:
Navigation layout
The account areas render as a single, iconless sub-navigation inside the account page's header, built with mortalkiller/filament-page-header. Built-in features and custom sections share that navigation. Inline areas use the section query parameter, for example ?section=security; page sections use their own native Filament URLs. Invalid or missing section values fall back to the first visible inline area. If only accessible page sections remain, the profile redirects to the first one; an empty account center retains its empty state.
You register one plugin. CompleteUserProfilePlugin registers PageHeaderPlugin on the panel when it is not already there. To change the header mode without registering a second plugin:
If your application already registers PageHeaderPlugin on the same panel, that registration is authoritative in either order and pageHeader() is ignored.
This uses native Filament and filament-page-header components and requires no package-specific navigation CSS.
There is no way to opt out of the header (no pageHeader(false)). An application that wants Filament's stock profile heading instead must subclass CompleteUserProfile and override headerSchema().
Content width
Configure the default account page width per panel:
maxContentWidth() accepts Width|string|null. The default null preserves Filament's panel fallback. This affects the built-in and inline custom sections, not separately routed page sections. Those keep their native page widths. An explicit width on a custom profile page subclass takes precedence.
Account Security summary
Beside the Overview and Profile areas, the page can render an "Account Security" summary card next to the main content. It lists up to four rows, each gated independently:
| Row | Appears when | State shown |
|---|---|---|
| Authenticator app | Security is enabled and app authentication is configured | "Enabled" when the user has a stored app-authentication secret, otherwise "Not configured" |
| Email MFA | Security is enabled and email authentication is configured | "Enabled" when hasEmailAuthentication() returns true for the user, otherwise "Not configured" |
| Active sessions | Sessions is enabled and the session store is supported (database session driver with a migrated sessions table) | The user's active session count, correctly pluralized |
| Personal access tokens | API Tokens is enabled and the user model exposes a tokens() relation |
The user's token count, correctly pluralized |
Each bordered row is a keyboard-accessible link to the account area it summarizes. Only MFA rows have a status dot: green for enabled, neutral for not configured. Counts are not security assessments. The card uses a neutral description and adapts to mobile and dark mode.
The sessions row is hidden entirely — not shown as "0 active sessions" — when the session store is unsupported (a non-database session driver, or a missing sessions table), since a confident zero would contradict the "unsupported" message the Sessions area itself shows in that situation. Every row is independently gated the same way: if none of the four apply, the card does not render at all, and the main content takes the full width.
The card is built by CompleteUserProfile::getAccountSecurityAsideComponent(): ?Component, a protected method you can override in a subclass to add, remove or reorder rows.
Enable MFA
MFA providers are configured inside the Security feature. The package builds on Filament's native MFA providers and keeps Filament responsible for code generation, verification, and the authentication challenge flow.
Enable authenticator-app MFA with recovery codes:
Enable email-code MFA:
Enable both and let Filament manage the available methods:
For authenticator-app MFA, your authenticatable Eloquent model must implement the package MFA contract and use its storage adapter trait:
For email MFA, implement Filament's native email-authentication contract, use the package storage trait, and ensure the model can send Laravel notifications:
Email MFA adds a server-enforced 60-second cooldown between verification-code sends. During the cooldown, the resend action is disabled and displays the remaining seconds. The verification code keeps Filament's native expiry window, which is currently 4 minutes by default.
The verification email is a queued Laravel notification. If your application uses an asynchronous queue connection such as database or redis, a queue worker must be running for codes to be delivered:
With QUEUE_CONNECTION=sync, the notification is delivered in the request, which can be useful locally, but production applications should keep their normal queue strategy rather than switching to sync only for MFA email delivery.
The package-managed migrations provide the default authenticator-app secret, recovery-code, and email-MFA state columns when storage is user. Existing configured columns are reused rather than replaced.
Because MFA is registered at the Filament panel level, all authentication flows entering that panel must continue through Filament's MFA challenge. Do not bypass the panel's authentication completion flow from a custom social-login callback.
Enable Sessions
Browser-session management requires Laravel database sessions:
Create Laravel's sessions table if your application does not already have one, then run migrations:
Enable the feature:
The account page lists only sessions belonging to the authenticated user, marks the current session, prevents terminating the current session from the row action, and supports revoking all other sessions after reauthentication.
Enable API Tokens
API-token management uses Laravel Sanctum. Install Sanctum in the host application and add HasApiTokens to the authenticatable model:
Then enable the feature with an explicit ability whitelist:
The whitelist is mandatory. Wildcard (*) abilities and abilities outside the configured list are rejected. The plaintext token is shown only immediately after creation and is cleared from the Livewire component when the confirmation modal is completed.
Tenant-scoped tokens
Tenant-scoped tokens are opt-in and fail closed. By default, the package resolves the active tenant through Filament's native Filament::getTenant(). Applications using another tenancy system can replace that behavior once on the panel plugin with tenancyResolver(); the same resolver is then used for token creation, listing, revocation, and API request enforcement.
Enable tenant scoping with the native Filament resolver:
Publish and run the opt-in migration:
In multi-database applications, run the migration on the database connection used by Sanctum's PersonalAccessToken model. The package checks the token model's actual relation and connection rather than assuming Laravel's current default connection.
Custom tenancy resolver
A resolver must implement TenancyResolver and return the active Eloquent tenant/context model or null:
Configure it on the Filament panel:
tenancyResolver() accepts a resolver class-string, a resolver instance, or a closure returning ?Model. Class-strings are recommended for reusable integrations because Laravel can resolve their constructor dependencies.
This works with stancl/tenancy / archtechx/tenancy without making it a dependency of this package. The same pattern can adapt any tenancy implementation.
Protect tenant-sensitive API routes after Sanctum authentication:
The middleware uses the same configured resolver. A missing active context, token without context metadata, or context mismatch returns HTTP 403. A token created for one tenant cannot be listed, revoked, or accepted for another tenant through the package's tenant-scoped flow.
The previous TokenContextResolver contract remains supported for backwards compatibility, but new integrations should use TenancyResolver.
Customize Profile fields
The package keeps Filament's native profile fields and exposes small extension points instead of requiring published views.
Configure locale options with locale codes; common language names are resolved automatically:
Associative arrays remain available when you want custom labels:
Without explicit locale options, the package reads app.available_locales, then app.supported_locales, and finally falls back to app.locale.
Disable a default field:
Configure an existing field using the native Filament component:
Add application-owned user fields
Add the columns in the consuming application:
Then add normal Filament fields to the existing Profile form:
Additional fields are filled from the authenticated Eloquent model and participate in the normal profile save. The application still owns the columns, casts, validation rules and Eloquent mass-assignment policy. The package does not create arbitrary domain columns.
For advanced cases, Profile also exposes modifyFieldsUsing(), mutateDataBeforeSaveUsing(), and afterSave().
The local workbench demonstrates this with job_title and phone. See Extension examples for the complete example.
Custom account sections
Use a custom account section when you want a new first-class area in the account navigation rather than another field inside the existing Profile form. Register sections one at a time with the plugin's fluent section() method:
The section ID uses lowercase kebab-case. When no label is configured, the package derives one from the ID, so connected-accounts becomes Connected Accounts. Custom sections participate in the same ordering as built-in account areas and use the same ?section=... selection.
Back a section with another package
AccountSection composes navigation with either Filament schema components or a routed page; persistence stays application-owned. For example, the workbench uses spatie/laravel-settings without making it a runtime dependency of this package:
The settings class, migrations and package installation remain the consuming application's responsibility.
Show an Eloquent relationship
A custom section can also read or mutate a relationship. The workbench demonstrates a User::addresses() relation with native Filament entries and actions:
For a full table, filters or richer CRUD behavior, compose the section from a Livewire component:
Routed Filament Pages
A section can point to a native Filament page instead of defining an inline schema:
The plugin registers the page with the panel. The trait adopts the account header, breadcrumbs and navigation, hides the page from the main sidebar by default, and requires its section to be registered on the current panel. The page keeps its own URL, mount(), forms, tables, actions and native canAccess() authorization. It is never mounted inside the profile page. Override presentation methods normally when needed.
schema() and page() are mutually exclusive, including an explicitly empty schema. Only concrete custom panel pages using the trait are supported: not resources, authentication/profile pages, clusters, pages inside a cluster, pages with route parameters, or PageConfiguration variants. A page class can back only one section per panel. Configure sections before registering the plugin; separate panels can register the same class with their own metadata. Clear/rebuild Filament component and route caches when deploying registration changes.
visible() controls navigation, not authorization. A hidden page can still be opened directly when its canAccess() allows it. Inaccessible pages are omitted from navigation; sensitive actions must enforce their own permissions. Native tenant pages require the current tenant and use Filament URL generation; a custom token tenancy resolver does not replace Filament routing. ?section=billing does not load a routed page: follow its navigation link or use Billing::getUrl().
AccountSection does not automatically persist fields to the user model, ProfileStorage, or any package-owned table. The application owns migrations, validation and persistence for domain-specific data rendered inside a custom section.
Use Profile::fields() when a field naturally belongs to the existing Profile form and should participate in that form's normal save flow. Use AccountSection when the feature deserves its own navigable area.
The following IDs are reserved by the built-in package features and cannot be registered as custom sections:
overviewprofilesecuritysessionsapi-tokens
Registering a reserved ID or registering the same custom section ID twice throws a clear exception instead of silently overriding an existing area.
AccountSection API reference
AccountSection is intentionally small. The fluent configuration methods return the same section instance so configuration reads naturally from left to right.
Fluent configuration
make(string $id)creates a section. IDs must use lowercase kebab-case, for exampleconnected-accounts.label(string|Closure $label)sets the navigation label. Without a label, the ID is converted to a headline.description(string|Closure|null $description)sets the description rendered in the page header when the section is active.sort(int $sort)controls ordering relative to built-in and custom account areas. The default is100.visible(bool|Closure $condition = true)controls navigation visibility and inline selection, not routed-page authorization. The default istrue.schema(array|Closure $components)defines the section content. The array or callback result must contain only Filament schema components.page(string $page)selects a concrete custom Filament page usingInteractsWithAccountSection, instead of an inline schema.
Read-only accessors
These methods expose the resolved section configuration for integrations and package-level customization:
getId()returns the section ID.getLabel()returns the resolved label, including the generated headline fallback.getDescription()returns the resolved description ornull.getSort()returns the configured sort value.isVisible()evaluates the visibility condition.getSchema()evaluates and validates the schema, returning the normalized list of Filament schema components.getPage()returns the configured page class ornullfor an inline section.
Plugin registration API
CompleteUserProfilePlugin exposes the following custom-section methods:
section(AccountSection $section)registers one custom account section and returns the plugin for fluent chaining. Reserved or duplicate IDs throw aLogicException.getSections()returns all registered custom sections keyed by ID.getVisibleSections()returns only visible custom sections, ordered by their sort value.
There is intentionally no sections() method. Register sections one at a time with section() so the package has one canonical, autocomplete-friendly API.
Structural config
Publishing the config is optional:
The structural defaults are:
user_model => null resolves the model from Laravel's default authentication provider. Set it explicitly when the package should use another authenticatable model.
storage => 'user' stores avatar, locale, and package-managed MFA data on the configured user model. The migrations check each configured column before adding it.
storage => 'separate' stores package profile data in the package-owned filament_user_profiles table. This is useful when the host application should not add package-specific profile columns to its user table.
Feature toggles do not belong in this config. Configure features per Filament panel through CompleteUserProfilePlugin.
Diagnostics
Run the installation checker after configuring the package or enabling an optional capability:
The command reports PASS, INFO, and FAIL checks for the registered panels, user model, profile storage, configured profile columns, authenticator-app MFA, email MFA, database sessions, Sanctum, and tenant-token infrastructure.
It exits with code 0 when every enabled capability is ready and code 1 when an enabled capability is misconfigured. Disabled optional capabilities are informational and do not make the command fail.
Advanced contracts
The package deliberately keeps authentication and tenancy integration replaceable through small contracts.
Reauthentication controls how sensitive account actions re-confirm the user's identity. The default implementation uses the current password when available. Applications with passwordless or social-only users can bind their own implementation.
SessionStore abstracts browser-session storage. The built-in implementation supports Laravel's database session driver.
TenancyResolver resolves the active tenant/context for all tenant-aware package operations. The default implementation uses Filament native tenancy; applications can replace it through CompleteUserProfilePlugin::tenancyResolver(). TokenContextResolver remains as a deprecated backwards-compatible alias.
HasMultiFactorAuthentication is the package-facing contract that connects the user model to Filament's native authenticator-app MFA storage. InteractsWithMultiFactorAuthentication is the provided implementation for the package storage modes.
InteractsWithEmailAuthentication implements Filament's native email-MFA storage methods using the same package storage modes.
Roadmap
See docs/roadmap.md for features being considered for future releases.
Roadmap items are exploratory and are not release commitments.
Development
See CONTRIBUTING.md for contribution and maintenance guidance.
The GitHub Actions matrix validates supported PHP versions. A separate code-quality workflow verifies formatting, static analysis and tracked PHP syntax.
Security
Please report vulnerabilities privately using the process in SECURITY.md. Use GitHub Issues for ordinary bugs and feature requests.
License
MIT. See LICENSE.md.
All versions of filament-complete-user-profile with dependencies
filament/filament Version >=5.8.3 <6.0.0
illuminate/contracts Version ^13.0
illuminate/database Version ^13.0
illuminate/support Version ^13.0
mortalkiller/filament-page-header Version ^2.3.1