├── .gitignore
├── .travis.yml
├── LICENSE.md
├── README.md
├── composer.json
├── phpunit.xml
├── src
├── Krucas
│ └── LaravelUserEmailVerification
│ │ ├── AuthenticatesAndRegistersUsers.php
│ │ ├── AuthenticatesUsers.php
│ │ ├── Console
│ │ ├── ClearVerificationTokensCommand.php
│ │ ├── MakeVerificationCommand.php
│ │ └── stubs
│ │ │ ├── controllers
│ │ │ └── verifycontroller.stub
│ │ │ ├── migrations
│ │ │ ├── users.stub
│ │ │ └── users_verifications.stub
│ │ │ └── routes.stub
│ │ ├── Contracts
│ │ ├── Factory.php
│ │ ├── RequiresEmailVerification.php
│ │ ├── TokenRepositoryInterface.php
│ │ └── VerificationBroker.php
│ │ ├── DatabaseTokenRepository.php
│ │ ├── Facades
│ │ └── Verification.php
│ │ ├── RedirectsUsers.php
│ │ ├── RegistersUsers.php
│ │ ├── RequiresEmailVerification.php
│ │ ├── UserEmailVerificationServiceProvider.php
│ │ ├── VerificationBroker.php
│ │ ├── VerificationBrokerManager.php
│ │ └── VerifiesUsers.php
├── config
│ └── verification.php
├── translations
│ └── en
│ │ └── verification.php
└── views
│ └── auth
│ ├── emails
│ └── verification.blade.php
│ └── verification
│ ├── message.blade.php
│ └── resend.blade.php
└── tests
├── AuthenticatesUsersTest.php
├── DatabaseTokenRepositoryTest.php
├── RedirectsUsersTest.php
├── RegistersUsersTest.php
├── TestCase.php
├── VerificationBrokerTest.php
└── VerifiesUsersTest.php
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | vendor
3 | composer.lock
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | - 5.5
5 | - 5.6
6 | - 7.0
7 | - hhvm
8 |
9 | before_script:
10 | - curl -s http://getcomposer.org/installer | php
11 | - php composer.phar install --dev
12 |
13 | script: phpunit
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (C) 2016 Edvinas Kručas
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # User email verification for Laravel 5
2 |
3 |
4 | [](https://travis-ci.org/edvinaskrucas/laravel-user-email-verification)
5 |
6 | ---
7 |
8 | ## Installation
9 |
10 | Require this package in your composer.json by typing in your console:
11 |
12 | ```
13 | composer require edvinaskrucas/laravel-user-email-verification
14 | ```
15 |
16 | ### Registering to use it with laravel
17 |
18 | Add following lines to ```app/config/app.php```
19 |
20 | ServiceProvider array
21 |
22 | ```php
23 | Krucas\LaravelUserEmailVerification\UserEmailVerificationServiceProvider::class,
24 | ```
25 |
26 | ### Publishing config file
27 |
28 | If you want to edit default config file, just publish it to your app folder.
29 |
30 | php artisan vendor:publish --provider="Krucas\LaravelUserEmailVerification\UserEmailVerificationServiceProvider" --tag="config"
31 |
32 |
33 | ### Publishing translations
34 |
35 | In order to customise translations you need to publish it.
36 |
37 | php artisan vendor:publish --provider="Krucas\LaravelUserEmailVerification\UserEmailVerificationServiceProvider" --tag="translations"
38 |
39 |
40 | ### Publishing views
41 |
42 | Package comes with default views, if you want to edit them, just publish it.
43 |
44 | php artisan vendor:publish --provider="Krucas\LaravelUserEmailVerification\UserEmailVerificationServiceProvider" --tag="views"
45 |
46 | ## Usage
47 |
48 | ### Configuration
49 |
50 | Package comes with several configuration options.
51 |
52 | | Setting | Description |
53 | | --- | --- |
54 | | ```default``` | Default broker driver. |
55 | | ```verify``` | MUST or MUST NOT user validate his account before login. |
56 | | ```repositories``` | Config of all repositories which can be used. |
57 | | ```brokers``` | Config of all brokers which can be used. |
58 |
59 | ### Install default controller, routes and migrations
60 |
61 | ```
62 | php artisan verification:make
63 | ```
64 |
65 | Command above will add default ```VerifyController``` to ```app/Http/Controllers/Auth/VerifyController.php``` which
66 | will provide default verification behaviour.
67 |
68 | Also routes will be modified, it will add default routes for verification controller.
69 |
70 | Migrations will add extra columns to ```users``` table to identify if user is verified or not, also
71 | token table will be added to store verification tokens.
72 |
73 | After running command you have to install new migrations, this can be done with this command:
74 |
75 | ```
76 | php artisan migrate
77 | ```
78 |
79 | After all these steps you need to adjust default auth controller provided by Laravel, these adjustments
80 | will enable authentication controller to send verification email and will not allow non-verified users to login.
81 |
82 | ### Clear expired tokens
83 |
84 | Package comes with useful command to clear expired tokens, just replace ```{broker}``` with your broker name.
85 |
86 | ```
87 | php artisan verification:clear-tokens {broker}
88 | ```
89 |
90 | ---
91 |
92 | More info can be found here: [http://www.krucas.com/2016/04/user-email-verification-for-laravel-5/](http://www.krucas.com/2016/04/user-email-verification-for-laravel-5/)
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "edvinaskrucas/laravel-user-email-verification",
3 | "keywords": ["laravel", "user verification", "email verification", "user email verification"],
4 | "description": "Laravel Package for easier user email verification.",
5 | "authors": [
6 | {
7 | "name": "Edvinas Kručas",
8 | "email": "edv.krucas@gmail.com"
9 | }
10 | ],
11 | "license": "MIT",
12 | "require": {
13 | "php" : "^5.5|^7.0",
14 | "illuminate/support": "^5.2",
15 | "illuminate/console": "^5.2",
16 | "illuminate/database": "^5.2",
17 | "illuminate/filesystem": "^5.2",
18 | "illuminate/http": "^5.2",
19 | "illuminate/mail": "^5.2"
20 | },
21 | "require-dev": {
22 | "mockery/mockery": "0.9.*",
23 | "laravel/framework": "^5.2",
24 | "phpunit/phpunit": "^4.8"
25 | },
26 | "autoload": {
27 | "psr-0": {
28 | "Krucas\\LaravelUserEmailVerification": "src/"
29 | }
30 | },
31 | "autoload-dev": {
32 | "psr-4": {
33 | "Krucas\\LaravelUserEmailVerification\\Test\\": "tests"
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
17 |
18 | ./tests/
19 |
20 |
21 |
22 |
23 | ./src/Krucas/
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/Krucas/LaravelUserEmailVerification/AuthenticatesAndRegistersUsers.php:
--------------------------------------------------------------------------------
1 | isUserEmailVerified()) {
24 | Auth::guard($this->getGuard())->logout();
25 |
26 | return redirect($this->verificationRedirectPath());
27 | }
28 |
29 | return redirect()->intended($this->redirectPath());
30 | }
31 |
32 | /**
33 | * Get the guard to be used during verification.
34 | *
35 | * @return string|null
36 | */
37 | protected function getGuard()
38 | {
39 | return property_exists($this, 'guard') ? $this->guard : null;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/Krucas/LaravelUserEmailVerification/Console/ClearVerificationTokensCommand.php:
--------------------------------------------------------------------------------
1 | laravel['auth.verification']->broker($this->argument('name'))->getRepository()->deleteExpired();
31 | $this->info('Expired verification tokens cleared!');
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Krucas/LaravelUserEmailVerification/Console/MakeVerificationCommand.php:
--------------------------------------------------------------------------------
1 | composer = $composer;
42 | }
43 |
44 | /**
45 | * Execute the console command.
46 | *
47 | * @return void
48 | */
49 | public function fire()
50 | {
51 | $this->createMigrations();
52 |
53 | $this->info('Installed VerifyController');
54 |
55 | file_put_contents(
56 | app_path('Http/Controllers/Auth/VerifyController.php'),
57 | $this->compileControllerStub()
58 | );
59 |
60 | $this->info('Updated routes.php');
61 |
62 | $this->appendRoutes();
63 |
64 | $this->composer->dumpAutoloads();
65 | }
66 |
67 | /**
68 | * Create migrations.
69 | *
70 | * @return void
71 | */
72 | protected function createMigrations()
73 | {
74 | file_put_contents(
75 | $this->createUsersVerificationsMigration(),
76 | file_get_contents(__DIR__.'/stubs/migrations/users_verifications.stub')
77 | );
78 |
79 | file_put_contents(
80 | $this->createUsersMigration(),
81 | file_get_contents(__DIR__.'/stubs/migrations/users.stub')
82 | );
83 |
84 | $this->info('Migrations created successfully!');
85 | }
86 |
87 | /**
88 | * Create a base migration file for the verifications table.
89 | *
90 | * @return string
91 | */
92 | protected function createUsersVerificationsMigration()
93 | {
94 | $name = 'create_users_verifications_table';
95 |
96 | $path = $this->laravel->databasePath().'/migrations';
97 |
98 | return $this->laravel['migration.creator']->create($name, $path);
99 | }
100 |
101 | /**
102 | * Create a base migration file for the users table.
103 | *
104 | * @return string
105 | */
106 | protected function createUsersMigration()
107 | {
108 | $name = 'add_verified_columns_to_users_table';
109 |
110 | $path = $this->laravel->databasePath().'/migrations';
111 |
112 | return $this->laravel['migration.creator']->create($name, $path);
113 | }
114 |
115 | /**
116 | * Compiles the VerifyController stub.
117 | *
118 | * @return string
119 | */
120 | protected function compileControllerStub()
121 | {
122 | return str_replace(
123 | '{{namespace}}',
124 | $this->getAppNamespace(),
125 | file_get_contents(__DIR__.'/stubs/controllers/verifycontroller.stub')
126 | );
127 | }
128 |
129 | /**
130 | * Append routes file.
131 | *
132 | * @return void
133 | */
134 | protected function appendRoutes()
135 | {
136 | $path = app_path('Http/routes.php');
137 |
138 | file_put_contents(
139 | $path,
140 | file_get_contents($path)."\n\n".file_get_contents(__DIR__.'/stubs/routes.stub')
141 | );
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/src/Krucas/LaravelUserEmailVerification/Console/stubs/controllers/verifycontroller.stub:
--------------------------------------------------------------------------------
1 | middleware($this->guestMiddleware());
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/Krucas/LaravelUserEmailVerification/Console/stubs/migrations/users.stub:
--------------------------------------------------------------------------------
1 | boolean('verified')->default(0)->after('password');
17 | $table->timestamp('verified_at')->nullable(true)->default(null)->after('verified');
18 | });
19 | }
20 |
21 | /**
22 | * Reverse the migrations.
23 | *
24 | * @return void
25 | */
26 | public function down()
27 | {
28 | Schema::table('users', function (Blueprint $table) {
29 | $table->dropColumn('verified');
30 | $table->dropColumn('verified_at');
31 | });
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Krucas/LaravelUserEmailVerification/Console/stubs/migrations/users_verifications.stub:
--------------------------------------------------------------------------------
1 | string('email')->index();
17 | $table->string('token')->index();
18 | $table->timestamp('created_at');
19 | });
20 | }
21 |
22 | /**
23 | * Reverse the migrations.
24 | *
25 | * @return void
26 | */
27 | public function down()
28 | {
29 | Schema::drop('users_verifications');
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Krucas/LaravelUserEmailVerification/Console/stubs/routes.stub:
--------------------------------------------------------------------------------
1 | // verification token resend form
2 | Route::get('verify/resend', [
3 | 'uses' => 'Auth\VerifyController@showResendForm',
4 | 'as' => 'verification.resend',
5 | ]);
6 |
7 | // verification token resend action
8 | Route::post('verify/resend', [
9 | 'uses' => 'Auth\VerifyController@sendVerificationLinkEmail',
10 | 'as' => 'verification.resend.post',
11 | ]);
12 |
13 | // verification message / user verification
14 | Route::get('verify/{token?}', [
15 | 'uses' => 'Auth\VerifyController@verify',
16 | 'as' => 'verification.verify',
17 | ]);
--------------------------------------------------------------------------------
/src/Krucas/LaravelUserEmailVerification/Contracts/Factory.php:
--------------------------------------------------------------------------------
1 | table = $table;
51 | $this->hashKey = $hashKey;
52 | $this->expires = $expires;
53 | $this->connection = $connection;
54 | }
55 |
56 | /**
57 | * Create a new token.
58 | *
59 | * @param \Krucas\LaravelUserEmailVerification\Contracts\RequiresEmailVerification $user
60 | * @return string
61 | */
62 | public function create(Contracts\RequiresEmailVerification $user)
63 | {
64 | $email = $user->getEmailForVerification();
65 |
66 | $this->deleteExisting($user);
67 |
68 | $token = $this->createNewToken();
69 |
70 | $this->getTable()->insert($this->getPayload($email, $token));
71 |
72 | return $token;
73 | }
74 |
75 | /**
76 | * Delete all existing reset tokens from the database.
77 | *
78 | * @param \Krucas\LaravelUserEmailVerification\Contracts\RequiresEmailVerification $user
79 | * @return int
80 | */
81 | protected function deleteExisting(Contracts\RequiresEmailVerification $user)
82 | {
83 | return $this->getTable()->where('email', $user->getEmailForVerification())->delete();
84 | }
85 |
86 | /**
87 | * Build the record payload for the table.
88 | *
89 | * @param string $email
90 | * @param string $token
91 | * @return array
92 | */
93 | protected function getPayload($email, $token)
94 | {
95 | return ['email' => $email, 'token' => $token, 'created_at' => new Carbon];
96 | }
97 |
98 | /**
99 | * Determine if a token record exists and is valid.
100 | *
101 | * @param \Krucas\LaravelUserEmailVerification\Contracts\RequiresEmailVerification $user
102 | * @param string $token
103 | * @return bool
104 | */
105 | public function exists(Contracts\RequiresEmailVerification $user, $token)
106 | {
107 | $email = $user->getEmailForVerification();
108 |
109 | $token = (array) $this->getTable()->where('email', $email)->where('token', $token)->first();
110 |
111 | return $token && !$this->tokenExpired($token);
112 | }
113 |
114 | /**
115 | * Determine if the token has expired.
116 | *
117 | * @param array $token
118 | * @return bool
119 | */
120 | protected function tokenExpired($token)
121 | {
122 | if (!$this->isExpirationEnabled()) {
123 | return false;
124 | }
125 |
126 | $expirationTime = strtotime($token['created_at']) + $this->expires;
127 |
128 | return $expirationTime < $this->getCurrentTime();
129 | }
130 |
131 | /**
132 | * Get the current UNIX timestamp.
133 | *
134 | * @return int
135 | */
136 | protected function getCurrentTime()
137 | {
138 | return time();
139 | }
140 |
141 | /**
142 | * Delete token record.
143 | *
144 | * @param string $token
145 | * @return void
146 | */
147 | public function delete($token)
148 | {
149 | $this->getTable()->where('token', $token)->delete();
150 | }
151 |
152 | /**
153 | * Delete expired tokens.
154 | *
155 | * @return void
156 | */
157 | public function deleteExpired()
158 | {
159 | if ($this->isExpirationEnabled()) {
160 | $expiredAt = Carbon::now()->subSeconds($this->expires);
161 |
162 | $this->getTable()->where('created_at', '<', $expiredAt)->delete();
163 | }
164 | }
165 |
166 | /**
167 | * Create a new token for the user.
168 | *
169 | * @return string
170 | */
171 | public function createNewToken()
172 | {
173 | return hash_hmac('sha256', Str::random(40), $this->hashKey);
174 | }
175 |
176 | /**
177 | * Begin a new database query against the table.
178 | *
179 | * @return \Illuminate\Database\Query\Builder
180 | */
181 | protected function getTable()
182 | {
183 | return $this->connection->table($this->table);
184 | }
185 |
186 | /**
187 | * Determine if token expiration is enabled or disabled.
188 | *
189 | * @return bool
190 | */
191 | protected function isExpirationEnabled()
192 | {
193 | return $this->expires > 0;
194 | }
195 |
196 | /**
197 | * Get the database connection instance.
198 | *
199 | * @return \Illuminate\Database\ConnectionInterface
200 | */
201 | public function getConnection()
202 | {
203 | return $this->connection;
204 | }
205 | }
206 |
--------------------------------------------------------------------------------
/src/Krucas/LaravelUserEmailVerification/Facades/Verification.php:
--------------------------------------------------------------------------------
1 | verificationRedirectPath;
16 | }
17 |
18 | return property_exists($this, 'verificationRedirectTo')
19 | ? $this->verificationRedirectTo : route('verification.verify', [], false);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/Krucas/LaravelUserEmailVerification/RegistersUsers.php:
--------------------------------------------------------------------------------
1 | validator($request->all());
23 |
24 | if ($validator->fails()) {
25 | $this->throwValidationException($request, $validator);
26 | }
27 |
28 | $user = $this->create($request->all());
29 |
30 | $broker = $this->getBroker();
31 |
32 | $credentials = $request->only('email');
33 |
34 | Verification::broker($broker)->sendVerificationLink($credentials, function (Message $message) {
35 | $message->subject($this->getEmailSubject());
36 | });
37 |
38 | if (config('verification.verify')) {
39 | return redirect($this->verificationRedirectPath());
40 | }
41 |
42 | Auth::guard($this->getGuard())->login($user);
43 |
44 | return redirect($this->redirectPath());
45 | }
46 |
47 | /**
48 | * Get the broker to be used during verification process.
49 | *
50 | * @return string|null
51 | */
52 | public function getBroker()
53 | {
54 | return property_exists($this, 'broker') ? $this->broker : null;
55 | }
56 |
57 | /**
58 | * Get the guard to be used during verification.
59 | *
60 | * @return string|null
61 | */
62 | protected function getGuard()
63 | {
64 | return property_exists($this, 'guard') ? $this->guard : null;
65 | }
66 |
67 | /**
68 | * Get the e-mail subject line to be used for the reset link email.
69 | *
70 | * @return string
71 | */
72 | protected function getEmailSubject()
73 | {
74 | return trans('verification::verification.subject');
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/Krucas/LaravelUserEmailVerification/RequiresEmailVerification.php:
--------------------------------------------------------------------------------
1 | email;
15 | }
16 |
17 | /**
18 | * Determine if user is verified or not.
19 | *
20 | * @return bool
21 | */
22 | public function isUserEmailVerified()
23 | {
24 | return (bool) $this->verified;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/Krucas/LaravelUserEmailVerification/UserEmailVerificationServiceProvider.php:
--------------------------------------------------------------------------------
1 | [VerificationBrokerManager::class, Contracts\Factory::class],
19 | 'auth.verification.broker' => [VerificationBroker::class, Contracts\VerificationBroker::class],
20 | ];
21 |
22 | /**
23 | * Boot service provider.
24 | *
25 | * @return void
26 | */
27 | public function boot()
28 | {
29 | $this->loadTranslationsFrom(__DIR__ . '/../../translations', 'verification');
30 | $this->loadViewsFrom(__DIR__ . '/../../views', 'verification');
31 |
32 | $this->publishes([
33 | __DIR__ . '/../../config/verification.php' => config_path('verification.php'),
34 | ], 'config');
35 |
36 | $this->publishes([
37 | __DIR__ . '/../../translations' => resource_path('lang/vendor/verification'),
38 | ], 'translations');
39 |
40 | $this->publishes([
41 | __DIR__ . '/../../views' => resource_path('views/vendor/verification'),
42 | ], 'views');
43 | }
44 |
45 | /**
46 | * Register the service provider.
47 | *
48 | * @return void
49 | */
50 | public function register()
51 | {
52 | $this->mergeConfigFrom(__DIR__ . '/../../config/verification.php', 'verification');
53 |
54 | $this->app->singleton('auth.verification', function ($app) {
55 | return new VerificationBrokerManager($app);
56 | });
57 |
58 | $this->app->bind('auth.verification.broker', function ($app) {
59 | return $app->make('auth.verification')->broker();
60 | });
61 |
62 | foreach ($this->aliases as $key => $aliases) {
63 | foreach ($aliases as $alias) {
64 | $this->app->alias($key, $alias);
65 | }
66 | }
67 |
68 | $this->registerCommands();
69 | }
70 |
71 | /**
72 | * Register the related console commands.
73 | *
74 | * @return void
75 | */
76 | protected function registerCommands()
77 | {
78 | $this->app->singleton('command.verification.make', function ($app) {
79 | return new MakeVerificationCommand($app['composer']);
80 | });
81 |
82 | $this->app->singleton('command.verification.clear', function ($app) {
83 | return new ClearVerificationTokensCommand();
84 | });
85 |
86 | $this->commands('command.verification.make');
87 | $this->commands('command.verification.clear');
88 | }
89 |
90 | /**
91 | * Get the services provided by the provider.
92 | *
93 | * @return array
94 | */
95 | public function provides()
96 | {
97 | return [
98 | 'command.verification.make',
99 | 'command.verification.clear',
100 | 'auth.verification',
101 | 'auth.verification.broker',
102 | VerificationBrokerManager::class,
103 | Contracts\Factory::class,
104 | VerificationBroker::class,
105 | Contracts\VerificationBroker::class,
106 | ];
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/Krucas/LaravelUserEmailVerification/VerificationBroker.php:
--------------------------------------------------------------------------------
1 | tokens = $tokens;
51 | $this->users = $users;
52 | $this->mailer = $mailer;
53 | $this->emailView = $emailView;
54 | }
55 |
56 | /**
57 | * Send a user verification link.
58 | *
59 | * @param array $credentials
60 | * @param \Closure|null $callback
61 | * @return string
62 | */
63 | public function sendVerificationLink(array $credentials, Closure $callback = null)
64 | {
65 | $user = $this->getUser($credentials);
66 |
67 | if (is_null($user)) {
68 | return Contracts\VerificationBroker::INVALID_USER;
69 | }
70 |
71 | $token = $this->tokens->create($user);
72 |
73 | $this->emailVerificationLink($user, $token, $callback);
74 |
75 | return Contracts\VerificationBroker::VERIFICATION_LINK_SENT;
76 | }
77 |
78 | /**
79 | * Send the email verification link via e-mail.
80 | *
81 | * @param \Krucas\LaravelUserEmailVerification\Contracts\RequiresEmailVerification $user
82 | * @param string $token
83 | * @param \Closure|null $callback
84 | * @return int
85 | */
86 | public function emailVerificationLink(Contracts\RequiresEmailVerification $user, $token, Closure $callback = null)
87 | {
88 | $view = $this->emailView;
89 |
90 | return $this->mailer->send($view, compact('token', 'user'), function ($message) use ($user, $token, $callback) {
91 | $message->to($user->getEmailForVerification());
92 |
93 | if (!is_null($callback)) {
94 | call_user_func($callback, $message, $user, $token);
95 | }
96 | });
97 | }
98 |
99 | /**
100 | * Verify given account.
101 | *
102 | * @param array $credentials
103 | * @param \Closure $callback
104 | * @return mixed
105 | */
106 | public function verify(array $credentials, Closure $callback)
107 | {
108 | $user = $this->validateVerification($credentials);
109 |
110 | if (!$user instanceof Contracts\RequiresEmailVerification) {
111 | return $user;
112 | }
113 |
114 | call_user_func($callback, $user);
115 |
116 | $this->tokens->delete($credentials['token']);
117 |
118 | return Contracts\VerificationBroker::VERIFIED;
119 | }
120 |
121 | /**
122 | * Validate verification for the given credentials.
123 | *
124 | * @param array $credentials
125 | * @return \Krucas\LaravelUserEmailVerification\Contracts\RequiresEmailVerification
126 | */
127 | protected function validateVerification(array $credentials)
128 | {
129 | if (is_null($user = $this->getUser($credentials))) {
130 | return Contracts\VerificationBroker::INVALID_USER;
131 | }
132 |
133 | if (!$this->tokens->exists($user, $credentials['token'])) {
134 | return Contracts\VerificationBroker::INVALID_TOKEN;
135 | }
136 |
137 | return $user;
138 | }
139 |
140 | /**
141 | * Get the user for the given credentials.
142 | *
143 | * @param array $credentials
144 | * @return \Krucas\LaravelUserEmailVerification\Contracts\RequiresEmailVerification
145 | *
146 | * @throws \UnexpectedValueException
147 | */
148 | public function getUser(array $credentials)
149 | {
150 | $credentials = Arr::except($credentials, ['token']);
151 |
152 | $user = $this->users->retrieveByCredentials($credentials);
153 |
154 | if ($user && !$user instanceof Contracts\RequiresEmailVerification) {
155 | throw new UnexpectedValueException('User must implement RequiresEmailVerification interface.');
156 | }
157 |
158 | return $user;
159 | }
160 |
161 | /**
162 | * Get the verification token repository implementation.
163 | *
164 | * @return \Krucas\LaravelUserEmailVerification\Contracts\TokenRepositoryInterface
165 | */
166 | public function getRepository()
167 | {
168 | return $this->tokens;
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/src/Krucas/LaravelUserEmailVerification/VerificationBrokerManager.php:
--------------------------------------------------------------------------------
1 | app = $app;
40 | }
41 |
42 | /**
43 | * Get a verification broker instance by name.
44 | *
45 | * @param string|null $name
46 | * @return mixed
47 | */
48 | public function broker($name = null)
49 | {
50 | $name = $name ?: $this->getDefaultDriver();
51 |
52 | return $this->brokers[$name] = $this->get($name);
53 | }
54 |
55 | /**
56 | * Attempt to get the broker from the local cache.
57 | *
58 | * @param string $name
59 | * @return \Krucas\LaravelUserEmailVerification\Contracts\VerificationBroker
60 | */
61 | protected function get($name)
62 | {
63 | return isset($this->brokers[$name]) ? $this->brokers[$name] : $this->resolve($name);
64 | }
65 |
66 | /**
67 | * Resolve the given broker.
68 | *
69 | * @param string $name
70 | * @return \Krucas\LaravelUserEmailVerification\Contracts\VerificationBroker
71 | */
72 | protected function resolve($name)
73 | {
74 | $config = $this->getConfig($name);
75 |
76 | if (is_null($config)) {
77 | throw new InvalidArgumentException("Verification broker [{$name}] is not defined.");
78 | }
79 |
80 | if (isset($this->customCreators[$name])) {
81 | return $this->callCustomCreator($name, $config);
82 | } else {
83 | return $this->{'create'.ucfirst($name).'Broker'}($config);
84 | }
85 | }
86 |
87 | /**
88 | * Call a custom driver creator.
89 | *
90 | * @param string $name
91 | * @param array $config
92 | * @return mixed
93 | */
94 | protected function callCustomCreator($name, array $config)
95 | {
96 | return $this->customCreators[$name]($this->app, $config);
97 | }
98 |
99 | /**
100 | * Create users broker.
101 | *
102 | * @param array $config
103 | * @return \Krucas\LaravelUserEmailVerification\Contracts\VerificationBroker
104 | */
105 | protected function createUsersBroker(array $config)
106 | {
107 | return new VerificationBroker(
108 | $this->createTokenRepository($this->app['config']['verification.repositories.'.$config['repository']]),
109 | $this->app['auth']->createUserProvider($config['provider']),
110 | $this->app['mailer'],
111 | $config['email']
112 | );
113 | }
114 |
115 | /**
116 | * Create token repository
117 | *
118 | * @param array $config
119 | * @return \Krucas\LaravelUserEmailVerification\Contracts\TokenRepositoryInterface
120 | */
121 | protected function createTokenRepository(array $config)
122 | {
123 | return $this->{'create'.ucfirst($config['driver']).'Repository'}($config);
124 | }
125 |
126 | /**
127 | * Create database token repository.
128 | *
129 | * @param array $config
130 | * @return \Krucas\LaravelUserEmailVerification\Contracts\TokenRepositoryInterface
131 | */
132 | protected function createDatabaseRepository(array $config)
133 | {
134 | return new DatabaseTokenRepository(
135 | $this->app['db']->connection($config['connection']),
136 | $config['table'],
137 | $this->app['config']['app.key'],
138 | $config['expires']
139 | );
140 | }
141 |
142 | /**
143 | * Get the broker configuration.
144 | *
145 | * @param string $name
146 | * @return array
147 | */
148 | protected function getConfig($name)
149 | {
150 | return $this->app['config']["verification.brokers.{$name}"];
151 | }
152 |
153 | /**
154 | * Get the default settings repository name.
155 | *
156 | * @return string
157 | */
158 | public function getDefaultDriver()
159 | {
160 | return $this->app['config']['verification.default'];
161 | }
162 |
163 | /**
164 | * Set the default driver name.
165 | *
166 | * @param string $name
167 | * @return void
168 | */
169 | public function setDefaultDriver($name)
170 | {
171 | $this->app['config']['verification.default'] = $name;
172 | }
173 |
174 | /**
175 | * Register a custom driver creator Closure.
176 | *
177 | * @param string $driver
178 | * @param \Closure $callback
179 | * @return $this
180 | */
181 | public function extend($driver, Closure $callback)
182 | {
183 | $this->customCreators[$driver] = $callback;
184 |
185 | return $this;
186 | }
187 |
188 | /**
189 | * Dynamically call the default driver instance.
190 | *
191 | * @param string $method
192 | * @param array $parameters
193 | * @return mixed
194 | */
195 | public function __call($method, $parameters)
196 | {
197 | return call_user_func_array([$this->broker(), $method], $parameters);
198 | }
199 | }
200 |
--------------------------------------------------------------------------------
/src/Krucas/LaravelUserEmailVerification/VerifiesUsers.php:
--------------------------------------------------------------------------------
1 | verify($request, $token);
26 | }
27 |
28 | /**
29 | * Display verify message / verify account.
30 | *
31 | * @param Request $request
32 | * @param null $token
33 | * @return \Illuminate\Http\Response
34 | */
35 | public function verify(Request $request, $token = null)
36 | {
37 | if (is_null($token)) {
38 | return $this->showVerifyMessage();
39 | }
40 |
41 | $credentials = ['email' => $request->get('email'), 'token' => $token];
42 |
43 | $broker = $this->getBroker();
44 |
45 | $response = Verification::broker($broker)->verify($credentials, function ($user) {
46 | $this->verifyUser($user);
47 | });
48 |
49 | switch ($response) {
50 | case Contracts\VerificationBroker::VERIFIED:
51 | return $this->getVerificationSuccessResponse($response);
52 |
53 | default:
54 | return $this->getVerificationFailureResponse($request, $response);
55 | }
56 | }
57 |
58 | /**
59 | * Verify user.
60 | *
61 | * @param \Krucas\LaravelUserEmailVerification\Contracts\RequiresEmailVerification $user
62 | * @return void
63 | */
64 | protected function verifyUser($user)
65 | {
66 | $user->verified = true;
67 | $user->verified_at = new Carbon('now');
68 |
69 | $user->save();
70 |
71 | Auth::guard($this->getGuard())->login($user);
72 | }
73 |
74 | /**
75 | * Display verify message.
76 | *
77 | * @return \Illuminate\Http\Response
78 | */
79 | public function showVerifyMessage()
80 | {
81 | return view('verification::auth.verification.message');
82 | }
83 |
84 | /**
85 | * Display link resend form.
86 | *
87 | * @return \Illuminate\Http\Response
88 | */
89 | public function getResend()
90 | {
91 | return $this->showResendForm();
92 | }
93 |
94 | /**
95 | * Display link resend form.
96 | *
97 | * @return \Illuminate\Http\Response
98 | */
99 | public function showResendForm()
100 | {
101 | return view('verification::auth.verification.resend');
102 | }
103 |
104 | /**
105 | * Send a verification link to the given user.
106 | *
107 | * @param \Illuminate\Http\Request $request
108 | * @return \Illuminate\Http\Response
109 | */
110 | public function postResend(Request $request)
111 | {
112 | return $this->sendVerificationLinkEmail($request);
113 | }
114 |
115 | /**
116 | * Send a verification link to the given user.
117 | *
118 | * @param \Illuminate\Http\Request $request
119 | * @return \Illuminate\Http\Response
120 | */
121 | public function sendVerificationLinkEmail(Request $request)
122 | {
123 | $this->validate($request, ['email' => 'required|email']);
124 |
125 | $broker = $this->getBroker();
126 |
127 | $credentials = $request->only('email');
128 |
129 | $response = Verification::broker($broker)->sendVerificationLink($credentials, function (Message $message) {
130 | $message->subject($this->getEmailSubject());
131 | });
132 |
133 | switch ($response) {
134 | case Contracts\VerificationBroker::VERIFICATION_LINK_SENT:
135 | return $this->getResendLinkEmailSuccessResponse($response);
136 |
137 | default:
138 | return $this->getResendLinkEmailFailureResponse($response);
139 | }
140 | }
141 |
142 | /**
143 | * Get the response for after the link could not be sent.
144 | *
145 | * @param string $response
146 | * @return \Symfony\Component\HttpFoundation\Response
147 | */
148 | protected function getResendLinkEmailFailureResponse($response)
149 | {
150 | return redirect()->back()->withErrors(['email' => trans($response)]);
151 | }
152 |
153 | /**
154 | * Get the response for after the link has been successfully sent.
155 | *
156 | * @param string $response
157 | * @return \Symfony\Component\HttpFoundation\Response
158 | */
159 | protected function getResendLinkEmailSuccessResponse($response)
160 | {
161 | return redirect()->back()->with('status', trans($response));
162 | }
163 |
164 | /**
165 | * Get the broker to be used during verification process.
166 | *
167 | * @return string|null
168 | */
169 | public function getBroker()
170 | {
171 | return property_exists($this, 'broker') ? $this->broker : null;
172 | }
173 |
174 | /**
175 | * Get the guard to be used during verification.
176 | *
177 | * @return string|null
178 | */
179 | protected function getGuard()
180 | {
181 | return property_exists($this, 'guard') ? $this->guard : null;
182 | }
183 |
184 | /**
185 | * Get the e-mail subject line to be used for the reset link email.
186 | *
187 | * @return string
188 | */
189 | protected function getEmailSubject()
190 | {
191 | return trans('verification::verification.subject');
192 | }
193 |
194 | /**
195 | * Get the response for after a successful verification.
196 | *
197 | * @param string $response
198 | * @return \Symfony\Component\HttpFoundation\Response
199 | */
200 | protected function getVerificationSuccessResponse($response)
201 | {
202 | return redirect($this->verificationRedirectPath())->with('status', trans($response));
203 | }
204 |
205 | /**
206 | * Get the response for after a failing verification.
207 | *
208 | * @param Request $request
209 | * @param string $response
210 | * @return \Symfony\Component\HttpFoundation\Response
211 | */
212 | protected function getVerificationFailureResponse(Request $request, $response)
213 | {
214 | return redirect()->route('verification.resend')->withErrors(['status' => trans($response)]);
215 | }
216 |
217 | /**
218 | * Get the guest middleware for the application.
219 | */
220 | public function guestMiddleware()
221 | {
222 | $guard = $this->getGuard();
223 |
224 | return $guard ? 'guest:'.$guard : 'guest';
225 | }
226 | }
227 |
--------------------------------------------------------------------------------
/src/config/verification.php:
--------------------------------------------------------------------------------
1 | env('VERIFICATION_DRIVER', 'users'),
17 |
18 | /*
19 | |--------------------------------------------------------------------------
20 | | Default Verification Value
21 | |--------------------------------------------------------------------------
22 | |
23 | | This option determines if user MUST verify
24 | | his account before login or not.
25 | |
26 | */
27 |
28 | 'verify' => true,
29 |
30 | /*
31 | |--------------------------------------------------------------------------
32 | | Repositories Configuration
33 | |--------------------------------------------------------------------------
34 | |
35 | | Here you may configure the driver information for each repository that
36 | | is used by your application. A default configuration has been added
37 | | for each back-end shipped with this package. You are free to add more.
38 | |
39 | */
40 |
41 | 'repositories' => [
42 |
43 | 'database' => [
44 | 'driver' => 'database',
45 | 'connection' => env('DB_CONNECTION', 'mysql'),
46 | 'table' => 'users_verifications',
47 | 'expires' => 0,
48 | ],
49 |
50 | ],
51 |
52 | /*
53 | |--------------------------------------------------------------------------
54 | | Brokers Configuration
55 | |--------------------------------------------------------------------------
56 | |
57 | | Here you may configure brokers.
58 | | A default configuration has been added
59 | | for each back-end shipped with this package. You are free to add more.
60 | |
61 | */
62 |
63 | 'brokers' => [
64 |
65 | 'users' => [
66 | 'provider' => 'users',
67 | 'repository' => 'database',
68 | 'email' => 'verification::auth.emails.verification',
69 | ],
70 |
71 | ],
72 |
73 | ];
74 |
--------------------------------------------------------------------------------
/src/translations/en/verification.php:
--------------------------------------------------------------------------------
1 | 'We have e-mailed your verification link!',
17 | 'token' => 'This verification token is invalid.',
18 | 'user' => "We can't find a user with that e-mail address.",
19 | 'subject' => 'You account verification link',
20 |
21 | ];
22 |
--------------------------------------------------------------------------------
/src/views/auth/emails/verification.blade.php:
--------------------------------------------------------------------------------
1 | Click here to verify your account: {{ $link }}
--------------------------------------------------------------------------------
/src/views/auth/verification/message.blade.php:
--------------------------------------------------------------------------------
1 | @extends('layouts.app')
2 |
3 |
4 | @section('content')
5 |
6 |
7 |
8 |
9 |
Verify Account
10 |
11 | In order to verify your account, you have to click on the link in your inbox.
12 |
13 |
16 |
17 |
18 |
19 |
20 | @endsection
21 |
--------------------------------------------------------------------------------
/src/views/auth/verification/resend.blade.php:
--------------------------------------------------------------------------------
1 | @extends('layouts.app')
2 |
3 |
4 | @section('content')
5 |
6 |
7 |
8 |
9 |
Verify Account
10 |
11 | @if (session('status'))
12 |
13 | {{ session('status') }}
14 |
15 | @endif
16 |
17 | @if ($errors->has('status'))
18 |
19 | {{ $errors->first('status') }}
20 |
21 | @endif
22 |
23 |
48 |
49 |
50 |
51 |
52 |
53 | @endsection
54 |
--------------------------------------------------------------------------------
/tests/AuthenticatesUsersTest.php:
--------------------------------------------------------------------------------
1 | getUserMock();
19 | $user->shouldReceive('isUserEmailVerified')->andReturn(false);
20 |
21 | $this->laravelContainer->shouldReceive('make')->with('config', [])->andReturn($config = $this->getConfigMock());
22 | $config->shouldReceive('get')->with('verification.verify', null)->andReturn(true);
23 |
24 | $this->laravelContainer->shouldReceive('make')->with('redirect', [])->andReturn(
25 | $redirect = $this->getRedirectMock()
26 | );
27 | $redirect->shouldReceive('to')->once()->andReturn('redirect');
28 |
29 | Auth::shouldReceive('guard')->once()->andReturn($guard = m::mock('Illuminate\Contracts\Auth\Guard'));
30 | $guard->shouldReceive('logout')->once();
31 |
32 | $this->laravelContainer->shouldReceive('make')->with('url', [])->andReturn($url = $this->getUrlMock());
33 | $url->shouldReceive('route')->andReturn('redirect');
34 |
35 | $trait = $this->getObjectForTrait('Krucas\LaravelUserEmailVerification\AuthenticatesUsers');
36 |
37 | $this->assertEquals('redirect', $trait->authenticated($this->getRequestMock(), $user));
38 | }
39 |
40 | public function testShouldRedirectIntendedOnConfigEnabledUserVerified()
41 | {
42 | $user = $this->getUserMock();
43 | $user->shouldReceive('isUserEmailVerified')->andReturn(true);
44 |
45 | $this->laravelContainer->shouldReceive('make')->with('config', [])->andReturn($config = $this->getConfigMock());
46 | $config->shouldReceive('get')->with('verification.verify', null)->andReturn(true);
47 |
48 | $this->laravelContainer->shouldReceive('make')->with('redirect', [])->andReturn(
49 | $redirect = $this->getRedirectMock()
50 | );
51 | $redirect->shouldReceive('intended')->once()->andReturn('intended');
52 |
53 | $trait = $this->getObjectForTrait('Krucas\LaravelUserEmailVerification\AuthenticatesUsers');
54 |
55 | $this->assertEquals('intended', $trait->authenticated($this->getRequestMock(), $user));
56 | }
57 |
58 | public function testShouldRedirectIntendedOnConfigDisabled()
59 | {
60 | $this->laravelContainer->shouldReceive('make')->with('config', [])->andReturn($config = $this->getConfigMock());
61 | $config->shouldReceive('get')->with('verification.verify', null)->andReturn(false);
62 |
63 | $this->laravelContainer->shouldReceive('make')->with('redirect', [])->andReturn(
64 | $redirect = $this->getRedirectMock()
65 | );
66 | $redirect->shouldReceive('intended')->once()->andReturn('intended');
67 |
68 | $trait = $this->getObjectForTrait('Krucas\LaravelUserEmailVerification\AuthenticatesUsers');
69 |
70 | $this->assertEquals('intended', $trait->authenticated($this->getRequestMock(), $this->getUserMock()));
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/tests/DatabaseTokenRepositoryTest.php:
--------------------------------------------------------------------------------
1 | getRepository($mocks = $this->getMocks());
19 |
20 | $user = $this->getUserMock();
21 | $user->shouldReceive('getEmailForVerification')->andReturn('mail');
22 |
23 | $mocks['connection']->shouldReceive('table')->andReturn($table = $this->getQueryBuilderMock());
24 | $table->shouldReceive('where')->once()->with('email', 'mail')->andReturn($query = $this->getQueryBuilderMock());
25 | $query->shouldReceive('delete')->once();
26 | $table->shouldReceive('insert')->once();
27 |
28 | $repository->create($user);
29 | }
30 |
31 | public function testExistsShouldReturnTrue()
32 | {
33 | $repository = $this->getRepository($mocks = $this->getMocks());
34 |
35 | $user = $this->getUserMock();
36 | $user->shouldReceive('getEmailForVerification')->andReturn('mail');
37 |
38 | $mocks['connection']->shouldReceive('table')->andReturn($table = $this->getQueryBuilderMock());
39 | $table->shouldReceive('where')->once()->with('email', 'mail')->andReturn($query = $this->getQueryBuilderMock());
40 | $query->shouldReceive('where')->once()->with('token', 'token')->andReturn(
41 | $entryQuery = $this->getQueryBuilderMock()
42 | );
43 | $entryQuery->shouldReceive('first')->andReturn(['created' => time()]);
44 |
45 | $this->assertTrue($repository->exists($user, 'token'));
46 | }
47 |
48 | public function testExistsShouldReturnFalseOnNotFound()
49 | {
50 | $repository = $this->getRepository($mocks = $this->getMocks());
51 |
52 | $user = $this->getUserMock();
53 | $user->shouldReceive('getEmailForVerification')->andReturn('mail');
54 |
55 | $mocks['connection']->shouldReceive('table')->andReturn($table = $this->getQueryBuilderMock());
56 | $table->shouldReceive('where')->once()->with('email', 'mail')->andReturn($query = $this->getQueryBuilderMock());
57 | $query->shouldReceive('where')->once()->with('token', 'token')->andReturn(
58 | $entryQuery = $this->getQueryBuilderMock()
59 | );
60 | $entryQuery->shouldReceive('first')->andReturnNull();
61 |
62 | $this->assertFalse($repository->exists($user, 'token'));
63 | }
64 |
65 | public function testExistsOnExpiredToken()
66 | {
67 | $mocks = $this->getMocks();
68 | $mocks['expires'] = 1;
69 |
70 | $repository = $this->getRepository($mocks);
71 |
72 | $user = $this->getUserMock();
73 | $user->shouldReceive('getEmailForVerification')->andReturn('mail');
74 |
75 | $mocks['connection']->shouldReceive('table')->andReturn($table = $this->getQueryBuilderMock());
76 | $table->shouldReceive('where')->once()->with('email', 'mail')->andReturn($query = $this->getQueryBuilderMock());
77 | $query->shouldReceive('where')->once()->with('token', 'token')->andReturn(
78 | $entryQuery = $this->getQueryBuilderMock()
79 | );
80 | $entryQuery->shouldReceive('first')->andReturn(['created_at' => (new Carbon('-1 day'))->format('Y-m-d H:i:s')]);
81 |
82 | $this->assertFalse($repository->exists($user, 'token'));
83 | }
84 |
85 | public function testExistsOnNonExpiredToken()
86 | {
87 | $mocks = $this->getMocks();
88 | $mocks['expires'] = 100;
89 |
90 | $repository = $this->getRepository($mocks);
91 |
92 | $user = $this->getUserMock();
93 | $user->shouldReceive('getEmailForVerification')->andReturn('mail');
94 |
95 | $mocks['connection']->shouldReceive('table')->andReturn($table = $this->getQueryBuilderMock());
96 | $table->shouldReceive('where')->once()->with('email', 'mail')->andReturn($query = $this->getQueryBuilderMock());
97 | $query->shouldReceive('where')->once()->with('token', 'token')->andReturn(
98 | $entryQuery = $this->getQueryBuilderMock()
99 | );
100 | $entryQuery->shouldReceive('first')->andReturn(['created_at' => (new Carbon())->format('Y-m-d H:i:s')]);
101 |
102 | $this->assertTrue($repository->exists($user, 'token'));
103 | }
104 |
105 | public function testDeleteShouldDeleteToken()
106 | {
107 | $repository = $this->getRepository($mocks = $this->getMocks());
108 |
109 | $mocks['connection']->shouldReceive('table')->andReturn($table = $this->getQueryBuilderMock());
110 | $table->shouldReceive('where')->once()->with('token', 'token')->andReturn($query = $this->getQueryBuilderMock());
111 | $query->shouldReceive('delete')->once();
112 |
113 | $repository->delete('token');
114 | }
115 |
116 | public function testDeleteShouldDeleteExpiredTokens()
117 | {
118 | $mocks = $this->getMocks();
119 | $mocks['expires'] = 100;
120 | $repository = $this->getRepository($mocks);
121 |
122 | $mocks['connection']->shouldReceive('table')->andReturn($table = $this->getQueryBuilderMock());
123 | $table->shouldReceive('where')->once()->andReturn($query = $this->getQueryBuilderMock());
124 | $query->shouldReceive('delete')->once();
125 |
126 | $repository->deleteExpired();
127 | }
128 |
129 | public function testDeleteShouldSkipDeleteExpiredIfDisabled()
130 | {
131 | $repository = $this->getRepository($mocks = $this->getMocks());
132 |
133 | $mocks['connection']->shouldReceive('table')->never();
134 |
135 | $repository->deleteExpired();
136 | }
137 |
138 | protected function getRepository($mocks)
139 | {
140 | return new DatabaseTokenRepository($mocks['connection'], $mocks['table'], $mocks['hashKey'], $mocks['expires']);
141 | }
142 |
143 | protected function getMocks()
144 | {
145 | $mocks = [
146 | 'connection' => m::mock('Illuminate\Database\ConnectionInterface'),
147 | 'table' => 'verifications',
148 | 'hashKey' => 'hasKey',
149 | 'expires' => 0,
150 | ];
151 |
152 | return $mocks;
153 | }
154 |
155 | protected function getUserMock()
156 | {
157 | return m::mock('Krucas\LaravelUserEmailVerification\Contracts\RequiresEmailVerification');
158 | }
159 |
160 | protected function getQueryBuilderMock()
161 | {
162 | return m::mock('Illuminate\Database\Query\Builder');
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/tests/RedirectsUsersTest.php:
--------------------------------------------------------------------------------
1 | getObjectForTrait('Krucas\LaravelUserEmailVerification\RedirectsUsers');
18 | $trait->verificationRedirectPath = 'pathFrom';
19 |
20 | $this->assertEquals('pathFrom', $trait->verificationRedirectPath());
21 | }
22 |
23 | public function testVerificationRedirectToFromProperty()
24 | {
25 | $trait = $this->getObjectForTrait('Krucas\LaravelUserEmailVerification\RedirectsUsers');
26 | $trait->verificationRedirectTo = 'pathTo';
27 |
28 | $this->assertEquals('pathTo', $trait->verificationRedirectPath());
29 | }
30 |
31 | public function testVerificationRedirectPathFromRoute()
32 | {
33 | $this->laravelContainer->shouldReceive('make')->with('url', [])->andReturn($url = $this->getUrlMock());
34 | $url->shouldReceive('route')->andReturn('routePath');
35 |
36 | $trait = $this->getObjectForTrait('Krucas\LaravelUserEmailVerification\RedirectsUsers');
37 |
38 | $this->assertEquals('routePath', $trait->verificationRedirectPath());
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/tests/RegistersUsersTest.php:
--------------------------------------------------------------------------------
1 | getTraitMock(['validator', 'create', 'verificationRedirectPath']);
20 | $trait->expects($this->once())->method('validator')->will($this->returnValue(
21 | $validator = m::mock('stdClass')
22 | ));
23 | $trait->expects($this->once())->method('verificationRedirectPath')->will($this->returnValue('verifyPath'));
24 | $validator->shouldReceive('fails')->once()->andReturn(false);
25 |
26 | $request = $this->getRequestMock();
27 | $request->shouldReceive('all')->andReturn(['email' => 'mail']);
28 | $request->shouldReceive('only')->with('email')->andReturn(['email' => 'mail']);
29 |
30 | Verification::shouldReceive('broker')->once()->andReturn($broker = $this->getBrokerMock());
31 | $broker->shouldReceive('sendVerificationLink')->once();
32 |
33 | $this->laravelContainer->shouldReceive('make')->with('config', [])->andReturn($config = $this->getConfigMock());
34 | $config->shouldReceive('get')->with('verification.verify', null)->andReturn(true);
35 |
36 | $this->laravelContainer->shouldReceive('make')->with('redirect', [])->andReturn(
37 | $redirect = $this->getRedirectMock()
38 | );
39 | $redirect->shouldReceive('to')->once()->with('verifyPath', 302, [], null)->andReturn('redirect');
40 |
41 | $this->assertEquals('redirect', $trait->register($request));
42 | }
43 |
44 | public function testRegisterShouldRedirectToRedirectPath()
45 | {
46 |
47 | $trait = $this->getTraitMock(['validator', 'create', 'redirectPath']);
48 | $trait->expects($this->once())->method('validator')->will($this->returnValue(
49 | $validator = m::mock('stdClass')
50 | ));
51 | $trait->expects($this->once())->method('redirectPath')->will($this->returnValue('redirectPath'));
52 | $validator->shouldReceive('fails')->once()->andReturn(false);
53 |
54 | $request = $this->getRequestMock();
55 | $request->shouldReceive('all')->andReturn(['email' => 'mail']);
56 | $request->shouldReceive('only')->with('email')->andReturn(['email' => 'mail']);
57 |
58 | Verification::shouldReceive('broker')->once()->andReturn($broker = $this->getBrokerMock());
59 | $broker->shouldReceive('sendVerificationLink')->once();
60 |
61 | $this->laravelContainer->shouldReceive('make')->with('config', [])->andReturn($config = $this->getConfigMock());
62 | $config->shouldReceive('get')->with('verification.verify', null)->andReturn(false);
63 |
64 | $this->laravelContainer->shouldReceive('make')->with('redirect', [])->andReturn(
65 | $redirect = $this->getRedirectMock()
66 | );
67 | $redirect->shouldReceive('to')->once()->with('redirectPath', 302, [], null)->andReturn('redirect');
68 |
69 | Auth::shouldReceive('guard')->andReturn($guard = $this->getGuardMock());
70 | $guard->shouldReceive('login')->once();
71 |
72 | $this->assertEquals('redirect', $trait->register($request));
73 | }
74 |
75 | protected function getTraitMock($methods = [])
76 | {
77 | return $this->getMockForTrait(
78 | 'Krucas\LaravelUserEmailVerification\RegistersUsers',
79 | [],
80 | '',
81 | true,
82 | true,
83 | true,
84 | $methods
85 | );
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/tests/TestCase.php:
--------------------------------------------------------------------------------
1 | laravelContainer = m::mock('Illuminate\Contracts\Container\Container');
23 | Container::setInstance($this->laravelContainer);
24 | }
25 |
26 | protected function getConfigMock()
27 | {
28 | return m::mock('Illuminate\Contracts\Config\Repository');
29 | }
30 |
31 | protected function getRedirectMock()
32 | {
33 | return m::mock('Illuminate\Routing\Redirector');
34 | }
35 |
36 | protected function getUrlMock()
37 | {
38 | return m::mock('Illuminate\Contracts\Routing\UrlGenerator');
39 | }
40 |
41 | protected function getRequestMock()
42 | {
43 | return m::mock('Illuminate\Http\Request');
44 | }
45 |
46 | protected function getUserMock()
47 | {
48 | return m::mock('Krucas\LaravelUserEmailVerification\Contracts\RequiresEmailVerification');
49 | }
50 |
51 | protected function getBrokerMock()
52 | {
53 | return m::mock('Krucas\LaravelUserEmailVerification\Contracts\VerificationBroker');
54 | }
55 |
56 | protected function getGuardMock()
57 | {
58 | return m::mock('Illuminate\Contracts\Auth\Guard');
59 | }
60 |
61 | protected function getViewMock()
62 | {
63 | return m::mock('Illuminate\Contracts\View\Factory');
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/tests/VerificationBrokerTest.php:
--------------------------------------------------------------------------------
1 | getMocks();
18 | $broker = m::mock('Krucas\LaravelUserEmailVerification\VerificationBroker[getUser]', array_values($mocks));
19 | $broker->shouldReceive('getUser')->once()->andReturnNull();
20 | $this->assertEquals(VerificationBroker::INVALID_USER, $broker->sendVerificationLink(['credentials']));
21 | }
22 |
23 | /**
24 | * @expectedException \UnexpectedValueException
25 | */
26 | public function testGetUserThrowsExceptionIfUserDoesntImplementRequiresEmailVerification()
27 | {
28 | $broker = $this->getBroker($mocks = $this->getMocks());
29 | $mocks['users']->shouldReceive('retrieveByCredentials')->once()->with(['foo'])->andReturn('bar');
30 | $broker->getUser(['foo']);
31 | }
32 |
33 | public function testUserIsRetrievedByCredentials()
34 | {
35 | $broker = $this->getBroker($mocks = $this->getMocks());
36 | $mocks['users']->shouldReceive('retrieveByCredentials')->once()->with(['foo'])->andReturn(
37 | $user = m::mock('Krucas\LaravelUserEmailVerification\Contracts\RequiresEmailVerification')
38 | );
39 | $this->assertEquals($user, $broker->getUser(['foo']));
40 | }
41 |
42 | public function testBrokerCreatesTokenAndRedirectsWithoutError()
43 | {
44 | $mocks = $this->getMocks();
45 | $broker = m::mock(
46 | 'Krucas\LaravelUserEmailVerification\VerificationBroker[emailVerificationLink]',
47 | array_values($mocks)
48 | );
49 | $mocks['users']->shouldReceive('retrieveByCredentials')->once()->with(['foo'])->andReturn(
50 | $user = m::mock('Krucas\LaravelUserEmailVerification\Contracts\RequiresEmailVerification')
51 | );
52 | $mocks['tokens']->shouldReceive('create')->once()->with($user)->andReturn('token');
53 | $callback = function () {};
54 | $broker->shouldReceive('emailVerificationLink')->once()->with($user, 'token', $callback);
55 | $this->assertEquals(VerificationBroker::VERIFICATION_LINK_SENT, $broker->sendVerificationLink(
56 | ['foo'],
57 | $callback
58 | ));
59 | }
60 |
61 | public function testMailerIsCalledWithProperViewTokenAndCallback()
62 | {
63 | unset($_SERVER['__verification.verify.test']);
64 | $broker = $this->getBroker($mocks = $this->getMocks());
65 | $callback = function ($message, $user) {
66 | $_SERVER['__verification.verify.test'] = true;
67 | };
68 | $user = m::mock('Krucas\LaravelUserEmailVerification\Contracts\RequiresEmailVerification');
69 | $mocks['mailer']->shouldReceive('send')->once()->with(
70 | 'verifyAccountView',
71 | ['token' => 'token', 'user' => $user],
72 | m::type('Closure')
73 | )->andReturnUsing(function ($view, $data, $callback) {
74 | return $callback;
75 | });
76 | $user->shouldReceive('getEmailForVerification')->once()->andReturn('email');
77 | $message = m::mock('StdClass');
78 | $message->shouldReceive('to')->once()->with('email');
79 | $result = $broker->emailVerificationLink($user, 'token', $callback);
80 | call_user_func($result, $message);
81 | $this->assertTrue($_SERVER['__verification.verify.test']);
82 | }
83 |
84 | public function testRedirectIsReturnedByVerificationWhenUserCredentialsInvalid()
85 | {
86 | $broker = $this->getBroker($mocks = $this->getMocks());
87 | $mocks['users']->shouldReceive('retrieveByCredentials')->once()->with(['creds'])->andReturn(null);
88 | $this->assertEquals(VerificationBroker::INVALID_USER, $broker->verify(['creds'], function () {}));
89 | }
90 |
91 | public function testRedirectReturnedByVerificationWhenRecordDoesntExistInTable()
92 | {
93 | $creds = ['token' => 'token'];
94 | $broker = $this->getBroker($mocks = $this->getMocks());
95 | $mocks['users']
96 | ->shouldReceive('retrieveByCredentials')
97 | ->once()
98 | ->with(array_except($creds, ['token']))
99 | ->andReturn($user = m::mock('Krucas\LaravelUserEmailVerification\Contracts\RequiresEmailVerification'));
100 | $mocks['tokens']->shouldReceive('exists')->with($user, 'token')->andReturn(false);
101 | $this->assertEquals(VerificationBroker::INVALID_TOKEN, $broker->verify($creds, function () {}));
102 | }
103 |
104 | public function testVerificationRemovesRecordOnTokenTableAndCallsCallback()
105 | {
106 | unset($_SERVER['__verification.verify.test']);
107 | $broker = $this->getMock(
108 | 'Krucas\LaravelUserEmailVerification\VerificationBroker',
109 | ['validateVerification'],
110 | array_values($mocks = $this->getMocks())
111 | );
112 | $broker
113 | ->expects($this->once())
114 | ->method('validateVerification')
115 | ->will(
116 | $this->returnValue(
117 | $user = m::mock('Krucas\LaravelUserEmailVerification\Contracts\RequiresEmailVerification')
118 | )
119 | );
120 | $mocks['tokens']->shouldReceive('delete')->once()->with('token');
121 | $callback = function ($user) {
122 | $_SERVER['__verification.verify.test'] = compact('user');
123 | return 'foo';
124 | };
125 | $this->assertEquals(VerificationBroker::VERIFIED, $broker->verify(['token' => 'token'], $callback));
126 | $this->assertEquals(['user' => $user], $_SERVER['__verification.verify.test']);
127 | }
128 |
129 | protected function getBroker($mocks)
130 | {
131 | return new VerificationBroker(
132 | $mocks['tokens'],
133 | $mocks['users'],
134 | $mocks['mailer'],
135 | $mocks['view']
136 | );
137 | }
138 |
139 | protected function getMocks()
140 | {
141 | $mocks = [
142 | 'tokens' => m::mock('Krucas\LaravelUserEmailVerification\Contracts\TokenRepositoryInterface'),
143 | 'users' => m::mock('Illuminate\Contracts\Auth\UserProvider'),
144 | 'mailer' => m::mock('Illuminate\Contracts\Mail\Mailer'),
145 | 'view' => 'verifyAccountView',
146 | ];
147 |
148 | return $mocks;
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/tests/VerifiesUsersTest.php:
--------------------------------------------------------------------------------
1 | getTraitMock();
22 |
23 | $this->laravelContainer->shouldReceive('make')->with(Factory::class, [])->andReturn(
24 | $view = $this->getViewMock()
25 | );
26 | $view->shouldReceive('make')->with('verification::auth.verification.message', [], [])->andReturn('view');
27 |
28 | $this->assertEquals('view', $trait->getVerify($this->getRequestMock(), null));
29 | }
30 |
31 | public function testVerifyShouldShowSuccessForm()
32 | {
33 | $trait = $this->getTraitMock(['verificationRedirectPath']);
34 | $trait->expects($this->once())->method('verificationRedirectPath')->will($this->returnValue('path'));
35 |
36 | Verification::shouldReceive('broker')->andReturn($broker = $this->getBrokerMock());
37 | $broker->shouldReceive('verify')->once()->andReturn(VerificationBroker::VERIFIED);
38 |
39 | $this->laravelContainer->shouldReceive('make')->with('redirect', [])->andReturn(
40 | $redirect = $this->getRedirectMock()
41 | );
42 | $redirect->shouldReceive('to')->once()->with('path', 302, [], null)->andReturn($response = m::mock('stdClass'));
43 | $response->shouldReceive('with')->once()->with('status', 'translated')->andReturn('redirect');
44 |
45 | $this->laravelContainer->shouldReceive('make')->with('translator', [])->andReturn(
46 | $translator = m::mock('stdClass')
47 | );
48 | $translator->shouldReceive('trans')->andReturn('translated');
49 |
50 | $request = $this->getRequestMock();
51 | $request->shouldReceive('get');
52 |
53 | $this->assertEquals('redirect', $trait->getVerify($request, 'token'));
54 | }
55 |
56 | public function testVerifyShouldShowFailureForm()
57 | {
58 | $trait = $this->getTraitMock();
59 |
60 | Verification::shouldReceive('broker')->andReturn($broker = $this->getBrokerMock());
61 | $broker->shouldReceive('verify')->once()->andReturn(VerificationBroker::INVALID_TOKEN);
62 |
63 | $this->laravelContainer->shouldReceive('make')->with('redirect', [])->andReturn(
64 | $redirect = $this->getRedirectMock()
65 | );
66 | $redirect->shouldReceive('route')->once()->with('verification.resend')->andReturn(
67 | $response = m::mock('stdClass')
68 | );
69 | $response->shouldReceive('withErrors')->once()->with(['status' => 'translated'])->andReturn('redirect');
70 |
71 | $this->laravelContainer->shouldReceive('make')->with('translator', [])->andReturn(
72 | $translator = m::mock('stdClass')
73 | );
74 | $translator->shouldReceive('trans')->andReturn('translated');
75 |
76 | $request = $this->getRequestMock();
77 | $request->shouldReceive('get');
78 |
79 | $this->assertEquals('redirect', $trait->getVerify($request, 'token'));
80 | }
81 |
82 | public function testShowResendForm()
83 | {
84 | $trait = $this->getTraitMock();
85 |
86 | $this->laravelContainer->shouldReceive('make')->with(Factory::class, [])->andReturn(
87 | $view = $this->getViewMock()
88 | );
89 | $view->shouldReceive('make')->with('verification::auth.verification.resend', [], [])->andReturn('view');
90 |
91 | $this->assertEquals('view', $trait->getResend());
92 | }
93 |
94 | public function testSendVerificationLinkShowSuccess()
95 | {
96 | $trait = $this->getTraitMock(['validate']);
97 | $trait->expects($this->once())->method('validate');
98 |
99 | $request = $this->getRequestMock();
100 | $request->shouldReceive('only')->with('email')->andReturn(['email' => 'mail']);
101 |
102 | Verification::shouldReceive('broker')->andReturn($broker = $this->getBrokerMock());
103 | $broker->shouldReceive('sendVerificationLink')->once()->andReturn(VerificationBroker::VERIFICATION_LINK_SENT);
104 |
105 | $this->laravelContainer->shouldReceive('make')->with('redirect', [])->andReturn(
106 | $redirect = $this->getRedirectMock()
107 | );
108 | $redirect->shouldReceive('back')->andReturn($response = m::mock('stdClass'));
109 | $response->shouldReceive('with')->with('status', 'translated')->andReturn('redirect');
110 |
111 | $this->laravelContainer->shouldReceive('make')->with('translator', [])->andReturn(
112 | $translator = m::mock('stdClass')
113 | );
114 | $translator->shouldReceive('trans')->andReturn('translated');
115 |
116 | $this->assertEquals('redirect', $trait->postResend($request));
117 | }
118 |
119 | public function testSendVerificationLinkShowFailure()
120 | {
121 | $trait = $this->getTraitMock(['validate']);
122 | $trait->expects($this->once())->method('validate');
123 |
124 | $request = $this->getRequestMock();
125 | $request->shouldReceive('only')->with('email')->andReturn(['email' => 'mail']);
126 |
127 | Verification::shouldReceive('broker')->andReturn($broker = $this->getBrokerMock());
128 | $broker->shouldReceive('sendVerificationLink')->once()->andReturn(VerificationBroker::INVALID_USER);
129 |
130 | $this->laravelContainer->shouldReceive('make')->with('redirect', [])->andReturn(
131 | $redirect = $this->getRedirectMock()
132 | );
133 | $redirect->shouldReceive('back')->andReturn($response = m::mock('stdClass'));
134 | $response->shouldReceive('withErrors')->with(['email' => 'translated'])->andReturn('redirect');
135 |
136 | $this->laravelContainer->shouldReceive('make')->with('translator', [])->andReturn(
137 | $translator = m::mock('stdClass')
138 | );
139 | $translator->shouldReceive('trans')->andReturn('translated');
140 |
141 | $this->assertEquals('redirect', $trait->postResend($request));
142 | }
143 |
144 | protected function getTraitMock($methods = [])
145 | {
146 | return $this->getMockForTrait(
147 | 'Krucas\LaravelUserEmailVerification\VerifiesUsers',
148 | [],
149 | '',
150 | true,
151 | true,
152 | true,
153 | $methods
154 | );
155 | }
156 | }
157 |
--------------------------------------------------------------------------------