├── LICENSE ├── README.md ├── composer.json └── src ├── Account ├── Account.php ├── AccountServiceProvider.php ├── Controllers │ └── ActivationController.php ├── Notifications │ └── ActivationLinkNotification.php └── Traits │ ├── Accountable.php │ ├── ActiveLogin.php │ ├── ActiveRedirect.php │ └── ActiveRegister.php ├── config └── account.php ├── database └── migrations │ └── 2014_10_12_200000_create_accounts_table.php ├── resources ├── lang │ ├── en │ │ └── activation.php │ └── pt-br │ │ └── activation.php └── views │ └── activation │ └── _status.blade.php └── routes └── web.php /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Vítor Barroso 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel User Activation 2 | 3 | - Laravel 5.5 account verification (via e-mail confirmation) for new registers. 4 | - Messages are available in english and portuguese (BR). See `resources/lang/vendor/account` 5 | 6 | ## Install 7 | 8 | ``` 9 | composer require vibar/laravel-account 10 | ``` 11 | 12 | Add service provider in `config/app.php` 13 | 14 | ``` 15 | Vibar\Account\AccountServiceProvider::class 16 | ``` 17 | 18 | ## Config 19 | 20 | Add trait to `App\Http\Controllers\Auth\LoginController` 21 | 22 | ``` 23 | use Vibar\Account\Traits\ActiveLogin; 24 | 25 | use AuthenticatesUsers, ActiveLogin { 26 | ActiveLogin::authenticated insteadof AuthenticatesUsers; 27 | } 28 | ``` 29 | 30 | Add trait to `App\Http\Controllers\Auth\RegisterController` 31 | 32 | ``` 33 | use Vibar\Account\Traits\ActiveRegister; 34 | 35 | use RegistersUsers, ActiveRegister { 36 | ActiveRegister::register insteadof RegistersUsers; 37 | } 38 | ``` 39 | 40 | Add traits to `App\User` 41 | 42 | ``` 43 | use Illuminate\Notifications\Notifiable; 44 | use Vibar\Account\Traits\Accountable; 45 | 46 | class User extends Authenticatable 47 | { 48 | use Notifiable, Accountable; 49 | } 50 | ``` 51 | 52 | Publish package files 53 | ``` 54 | php artisan vendor:publish --provider="Vibar\Account\AccountServiceProvider" 55 | ``` 56 | Publish Laravel auth views 57 | ``` 58 | php artisan make:auth 59 | ``` 60 | 61 | Run migrations 62 | 63 | ``` 64 | php artisan migrate 65 | ``` 66 | 67 | Include activation status template on `resources/views/auth/login.blade.php` 68 | ``` 69 | @include('vendor.account.activation._status') 70 | ``` 71 | ## Update `.env` 72 | 73 | Update `APP_URL`. This URL will be used for the activation link sent by email. 74 | 75 | Use [Mailtrap](https://mailtrap.io/) to see the emails sent. Update `MAIL_USERNAME` and `MAIL_PASSWORD` 76 | 77 | ## Screenshots 78 | 79 |  80 | 81 |  82 | 83 |  84 | 85 |  86 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vibar/laravel-account", 3 | "description": "Laravel account activation.", 4 | "type": "library", 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Vítor Barroso", 9 | "email": "vitor.vgb@gmail.com" 10 | } 11 | ], 12 | "require": {}, 13 | "autoload": { 14 | "psr-4": { 15 | "Vibar\\Account\\": "src/Account/" 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/Account/Account.php: -------------------------------------------------------------------------------- 1 | belongsTo(config('auth.providers.users.model')); 25 | } 26 | 27 | /** 28 | * Scope activated accounts. 29 | * 30 | * @param $query 31 | * @return mixed 32 | */ 33 | public function scopeActivated($query) 34 | { 35 | return $query->whereNotNull('activated_at'); 36 | } 37 | 38 | /** 39 | * Scope not activated accounts. 40 | * 41 | * @param $query 42 | * @return mixed 43 | */ 44 | public function scopeNotActivated($query) 45 | { 46 | return $query->whereNull('activated_at'); 47 | } 48 | 49 | /** 50 | * Get account by token. 51 | * 52 | * @param string $token 53 | * @return mixed 54 | */ 55 | public static function getByToken(string $token) 56 | { 57 | return static::where('token', $token) 58 | ->notActivated() 59 | ->first(); 60 | } 61 | 62 | /** 63 | * Get account by public token. 64 | * 65 | * @param string $token 66 | * @return mixed 67 | */ 68 | public static function getByPublicToken(string $token) 69 | { 70 | return static::where('public_token', $token) 71 | ->notActivated() 72 | ->first(); 73 | } 74 | 75 | /** 76 | * Activate user account. 77 | */ 78 | public function activate() 79 | { 80 | $this->activated_at = Carbon::now(); 81 | $this->save(); 82 | } 83 | 84 | /** 85 | * Reset public token. 86 | */ 87 | public function resetPublicToken() 88 | { 89 | $this->public_token = Str::random(60); 90 | $this->save(); 91 | } 92 | 93 | public static function boot() 94 | { 95 | parent::boot(); 96 | 97 | static::creating(function ($account) { 98 | $account->token = Str::random(60); 99 | $account->public_token = Str::random(60); 100 | }); 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /src/Account/AccountServiceProvider.php: -------------------------------------------------------------------------------- 1 | loadRoutesFrom(__DIR__.'/../routes/web.php'); 18 | 19 | $this->loadTranslationsFrom(resource_path('lang'), 'account'); 20 | 21 | $this->publishes([ 22 | __DIR__.'/../resources/lang' => resource_path('lang/vendor/account'), 23 | ], 'translations'); 24 | 25 | $this->loadViewsFrom(resource_path('views'), 'account'); 26 | 27 | $this->publishes([ 28 | __DIR__.'/../resources/views' => resource_path('views/vendor/account'), 29 | ], 'views'); 30 | 31 | $this->publishes([ 32 | __DIR__.'/../database/migrations/' => database_path('migrations') 33 | ], 'migrations'); 34 | 35 | $this->publishes([ 36 | __DIR__.'/../config/account.php' => config_path('account.php') 37 | ], 'config'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Account/Controllers/ActivationController.php: -------------------------------------------------------------------------------- 1 | route(config('account.activation.route')); 27 | } 28 | 29 | $account->user->notify(new ActivationLinkNotification($account->token)); 30 | 31 | $account->resetPublicToken(); 32 | 33 | return $this->redirect(trans('account::activation.required'), false); 34 | } 35 | 36 | /** 37 | * @param string $token 38 | * @return \Illuminate\Http\RedirectResponse 39 | */ 40 | public function process(string $token) 41 | { 42 | $account = Account::getByToken($token); 43 | 44 | if (!$account) { 45 | return redirect()->route(config('account.activation.route')); 46 | } 47 | 48 | $account->activate(); 49 | 50 | return $this->redirect(trans('account::activation.performed'), true); 51 | } 52 | } -------------------------------------------------------------------------------- /src/Account/Notifications/ActivationLinkNotification.php: -------------------------------------------------------------------------------- 1 | token = $token; 31 | } 32 | 33 | /** 34 | * Get the notification's channels. 35 | * 36 | * @param mixed $notifiable 37 | * @return array|string 38 | */ 39 | public function via($notifiable) 40 | { 41 | return ['mail']; 42 | } 43 | 44 | /** 45 | * Build the mail representation of the notification. 46 | * 47 | * @param mixed $notifiable 48 | * @return \Illuminate\Notifications\Messages\MailMessage 49 | */ 50 | public function toMail($notifiable) 51 | { 52 | $url = config('app.url').route('activation.process', $this->token, false); 53 | 54 | return (new MailMessage) 55 | ->greeting(trans('account::activation.email.greeting', ['name' => $notifiable->name])) 56 | ->subject(trans('account::activation.email.subject')) 57 | ->line(trans('account::activation.email.line1')) 58 | ->action(trans('account::activation.email.action'), $url) 59 | ->line(trans('account::activation.email.line2')); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Account/Traits/Accountable.php: -------------------------------------------------------------------------------- 1 | hasOne(Account::class); 18 | } 19 | } -------------------------------------------------------------------------------- /src/Account/Traits/ActiveLogin.php: -------------------------------------------------------------------------------- 1 | account()->activated()->exists(); 23 | 24 | if (! $accountActivated) { 25 | 26 | $token = $user->account->public_token; 27 | 28 | $this->guard()->logout(); 29 | 30 | return $this->redirect(trans('account::activation.required'), false, $token); 31 | } 32 | 33 | $session = $user->account->session_id; 34 | 35 | if ($session) { 36 | Session::getHandler()->destroy($session); 37 | } 38 | 39 | $user->account->session_id = session()->getId(); 40 | $user->account->save(); 41 | 42 | return redirect()->intended($this->redirectPath()); 43 | } 44 | } -------------------------------------------------------------------------------- /src/Account/Traits/ActiveRedirect.php: -------------------------------------------------------------------------------- 1 | route(config('account.activation.route')) 18 | ->with('account_message', $message); 19 | 20 | if ($activated !== null) { 21 | $response->with('account_status', $activated); 22 | } 23 | 24 | if ($link) { 25 | $response->with('account_link', route('activation.notify', $link)); 26 | } 27 | 28 | return $response; 29 | } 30 | } -------------------------------------------------------------------------------- /src/Account/Traits/ActiveRegister.php: -------------------------------------------------------------------------------- 1 | validator($request->all())->validate(); 24 | 25 | $account = null; 26 | 27 | DB::transaction(function () use ($request, &$account) { 28 | 29 | $user = $this->create($request->all()); 30 | 31 | $account = $user->account()->create(); 32 | 33 | $user->notify(new ActivationLinkNotification($account->token)); 34 | 35 | event(new Registered($user)); 36 | 37 | }); 38 | 39 | return $this->redirect(trans('account::activation.required'), false, $account->public_token); 40 | } 41 | } -------------------------------------------------------------------------------- /src/config/account.php: -------------------------------------------------------------------------------- 1 | [ 6 | 7 | // Base route for activation account 8 | 9 | 'route' => 'login', 10 | 11 | ], 12 | 13 | ]; -------------------------------------------------------------------------------- /src/database/migrations/2014_10_12_200000_create_accounts_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->integer('user_id')->unsigned()->unique(); 19 | $table->foreign('user_id')->references('id')->on('users'); 20 | $table->string('token')->unique(); 21 | $table->string('public_token')->unique(); 22 | $table->timestamp('activated_at')->nullable(); 23 | $table->string('session_id')->nullable(); 24 | $table->timestamps(); 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::drop('accounts'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/resources/lang/en/activation.php: -------------------------------------------------------------------------------- 1 | 'Check your email to activate your account.', 12 | 'performed' => 'Account activated.', 13 | 'resend' => 'Resend activation email', 14 | 15 | 'email' => [ 16 | 'greeting' => 'Hello :name,', 17 | 'subject' => 'Account activation', 18 | 'line1' => 'Click the link below to activate your account.', 19 | 'action' => 'Activate account', 20 | 'line2' => 'If you did not make this request, please ignore this email.', 21 | ], 22 | 23 | ]; 24 | -------------------------------------------------------------------------------- /src/resources/lang/pt-br/activation.php: -------------------------------------------------------------------------------- 1 | 'Acesse seu e-mail para ativar sua conta.', 12 | 'performed' => 'Conta ativada com sucesso.', 13 | 'resend' => 'Reenviar e-mail de ativação', 14 | 15 | 'email' => [ 16 | 'greeting' => 'Olá :name,', 17 | 'subject' => 'Ativação de Conta', 18 | 'line1' => 'Clique no link abaixo para ativar sua conta.', 19 | 'action' => 'Ativar conta', 20 | 'line2' => 'Se você não fez essa solicitação, por favor ignore esse e-mail.', 21 | ], 22 | 23 | ]; 24 | -------------------------------------------------------------------------------- /src/resources/views/activation/_status.blade.php: -------------------------------------------------------------------------------- 1 | @if (session()->has('account_message')) 2 |