Laravel: Approve New Registered Users from Administrator
Tags: laravel, php
Published: 2018-10-22 08:24:45

---
title: Laravel: Approve New Registered Users from Administrator
published: true
description: Tutorial on how to create admin user and allow them to approve newly registered users, protecting middle pages with Middleware.
tags: Laravel,PHP
cover_image: https://laraveldaily.com/wp-content/uploads/2018/10/approve-user.png
---

Laravel framework comes with built-in Auth system, which is pretty good. But it doesn't cover all the cases, and the most common one is administrator approval of every new registered user. In this article, I will show you how to do it in fresh Laravel 5.7 project.

What we will cover:

1. Preparing DB structure: migrations, models and seeders
2. Restricting new users from accessing dashboard
3. Notifying administrator about new user
4. Approving new user by administrator

---

First, let's create a new Laravel project:

```
laravel new laravel
```

Then you need to configure our **.env** file with database credentials. 

Next, let's generate our Login/Register links:

```
php artisan make:auth
```

So we can log in with this form:

![Laravel login auth](https://laraveldaily.com/wp-content/uploads/2018/10/Screen-Shot-2018-10-22-at-11.12.32-AM.png)

From `users` DB table perspective, we need to add two fields: 

- `admin` (boolean, 0/1) - you may have more complicated logic with roles/permissions
- `approved_at` (timestamp, nullable) - will be set to current timestamp when approved

So:

```
php artisan make:migration add_admin_to_users_table
```

And then the migration itself:

```
Schema::table('users', function (Blueprint $table) {
    $table->boolean('admin')->default(false);
    $table->timestamp('approved_at')->nullable();
});

```

Also, we need to add those fields into `$fillable` array in `app/User.php` model:

```
protected $fillable = [
    'name', 'email', 'password', 'admin', 'approved_at'
];
```

## Seeding admin user

This command will help us:

```
php artisan make:seeder AdminSeeder
```

It will generate a new file in `database/seeds` folder, which we fill like this:

```
class AdminSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        \App\User::create([
            'name' => 'Admin',
            'email' => 'admin@admin.com',
            'email_verified_at' => now(),
            'password' => bcrypt('verysafepassword'),
            'admin' => 1,
            'approved_at' => now(),
        ]);
    }
}

```

Finally, we need to add this class to the main `database/seeds/DatabaseSeeder.php` file.

```
public function run()
{
    $this->call(AdminSeeder::class);
}
```

Now, we're ready with our DB structure and can run this:

```
php artisan migrate --seed
```

At this point, if we log in with credentials `admin@admin.com` - `verysafepassword`, we should see our empty Home Dashboard, from default Laravel.


![Laravel auth home dashboard](https://laraveldaily.com/wp-content/uploads/2018/10/Screen-Shot-2018-10-22-at-10.37.17-AM.png)

---

## Restricting New User from Dashboard

Ok, now we can register with new user which will be not approved. Let's restrict them from accessing the actual dashboard.

First, we create a separate Blade file which will have text like "Waiting for approval". This will be a page we will redirect to, for every request of non-approved user.

So, `resources/views/approval.blade.php`:

```
@extends('layouts.app')

@section('content')
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-md-8">
                <div class="card">
                    <div class="card-header">Waiting for Approval</div>

                    <div class="card-body">
                        Your account is waiting for our administrator approval.
                        <br />
                        Please check back later.
                    </div>
                </div>
            </div>
        </div>
    </div>
@endsection

```

Next, we create a Controller to point to it. Or, in fact, we create a method in the same `HomeController`:

```
public function approval()
{
    return view('approval');
}

```

Here's how it looks:

![Laravel user approve](https://laraveldaily.com/wp-content/uploads/2018/10/Screen-Shot-2018-10-22-at-11.16.24-AM.png)

Finally, we need a **route** for it. Let's put it under `auth` middleware, and our `routes/web.php` will look like this:

```
Route::middleware(['auth'])->group(function () {
    Route::get('/approval', 'HomeController@approval')->name('approval');
    Route::get('/home', 'HomeController@index')->name('home');
});

```

Now, we need to restrict the access for non-approved users to that `/home` URL. We create a new **Middleware**:

```
php artisan make:middleware CheckApproved
```

It generates a file `app/Http/Middleware/CheckApproved.php` which we fill like this:

```
namespace App\Http\Middleware;

use Closure;

class CheckApproved
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if (!auth()->user()->approved_at) {
            return redirect()->route('approval');
        }

        return $next($request);
    }
}
```

We need to register that Middleware in `app/Http/Kernel.php` in the `$routeMiddleware` array:

```
protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    // ...
    'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
    'approved' => \App\Http\Middleware\CheckApproved::class,
];

```

Finally, we add the `home` route to the block under that Middleware, so our `routes/web.php` now looks like this:

```
Route::middleware(['auth'])->group(function () {
    Route::get('/approval', 'HomeController@approval')->name('approval');

    Route::middleware(['approved'])->group(function () {
        Route::get('/home', 'HomeController@index')->name('home');
    });
});

```

So now, every new user, after logging in, or on any action, will be redirected to the `approval page`.

---

## Notifying Administrator About New User

We will use [Laravel Notifications](https://laravel.com/docs/5.7/notifications) function that comes with the framework.

Let's generate a new Notification class:

```
php artisan make:notification NewUser
```

Then we fill in a newly generated `app/Notifications/NewUser.php`:

```
namespace App\Notifications;

use App\User;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;

class NewUser extends Notification
{
    use Queueable;

    private $new_user;

    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct(User $new_user)
    {
        $this->new_user = $new_user;
    }


    /**
     * Get the mail representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return \Illuminate\Notifications\Messages\MailMessage
     */
    public function toMail($notifiable)
    {
        return (new MailMessage)
            ->line('New user has registered with email ' . $this->new_user->email)
            ->action('Approve user', route('admin.users.approve', $this->new_user->id));
    }

}

```

A few things to notice here:

- We will pass new registered user as an object via `__construct()` method, then it turns into a local private variable, which we will use in `toMail()` method as `$this->new_user`;
- We specify the route to approve user, and we will create the functionality a little later below.

Now, to use this Notification, we will extend a controller `app/Http/Controllers/Auth/RegisterController.php`, specifically method `create()`:

```
// Don't forget to add this
use App\Notifications\NewUser;

// ...

/**
 * Create a new user instance after a valid registration.
 *
 * @param  array  $data
 * @return \App\User
 */
protected function create(array $data)
{
    $user = User::create([
        'name' => $data['name'],
        'email' => $data['email'],
        'password' => Hash::make($data['password']),
    ]);

    $admin = User::where('admin', 1)->first();
    if ($admin) {
        $admin->notify(new NewUser($user));
    }

    return $user;
}

```

To test sending of an email, I recommend [MailTrap](https://mailtrap.io/) which I will use and put its credentials to Laravel `.env` file:

```
MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=54043xxxxxxxxxx
MAIL_PASSWORD=a7d17xxxxxxxxx
MAIL_ENCRYPTION=null
```

So, on every new user, admin will get something like this:

![Laravel mailtrap email](https://laraveldaily.com/wp-content/uploads/2018/10/Screen-Shot-2018-10-22-at-11.16.39-AM.png)

---

## Approving New User by Administrator

In previous step, we've used a route: `route('admin.users.approve', $this->new_user->id)`, now let's actually implement it.

We actually need two routes: to list the users, and to approve one of them.
Also, we need to restrict it for admin users only, so let's generate another middleware:

```
php artisan make:middleware CheckAdmin
```

We fill the new file `app/Http/Middleware/CheckAdmin.php`:

```
namespace App\Http\Middleware;

use Closure;

class CheckAdmin
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if (!auth()->user()->admin) {
            return redirect()->route('home');
        }

        return $next($request);
    }
}
```

We also need to add it to `app/Http/Kernel.php` array, as above:

```
protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    // ...
    'approved' => \App\Http\Middleware\CheckApproved::class,
    'admin' => \App\Http\Middleware\CheckAdmin::class,
];
```

Finally, here's our final `routes/web.php` version:

```
Route::middleware(['auth'])->group(function () {
    Route::get('/approval', 'HomeController@approval')->name('approval');

    Route::middleware(['approved'])->group(function () {
        Route::get('/home', 'HomeController@index')->name('home');
    });

    Route::middleware(['admin'])->group(function () {
        Route::get('/users', 'UserController@index')->name('admin.users.index');
        Route::get('/users/{user_id}/approve', 'UserController@approve')->name('admin.users.approve');
    });
});
```

Last thing we need is to implement the actual approval.

```
php artisan make:controller UserController
```

Here's the code for `app/Http/Controllers/UserController.php`:

```
namespace App\Http\Controllers;

use App\User;

class UserController extends Controller
{

    public function index()
    {
        $users = User::whereNull('approved_at')->get();

        return view('users', compact('users'));
    }

    public function approve($user_id)
    {
        $user = User::findOrFail($user_id);
        $user->update(['approved_at' => now()]);

        return redirect()->route('admin.users.index')->withMessage('User approved successfully');
    }

}
```

So method `approve()` will approve user and redirect back to the list. Which is implemented in `resources/views/users.blade.php`:

```
@extends('layouts.app')

@section('content')
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-md-8">
                <div class="card">
                    <div class="card-header">Users List to Approve</div>

                    <div class="card-body">

                        @if (session('message'))
                            <div class="alert alert-success" role="alert">
                                {{ session('message') }}
                            </div>
                        @endif

                        <table class="table">
                            <tr>
                                <th>User name</th>
                                <th>Email</th>
                                <th>Registered at</th>
                                <th></th>
                            </tr>
                            @forelse ($users as $user)
                                <tr>
                                    <td>{{ $user->name }}</td>
                                    <td>{{ $user->email }}</td>
                                    <td>{{ $user->created_at }}</td>
                                    <td><a href="{{ route('admin.users.approve', $user->id) }}"
                                           class="btn btn-primary btn-sm">Approve</a></td>
                                </tr>
                            @empty
                                <tr>
                                    <td colspan="4">No users found.</td>
                                </tr>
                            @endforelse
                        </table>
                    </div>
                </div>
            </div>
        </div>
    </div>
@endsection
```

Final visual result:

![Laravel administrator approve users](https://laraveldaily.com/wp-content/uploads/2018/10/Screen-Shot-2018-10-22-at-11.19.10-AM.png)

So here's probably the quickest way to approve new registered users in Laravel. Pretty simple, huh?