In your Filament application, you might want multiple user verifications by email and admin after a user registers. Let's see how to do that.
Imagine we have two Filament panels in this tutorial: admin
and owner
.
Email verification can be enabled simply by adding the MustVerifyEmail
interface to the user User
Model and enabling verification in the panel provider.
app/Models/User.php:
use Illuminate\Contracts\Auth\MustVerifyEmail;use Filament\Models\Contracts\FilamentUser;use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable implements FilamentUser, MustVerifyEmail{ // ...}
app/Providers/Filament/OwnerPanelProvider.php:
use Filament\Panel; public function panel(Panel $panel): Panel{ return $panel // ... ->login() ->registration() ->emailVerification() // ...}
For email verification, that is enough; filament will handle everything.
Now, let's add manual verification by an admin user. First, we need a column in the users
table similar to how the email_verified_at
column works for email verification.
database/migrations/xxxx_add_owner_verified_at_to_users_table.php:
Schema::table('users', function (Blueprint $table) { $table->timestamp('owner_verified_at')->nullable();});
app/Models/User.php:
class User extends Authenticatable implements FilamentUser, MustVerifyEmail{ // ... protected $fillable = [ 'name', 'email', 'password', 'owner_verified_at', ]; // ... protected function casts(): array { return [ 'email_verified_at' => 'datetime', 'password' => 'hashed', 'owner_verified_at' => 'datetime', ]; } // ...}
Next, we need Middleware to check if the user is verified; if not, we need to restrict access. This Middleware must be added to the authMiddleware
list in the panel provider.
php artisan make:middleware OwnerUserVerifiedMiddleware
app/Middleware/OwnerUserVerifiedMiddleware.php:
use Closure;use Illuminate\Http\Request;use Symfony\Component\HttpFoundation\Response; class OwnerUserVerifiedMiddleware{ public function handle(Request $request, Closure $next) { if (is_null($request->user()->owner_verified_at) { abort(Response::HTTP_FORBIDDEN, 'Your account must be verified by an admin.'); } return $next($request); }}
In the panel provider:
app/Providers/Filament/OwnerPanelProvider.php:
use App\Http\Middleware\OwnerUserVerifiedMiddleware; public function panel(Panel $panel): Panel{ return $panel // ... ->authMiddleware([ Authenticate::class, OwnerUserVerifiedMiddleware::class, ]);}
It would be great if after registration admin users would get notified about a new user that needs verification. There are multiple ways to do that. We will use a custom registration page.
php artisan make:filament-page Register
You should choose the panel to which the page will be added. In my case, the panel will be
Owner
, which corresponds to the namespace.
app/Filament/Owner/Pages/Register.php:
use App\Models\User;use Filament\Pages\Auth\Register as BaseRegister;use Illuminate\Database\Eloquent\Model;use App\Notifications\OwnerUserCreatedNotification; class Register extends BaseRegister{ protected function handleRegistration(array $data): Model { /** @var User $user */ $user = parent::handleRegistration($data); $admins = User::whereRelation('role', 'name', 'admin')->get(); $admins->each->notify(new OwnerUserCreatedNotification($user->id)); return $user; }}
Here, we get all the users with the role admin
and send the OwnerUserCreatedNotification
notification to each one.
app/Notifications/OwnerUserCreatedNotification.php:
use App\Models\User;use Illuminate\Bus\Queueable;use Illuminate\Notifications\Notification;use Illuminate\Contracts\Queue\ShouldQueue;use App\Filament\Admin\Resources\UserResource;use Illuminate\Notifications\Messages\MailMessage; class OwnerUserCreatedNotification extends Notification implements ShouldQueue{ use Queueable; public function __construct(private readonly int $userId) {} public function via(User $notifiable): array { return ['mail']; } public function toMail(User $notifiable): MailMessage { return (new MailMessage) ->line('A new owner user has been created.') ->line('Please login to the admin panel and verify the user.') ->action('Visit Admin Panel', UserResource::getUrl()); }}
You would have a resource for managing users in the Admin panel, typically a UserResource
. Let's add a verify action to the table.
app/Filament/Admin/Resources/UserResource.php:
use Filament\Notifications\Notification;use App\Notifications\OwnerUserVerifiedNotification; public static function table(Table $table): Table{ return $table // ... ->actions([ Tables\Actions\Action::make('verify') ->icon('heroicon-o-check-circle') ->visible(fn (User $user) => is_null($user->owner_verified_at)) ->action(function (User $user) { if (is_null($user->owner_verified_at)) { return; } $user->touch('owner_verified_at'); $user->notify(new OwnerUserVerifiedNotification()); Notification::make() ->success() ->title("User {$user->name} verified") ->send(); }), Tables\Actions\ViewAction::make(), ]) // ...}
Here, we show action only if the owner_verified_at
column is null. After hitting this action, the owner_verified_at
column is updated, and a notification is sent to the user to inform him that he was approved by an admin. To the admin user, a success notification is shown.
app/Notification/OwnerUserVerifiedNotification.php:
use App\Models\User;use Illuminate\Bus\Queueable;use Filament\Pages\Dashboard;use Illuminate\Notifications\Notification;use Illuminate\Contracts\Queue\ShouldQueue;use Illuminate\Notifications\Messages\MailMessage; class OwnerUserVerifiedNotification extends Notification implements ShouldQueue{ use Queueable; public function __construct() {} public function via(User $notifiable): array { return ['mail']; } public function toMail(User $notifiable): MailMessage { return (new MailMessage) ->line('An admin has verified your account.') ->action('Visit Owner Panel', Dashboard::getUrl(panel: 'owner')); }}
Now, when the user has both verifications, he can access the panel.
A few of our Premium Examples: