Howdy! ðŸ¤
I am trying to prevent a user from verifying their email if it has already been verified.
It doesn't hurt to verify it again, nevertheless, that's what I'm trying to achieve here. I am using Laravel Fortify.
app()->singleton(VerifyEmailResponseContract::class, VerifyEmailResponse::class);
class VerifyEmailResponse implements VerifyEmailResponseContract
{
public function toResponse($request): Response|JsonResponse|RedirectResponse
{
return $request->wantsJson()
? response()->json([
'metadata' => [
'message' => trans('responses.email_verified_successfully'),
],
])
: redirect()->intended(Config::get('fortify.home'));
}
}
My first thought was to check whether the email had been verified and return a different response. Something like this:
class VerifyEmailResponse implements VerifyEmailResponseContract
{
public function toResponse($request): Response|JsonResponse|RedirectResponse
{
return $request->wantsJson()
? response()->json([
'metadata' => [
'message' => $request->user()->hasVerifiedEmail()
? trans('responses.email_already_verified')
: trans('responses.email_verified_successfully'),
],
])
: redirect()->intended(Config::get('fortify.home'));
}
}
This didn't go quite to plan. This strangely always returns responses.email_already_verified
regardless of the value. This is because, by the time it returns the response, the email has been verified.
In a nutshell, this is what I am trying to achieve:
email_verified_at
is NULLemail_verified_at
is NOT NULLMy second attempt was to try and override EmailVerificationRequest to throw a validation message.
class EmailVerificationRequest extends BaseEmailVerificationRequest
{
public function authorize(): bool
{
if ($this->user()->hasVerifiedEmail()) {
$response = response()->json(
[
'metadata' => [
'message' => 'You have already verified your email.',
],
],
Response::HTTP_UNPROCESSABLE_ENTITY,
);
throw new HttpResponseException($response);
}
return parent::authorize();
}
}
app()->bind(EmailVerificationRequest::class, CustomEmailVerificationRequest::class);
It doesn't look like CustomEmailVerificationRequest is taking effect though.
Any ideas?
It might be better to expire the link once it has been used. Not sure. This would be consistent, and it makes sense because it will have the same behaviour after the link has expired.
FWIW, I am trying to avoid overriding routes.
Edit:
Perhaps this is overkill. Setting up another column just to track when an email was verified so we can return a more accurate response and handle the action properly. All for the duration of the email signature is active (like 60 minutes?)... Hmm.
so we can return a more accurate response and handle the action properly
Or rather, to throw a 419.