-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add email verification, 'email changed' email notifications to hub (#…
- Loading branch information
1 parent
6b00c0b
commit add81ea
Showing
20 changed files
with
380 additions
and
91 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace App\Listeners; | ||
|
||
use App\Events\UserSaved; | ||
use App\Mail\EmailChanged; | ||
use App\Mail\VerifyEmailAddress; | ||
use Illuminate\Contracts\Mail\Mailer; | ||
|
||
final readonly class SendAccountEmails | ||
{ | ||
public function __construct(private Mailer $mailer) {} | ||
|
||
public function handleUserSaved(UserSaved $event): void | ||
{ | ||
if ($event->user->email_verified) { | ||
// nothing to do | ||
return; | ||
} | ||
|
||
if ($event->user->wasRecentlyCreated) { | ||
$this->sendEmailToNewAccount($event); | ||
} elseif ($event->user->wasChanged('email')) { | ||
$this->sendEmailsOnEmailChange($event); | ||
} | ||
} | ||
|
||
private function sendEmailToNewAccount(UserSaved $event): void | ||
{ | ||
// TODO: should be a welcome email | ||
$this->mailer->send(new VerifyEmailAddress($event->user)); | ||
} | ||
|
||
private function sendEmailsOnEmailChange(UserSaved $event): void | ||
{ | ||
// do not send the notification if the previous email was unverified | ||
if ($event->user->getOriginal('email_verified')) { | ||
$this->mailer->send( | ||
new EmailChanged( | ||
oldEmail: $event->user->getOriginal('email'), | ||
name: $event->user->getOriginal('name'), | ||
), | ||
); | ||
} | ||
|
||
// send a verification request to the new address | ||
// TODO: should acknowledge the email change | ||
$this->mailer->send(new VerifyEmailAddress($event->user)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace App\Mail; | ||
|
||
use Illuminate\Bus\Queueable; | ||
use Illuminate\Mail\Mailable; | ||
use Illuminate\Mail\Mailables\Address; | ||
use Illuminate\Mail\Mailables\Content; | ||
use Illuminate\Mail\Mailables\Envelope; | ||
|
||
final class EmailChanged extends Mailable | ||
{ | ||
use Queueable; | ||
|
||
public function __construct( | ||
private readonly string $name, | ||
private readonly string $oldEmail, | ||
) {} | ||
|
||
public function envelope(): Envelope | ||
{ | ||
return new Envelope( | ||
subject: trans('email-changed.subject'), | ||
to: [new Address($this->oldEmail, $this->name)], | ||
); | ||
} | ||
|
||
public function content(): Content | ||
{ | ||
return new Content(html: 'emails.email-changed'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace App\Mail; | ||
|
||
use App\Models\User; | ||
use Illuminate\Bus\Queueable; | ||
use Illuminate\Mail\Mailable; | ||
use Illuminate\Mail\Mailables\Address; | ||
use Illuminate\Mail\Mailables\Content; | ||
use Illuminate\Mail\Mailables\Envelope; | ||
use Illuminate\Queue\SerializesModels; | ||
|
||
final class VerifyEmailAddress extends Mailable | ||
{ | ||
use Queueable; | ||
use SerializesModels; | ||
|
||
public function __construct( | ||
private readonly User $user, | ||
) {} | ||
|
||
public function envelope(): Envelope | ||
{ | ||
return new Envelope( | ||
subject: trans('verify-email.subject', ['site' => config('app.name')]), | ||
to: [new Address($this->user->email, $this->user->name)], | ||
); | ||
} | ||
|
||
public function content(): Content | ||
{ | ||
return new Content(html: 'emails.verify-email', with: [ | ||
'verification_link' => $this->user->makeVerificationLink(), | ||
]); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
sourcecode/hub/database/migrations/2025_01_16_080000_add_email_verified_column.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
use Illuminate\Database\Migrations\Migration; | ||
use Illuminate\Database\PostgresConnection; | ||
use Illuminate\Database\Schema\Blueprint; | ||
use Illuminate\Support\Facades\DB; | ||
use Illuminate\Support\Facades\Schema; | ||
|
||
return new class extends Migration { | ||
public function up(): void | ||
{ | ||
Schema::table('users', function (Blueprint $table) { | ||
$table->boolean('email_verified')->default(false); | ||
}); | ||
|
||
if (DB::connection() instanceof PostgresConnection) { | ||
DB::update('UPDATE users SET email_verified = true WHERE admin'); | ||
} else { | ||
DB::update('UPDATE users SET email_verified = 1 WHERE admin = 1'); | ||
} | ||
} | ||
|
||
public function down(): void | ||
{ | ||
Schema::table('users', function (Blueprint $table) { | ||
$table->dropColumn('email_verified'); | ||
}); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<?php | ||
|
||
return [ | ||
'subject' => 'Email address changed', | ||
'summary' => 'Someone (hopefully you) changed the email address on your :site account.', | ||
'unrecognised-action' => "If you didn't make this change, please get in touch with the :site administrator.", | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<?php | ||
|
||
return [ | ||
'subject' => 'Verify your :site account', | ||
'summary' => 'To verify your :site account, click the link below. If you aren\'t already logged in, you must do so for verification to take effect.', | ||
]; |
17 changes: 17 additions & 0 deletions
17
sourcecode/hub/resources/views/components/email-layout.blade.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{{-- | ||
Before changing this, note that some commonly used email clients are stuck in | ||
the stone ages (as of 2025), and don't support the HTML5 doctype or the | ||
<style> element. | ||
--}} | ||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" | ||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | ||
<html> | ||
<head> | ||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | ||
<title>{{ $title }}</title> | ||
</head> | ||
|
||
<body style="font-family: helvetica, arial, sans-serif; line-height: 1.5; max-width: 600px"> | ||
{{ $slot }} | ||
</body> | ||
</html> |
Oops, something went wrong.