Tapping into email verification functionality.
I'm trying to make it so that an admin registers users for the app and sends an invite, rather than the user registering themselves. I added the
MustVerifyEmail
trait to my User model, and I'm calling $this->sendEmailVerificationNotification()
method after creating the user. I'm getting the error:
Route [verification.verify] not defined.
Which I get, I need to add the route, but I'm unsure of where the route should point to? Or is it more of a configuration change I need to make, rather than adding it to my web.php route file?Solution:Jump to solution
ok, figured it out. This was the solution in case anyone is trying to do this oddly specific thing in the future:
```
class VerificationResponse implements EmailVerificationResponse
{...
11 Replies
I added this to my web.php file:
Route::get('/email/verify/{id}/{hash}', [EmailVerificationController::class, '__invoke'])->middleware(['signed'])->name('verification.verify');
Which resolves the error, but I'm still not sure if I'm doing it right. I believe I should be calling the Filament EmailVerificationController. However, when I do that, I get Call to a member function hasVerifiedEmail() on null
I think part of the problem might be that the EmailVerificationController expects the user to be logged in already? In my case, the user won't be able to log in until they reset their password, so I technically need to redirect them to the password reset route.
In the EmailVerificationController class, it returns:
return app(EmailVerificationResponse::class);
It seems like if I create a class that implements that, and then do my redirect there, that should work. I'm not sure if I'm doing any of this correctly, so hoping someone might be able to point me in the right direction.$panel->emailVerification() ?
yeah, I have that included. I think I've got it mostly working. I can send the email verification, and I can mark it as verified in the DB. What I need to do is validate the hash in the verification URL, as it doesn't seem like that's happening anywhere (which I find odd) unless it's happening somehow behind the scenes and I'm just not seeing it, and then I need to redirect to the password reset view that would be generated from a password reset email. Trying to skip the step where they put in their email address and it sends them an email.
nvm, it's generating a signed route and i'm using the signed middleware, so all of that is taken care of. I just need to generate a new signed route for the password reset
Still working on this...I'm unable to redirect to the password reset screen after the user verifies their email. I get the error:
Route [filament.admin.auth.password-reset.reset] not defined.
But my login/password reset/email verification is all defined on the app panel, not the admin panel.
And when I run artisan route:list
, the route that's shown is filament.app.auth.password-reset.reset
.
And the regular password reset is working as expected.
Here's how I'm attempting to do it:
and the getResetPasswordUrl
method in Filament is getting the currentPanel, which I don't understand.
Can I set the current panel for the purposes of what I'm trying to do?
I don't understand why the current panel matters for a password reset.Solution
ok, figured it out. This was the solution in case anyone is trying to do this oddly specific thing in the future:
@Jon Mason Your solutions almost works for me but I am just confused as to how to bind the custom VerificationResponse to act instead of the default EmailVerificationResponse. I tried to register it inside my service providers but It does not work. I suspect that are some different mechanisms in Filament
@toufikkhattara This may be helpful for you. I have this controller:
As you can see, this returns my own VerificationResponse, which implements the EmailVerificationResponse interface.
and then in my web.php routes file, I have this route:
Route::get('email/verify/{id}/{hash}', [EmailVerificationController::class, '__invoke'])->middleware(['signed', 'guest'])->name('verification.verify');
Hopefully that helps!
oh, you also need this on your panel provider: ->emailVerification(EmailVerificationController::class)
I see. I was confused at first since you did not mention that you extended the EmailVerificationController although it was somewhat obvious. I actually figured it out this way and implemented a new function toResponse inside the controller which I called from the route too. My case and implementation was slightly different and included the whole logic inside one function. Your solution was very insightful and not oddly specific 🙂
class CustomVerificationResponse extends EmailVerificationController
{
public function toResponse(Request $request): RedirectResponse
{
$user = User::find($request->route('id'));
if ($user->role === 'admin') {
return app(EmailVerificationResponse::class)->toResponse($request);
}
$user->markEmailAsVerified();
$token = Password::broker()->createToken($user);
$url = Filament::getResetPasswordUrl($token, $user);
return redirect()->to($url);
}
}
awesome, glad you got it figured out!
Hi, I'm testing the same features.
where can i call $this->sendEmailVerificationNotification() ?
I have implemented it. App\Http\Controllers\Auth\EmailVerificationController App\Http\Controllers\Responses\VerificationResponse and UserObserver Thanks 🙂 Ohh there was a session opened in another tab , everything works fine !!
I have implemented it. App\Http\Controllers\Auth\EmailVerificationController App\Http\Controllers\Responses\VerificationResponse and UserObserver Thanks 🙂 Ohh there was a session opened in another tab , everything works fine !!
On your user model, make sure you have:
Where VerifyEmail is a notification class containing a toMail method:
I'm having some issues with my implementation, so can't promise you all of the above is correct. Trying to work through it now.
For future readers, try this