mirror of
https://github.com/flarum/framework.git
synced 2024-11-23 06:01:56 +08:00
Preliminary email confirmation implementation
Whenever a user registers or changes their email, they are sent an email containing a link which they must click to confirm it. Upon registering, a user won’t be assigned to any groups and therefore won’t have permission to do anything (but they can still log in!) Upon confirming their email for the first time, their account will be assigned to the Member group and thus “activated”.
This commit is contained in:
parent
b6ef1f296e
commit
0e4e44c358
|
@ -32,6 +32,7 @@ class CoreServiceProvider extends ServiceProvider
|
|||
Event::listen('Flarum.Core.*', 'Flarum\Core\Listeners\DiscussionMetadataUpdater');
|
||||
Event::listen('Flarum.Core.*', 'Flarum\Core\Listeners\UserMetadataUpdater');
|
||||
Event::listen('Flarum.Core.*', 'Flarum\Core\Listeners\RenamedPostCreator');
|
||||
Event::listen('Flarum.Core.*', 'Flarum\Core\Listeners\EmailConfirmationMailer');
|
||||
|
||||
Post::addType('comment', 'Flarum\Core\Posts\CommentPost');
|
||||
Post::addType('renamed', 'Flarum\Core\Posts\RenamedPost');
|
||||
|
|
36
src/Flarum/Core/Listeners/EmailConfirmationMailer.php
Executable file
36
src/Flarum/Core/Listeners/EmailConfirmationMailer.php
Executable file
|
@ -0,0 +1,36 @@
|
|||
<?php namespace Flarum\Core\Listeners;
|
||||
|
||||
use Illuminate\Mail\Mailer;
|
||||
use Laracasts\Commander\Events\EventListener;
|
||||
|
||||
use Flarum\Core\Users\Events\UserWasRegistered;
|
||||
use Flarum\Core\Users\Events\EmailWasChanged;
|
||||
|
||||
class EmailConfirmationMailer extends EventListener
|
||||
{
|
||||
protected $mailer;
|
||||
|
||||
public function __construct(Mailer $mailer)
|
||||
{
|
||||
$this->mailer = $mailer;
|
||||
}
|
||||
|
||||
public function whenUserWasRegistered(UserWasRegistered $event)
|
||||
{
|
||||
$user = $event->user;
|
||||
|
||||
$data = [
|
||||
'user' => $user,
|
||||
'url' => route('flarum.confirm', ['id' => $user->id, 'token' => $user->confirmation_token])
|
||||
];
|
||||
|
||||
$this->mailer->send('flarum::emails.confirm', $data, function ($message) use ($user) {
|
||||
$message->to($user->email)->subject('Welcome!');
|
||||
});
|
||||
}
|
||||
|
||||
public function whenEmailWasChanged(EmailWasChanged $event)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<?php namespace Flarum\Core\Support\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class InvalidConfirmationTokenException extends Exception
|
||||
{
|
||||
}
|
|
@ -26,9 +26,9 @@ class UserTableSeeder extends Seeder
|
|||
$user = User::create([
|
||||
'username' => $faker->userName,
|
||||
'email' => $faker->safeEmail,
|
||||
'is_confirmed' => true,
|
||||
'password' => 'password',
|
||||
'join_time' => $faker->dateTimeThisYear,
|
||||
'time_zone' => $faker->timezone
|
||||
'join_time' => $faker->dateTimeThisYear
|
||||
]);
|
||||
|
||||
// Assign the users to the 'Member' group, and possibly some others.
|
||||
|
@ -49,6 +49,7 @@ class UserTableSeeder extends Seeder
|
|||
|
||||
// Guests can view the forum
|
||||
['group.2' , 'forum' , 'view'],
|
||||
['group.2' , 'forum' , 'register'],
|
||||
|
||||
// Members can create and reply to discussions + edit their own stuff
|
||||
['group.3' , 'forum' , 'startDiscussion'],
|
||||
|
|
14
src/Flarum/Core/Users/Commands/ConfirmEmailCommand.php
Normal file
14
src/Flarum/Core/Users/Commands/ConfirmEmailCommand.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php namespace Flarum\Core\Users\Commands;
|
||||
|
||||
class ConfirmEmailCommand
|
||||
{
|
||||
public $userId;
|
||||
|
||||
public $token;
|
||||
|
||||
public function __construct($userId, $token)
|
||||
{
|
||||
$this->userId = $userId;
|
||||
$this->token = $token;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
<?php namespace Flarum\Core\Users\Commands;
|
||||
|
||||
use Laracasts\Commander\CommandHandler;
|
||||
use Laracasts\Commander\Events\DispatchableTrait;
|
||||
use Event;
|
||||
|
||||
use Flarum\Core\Users\UserRepository;
|
||||
|
||||
class ConfirmEmailCommandHandler implements CommandHandler
|
||||
{
|
||||
use DispatchableTrait;
|
||||
|
||||
protected $userRepo;
|
||||
|
||||
public function __construct(UserRepository $userRepo)
|
||||
{
|
||||
$this->userRepo = $userRepo;
|
||||
}
|
||||
|
||||
public function handle($command)
|
||||
{
|
||||
$user = $this->userRepo->findOrFail($command->userId);
|
||||
|
||||
$user->confirmEmail($command->token);
|
||||
|
||||
// If the user hasn't yet had their account activated,
|
||||
if (! $user->join_time) {
|
||||
$user->activate();
|
||||
}
|
||||
|
||||
Event::fire('Flarum.Core.Users.Commands.ConfirmEmail.UserWillBeSaved', [$user, $command]);
|
||||
|
||||
$this->userRepo->save($user);
|
||||
$this->dispatchEventsFor($user);
|
||||
|
||||
return $user;
|
||||
}
|
||||
}
|
11
src/Flarum/Core/Users/Commands/ConfirmEmailValidator.php
Normal file
11
src/Flarum/Core/Users/Commands/ConfirmEmailValidator.php
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?php namespace Flarum\Core\Users\Commands;
|
||||
|
||||
use Flarum\Core\Support\CommandValidator;
|
||||
|
||||
class ConfirmEmailValidator extends CommandValidator
|
||||
{
|
||||
public function validate($command)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -41,7 +41,6 @@ class RegisterUserCommandHandler implements CommandHandler
|
|||
Event::fire('Flarum.Core.Users.Commands.RegisterUser.UserWillBeSaved', [$user, $command]);
|
||||
|
||||
$this->userRepo->save($user);
|
||||
$this->userRepo->syncGroups($user, [3]); // default groups
|
||||
$this->dispatchEventsFor($user);
|
||||
|
||||
return $user;
|
||||
|
|
13
src/Flarum/Core/Users/Events/EmailWasConfirmed.php
Normal file
13
src/Flarum/Core/Users/Events/EmailWasConfirmed.php
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php namespace Flarum\Core\Users\Events;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
|
||||
class EmailWasConfirmed
|
||||
{
|
||||
public $user;
|
||||
|
||||
public function __construct(User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
}
|
13
src/Flarum/Core/Users/Events/UserWasActivated.php
Normal file
13
src/Flarum/Core/Users/Events/UserWasActivated.php
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php namespace Flarum\Core\Users\Events;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
|
||||
class UserWasActivated
|
||||
{
|
||||
public $user;
|
||||
|
||||
public function __construct(User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ use Laracasts\Commander\Events\EventGenerator;
|
|||
use Flarum\Core\Entity;
|
||||
use Flarum\Core\Groups\Group;
|
||||
use Flarum\Core\Support\Exceptions\PermissionDeniedException;
|
||||
use Flarum\Core\Support\Exceptions\InvalidConfirmationTokenException;
|
||||
|
||||
class User extends Entity implements UserInterface, RemindableInterface
|
||||
{
|
||||
|
@ -61,12 +62,20 @@ class User extends Entity implements UserInterface, RemindableInterface
|
|||
|
||||
public function setUsernameAttribute($username)
|
||||
{
|
||||
if ($username === $this->username) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->attributes['username'] = $username;
|
||||
$this->raise(new Events\UserWasRenamed($this));
|
||||
}
|
||||
|
||||
public function setEmailAttribute($email)
|
||||
{
|
||||
if ($email === $this->email) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->attributes['email'] = $email;
|
||||
$this->raise(new Events\EmailWasChanged($this));
|
||||
}
|
||||
|
@ -77,6 +86,14 @@ class User extends Entity implements UserInterface, RemindableInterface
|
|||
$this->raise(new Events\PasswordWasChanged($this));
|
||||
}
|
||||
|
||||
public function activate()
|
||||
{
|
||||
$this->join_time = time();
|
||||
$this->groups()->sync([3]);
|
||||
|
||||
$this->raise(new Events\UserWasActivated($this));
|
||||
}
|
||||
|
||||
public static function register($username, $email, $password)
|
||||
{
|
||||
$user = new static;
|
||||
|
@ -84,13 +101,39 @@ class User extends Entity implements UserInterface, RemindableInterface
|
|||
$user->username = $username;
|
||||
$user->email = $email;
|
||||
$user->password = $password;
|
||||
$user->join_time = time();
|
||||
|
||||
$user->refreshConfirmationToken();
|
||||
|
||||
$user->raise(new Events\UserWasRegistered($user));
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function validateConfirmationToken($token)
|
||||
{
|
||||
return ! $this->is_confirmed
|
||||
&& $token
|
||||
&& $this->confirmation_token === $token;
|
||||
}
|
||||
|
||||
public function refreshConfirmationToken()
|
||||
{
|
||||
$this->is_confirmed = false;
|
||||
$this->confirmation_token = str_random(30);
|
||||
}
|
||||
|
||||
public function confirmEmail($token)
|
||||
{
|
||||
if (! $this->validateConfirmationToken($token)) {
|
||||
throw new InvalidConfirmationTokenException;
|
||||
}
|
||||
|
||||
$this->is_confirmed = true;
|
||||
$this->confirmation_token = null;
|
||||
|
||||
$this->raise(new Events\EmailWasConfirmed($this));
|
||||
}
|
||||
|
||||
public function getDates()
|
||||
{
|
||||
return ['join_time', 'last_seen_time', 'read_time'];
|
||||
|
|
|
@ -17,10 +17,11 @@ class CreateUsersTable extends Migration {
|
|||
$table->increments('id');
|
||||
$table->string('username');
|
||||
$table->string('email');
|
||||
$table->boolean('is_confirmed')->default(0);
|
||||
$table->string('confirmation_token')->nullable();
|
||||
$table->string('password');
|
||||
$table->string('token');
|
||||
$table->dateTime('join_time');
|
||||
$table->string('time_zone');
|
||||
$table->dateTime('join_time')->nullable();
|
||||
$table->dateTime('last_seen_time')->nullable();
|
||||
$table->dateTime('read_time')->nullable();
|
||||
$table->integer('discussions_count')->unsigned()->default(0);
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
<?php
|
||||
|
||||
Route::get('/', function()
|
||||
{
|
||||
Route::get('/', function () {
|
||||
return View::make('flarum.web::index')
|
||||
->with('title', Config::get('flarum::forum_title', 'Flarum Demo Forum'));
|
||||
});
|
||||
|
||||
Route::get('confirm/{id}/{token}', ['as' => 'flarum.confirm', function ($userId, $token) {
|
||||
$command = new Flarum\Core\Users\Commands\ConfirmEmailCommand($userId, $token);
|
||||
|
||||
$commandBus = App::make('Laracasts\Commander\CommandBus');
|
||||
$commandBus->execute($command);
|
||||
}]);
|
||||
|
|
13
src/views/emails/confirm.blade.php
Normal file
13
src/views/emails/confirm.blade.php
Normal file
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<h2>Welcome, {{ $user->username }}</h2>
|
||||
|
||||
<div>
|
||||
To confirm your email, click here: {{ $url }}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user