Permalink
Browse files

http://www.laragle.com/2017/04/twitter-from-scratch-using-laravel-ema…

  • Loading branch information...
darwinluague committed Apr 5, 2017
1 parent 86d10ef commit cd2f2e62137d90f5a0ffc0635e57e481d1ddc747
@@ -0,0 +1,44 @@
<?php
namespace App\Events;
use App\User;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class UserHasRegistered
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* The \App\User instance
*
* @var $user
*/
public $user;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Get the channels the event should broadcast on.
*
* @return Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}
@@ -0,0 +1,29 @@
<?php
namespace App\Http\Controllers\Account\Verification;
use App\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class EmailController extends Controller
{
/**
* Verify user's email address.
*
* @param string $token
* @return [type]
*/
public function verify($token)
{
$user = User::whereEmailVerificationToken($token)->first();
if (is_null($user)) {
return redirect('/home')->with('message', 'The email confirmation link you followed has expired.Click "Resend confirmation" from Settings for a new one.');
}
$user->verifyEmail();
return redirect('/home')->with('message', 'Your account is now verified.');
}
}
@@ -68,6 +68,7 @@ protected function create(array $data)
'last_name' => $data['last_name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
'email_verification_token' => $data['email_verification_token'] ?? str_random(60)
]);
}
}
@@ -0,0 +1,33 @@
<?php
namespace App\Listeners;
use App\Events\UserHasRegistered;
use Illuminate\Support\Facades\Mail;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\Mail\UserHasRegistered as UserHasRegisteredMail;
class SendVerificationEmail
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param UserHasRegistered $event
* @return void
*/
public function handle(UserHasRegistered $event)
{
Mail::to($event->user->email)->send(new UserHasRegisteredMail($event->user));
}
}
@@ -0,0 +1,42 @@
<?php
namespace App\Mail;
use App\User;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class UserHasRegistered extends Mailable
{
use Queueable, SerializesModels;
/**
* The \App\User instance
*
* @var \App\User
*/
public $user;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->subject("Confirm your Twitter account, {$this->user->first_name}")
->markdown('user.email.verification');
}
}
@@ -13,9 +13,9 @@ class EventServiceProvider extends ServiceProvider
* @var array
*/
protected $listen = [
'App\Events\Event' => [
'App\Listeners\EventListener',
],
'App\Events\UserHasRegistered' => [
'App\Listeners\SendVerificationEmail',
]
];
/**
View
@@ -2,6 +2,7 @@
namespace App;
use App\Events\UserHasRegistered;
use Illuminate\Notifications\Notifiable;
use Cviebrock\EloquentSluggable\Sluggable;
use Illuminate\Foundation\Auth\User as Authenticatable;
@@ -16,7 +17,16 @@ class User extends Authenticatable
* @var array
*/
protected $fillable = [
'first_name', 'last_name', 'email', 'password',
'first_name', 'last_name', 'email', 'password', 'email_verification_token',
];
/**
* The event map for the model.
*
* @var array
*/
protected $events = [
'created' => UserHasRegistered::class,
];
/**
@@ -51,4 +61,27 @@ public function sluggable()
]
];
}
/**
* Verify user's email
*
* @return \App\User
*/
public function verifyEmail()
{
$this->email_verification_token = null;
$this->save();
return $this;
}
/**
* Get the email verification url.
*
* @return string
*/
public function getEmailVerificationUrlAttribute()
{
return route('account.verify.email', ['token' => $this->email_verification_token]);
}
}
View
@@ -26,7 +26,10 @@
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"files": [
"tests/MailTracking.php"
]
},
"scripts": {
"post-root-package-install": [
@@ -21,6 +21,7 @@
'email' => $faker->unique()->safeEmail,
'password' => $password ?: $password = bcrypt('secret'),
'remember_token' => str_random(10),
'email_verification_token' => str_random(60),
];
});
@@ -20,6 +20,7 @@ public function up()
$table->string('last_name');
$table->string('email')->unique();
$table->string('password');
$table->string('email_verification_token')->nullable();
$table->rememberToken();
$table->timestamps();
});
View
@@ -28,5 +28,6 @@
<env name="CACHE_DRIVER" value="array"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="QUEUE_DRIVER" value="sync"/>
<env name="MAIL_DRIVER" value="log"/>
</php>
</phpunit>
@@ -77,7 +77,9 @@
</div>
</div>
</nav>
@if (session()->has('message'))
<div class="alert alert-info">{{ session('message') }}</div>
@endif
@yield('content')
</div>
@@ -0,0 +1,12 @@
@component('mail::message')
# Final step...
Confirm your email address to complete your Twitter account {{ $user->username }}. It's easy — just click the button below.
@component('mail::button', ['url' => $user->email_verification_url])
Confirm now
@endcomponent
Thanks,<br>
{{ config('app.name') }}
@endcomponent
View
@@ -19,6 +19,12 @@
Route::get('/home', 'HomeController@index');
Route::group(['prefix' => 'account', 'namespace' => 'Account', 'as' => 'account.'], function () {
Route::group(['prefix' => 'verify', 'namespace' => 'Verification', 'as' => 'verify.'], function () {
Route::get('email/{token}', 'EmailController@verify')->name('email');
});
});
Route::group(['prefix' => '{username}', 'namespace' => 'User'], function () {
Route::resource('tweet', 'TweetController');
});
View
@@ -7,7 +7,7 @@
class UserTest extends TestCase
{
use DatabaseMigrations;
use DatabaseMigrations, \MailTracking;
/** @test */
public function a_user_can_view_a_tweet()
@@ -38,4 +38,35 @@ public function a_user_can_register()
$response->assertRedirect('/home');
}
/** @test */
public function a_confirmation_email_must_be_sent_after_registration()
{
$email = 'johndoe@gmail.com';
$token = str_random(60);
$response = $this->post('/register', [
'first_name' => 'John',
'last_name' => 'Doe',
'email' => $email,
'password' => 'secret',
'password_confirmation' => 'secret',
'email_verification_token' => $token
]);
$this->seeEmailWasSent()
->seeEmailSubject("Confirm your Twitter account, John")
->seeEmailTo('johndoe@gmail.com')
->seeEmailContains(route('account.verify.email', ['token' => $token]));
}
/** @test */
public function a_user_can_verify_their_email()
{
$user = factory('App\User')->create();
$this->actingAs($user)->get(route('account.verify.email', ['token' => $user->email_verification_token]));
$this->assertNull($user->fresh()->email_verification_token);
}
}
Oops, something went wrong.

0 comments on commit cd2f2e6

Please sign in to comment.