Add Front User Without Admin Permissions

By default, QuickAdminPanel generates two roles: Admin and Simple User, both being able to access the admin panel, with a bit different permissions. But what if you want to have Simple User as a front-end user, with only their own front pages you would build, and they wouldn't even see/access the admin panel?

Step 1. Front Homepage: Remove default redirect to /login

In the first line of routes/web.php file, we have this redirect:

Route::redirect('/', '/login');

It means there is no front homepage, just adminpanel. But you can change it easily, to this:

Route::view('/', 'welcome');

The view resources/views/welcome.blade.php comes from default Laravel, and now you have your front-end homepage, with Login link on the top-right:

You can customize that Blade file however you want, to build a proper designed homepage.

Step 2. Better "Welcome" page

Instead of default "empty" welcome page, let's take a bit more advanced, but still default Laravel template - from Laravel UI package (it used to be core Laravel before Laravel 7), and we need this file: layouts/app.stub to become our resources/views/layouts/user.blade.php:

Then, we can change our resources/views/welcome.blade.php into this:

@extends('layouts.user')
@section('content')
<div class="row justify-content-center">
    <div class="col-md-6">
        <div class="card mx-4">
            <div class="card-body p-4">
                Welcome!
            </div>
        </div>
    </div>
</div>

@endsection	

Notice: the structure is partly taken from default Laravel login page. And now, we have this homepage!

Why did we do it? Not only to make homepage more structured, but so that we can re-use the same layout for the home page of a logged-in user.

Step 3. Logged-in User's Homepage

Now, let's create an inside page that would be a homepage after logging in. We copy-paste the welcome.blade.php from above example, changing just the inner text. And this will become our resources/views/user/home.blade.php:

@extends('layouts.user')
@section('content')
<div class="row justify-content-center">
    <div class="col-md-6">
        <div class="card mx-4">
            <div class="card-body p-4">
                You are logged in!
            </div>
        </div>
    </div>
</div>

@endsection

To show that page, we will create a Controller, and separate it in a subfolder for all future front-user Controllers.

Here's app/Http/Controllers/User/HomeController.php:

namespace App\Http\Controllers\User;

class HomeController
{
    public function index()
    {
        return view('user.home');
    }
}

Notice: Don't forget the namespace! Cause we already have a HomeController with the same name in Admin namespace.

Finally, we need to make a route for it. But let's create the whole Route Group for all the future front-user routes. We almost copy-paste the part of Route::group() for admins, just changing "admin" to "user" everywhere.

routes/web.php:

// Old existing route group for administrators - we don't touch it
Route::group([
    'prefix' => 'admin', 
    'as' => 'admin.', 
    'namespace' => 'Admin', 
    'middleware' => ['auth']
], function () {
    Route::get('/', 'HomeController@index')->name('home');
    
    // Permissions
    Route::delete('permissions/destroy', 'PermissionsController@massDestroy')->name('permissions.massDestroy');
    Route::resource('permissions', 'PermissionsController');
    
    // ... other admin routes
});

// Our NEW group - for front-end users
Route::group([
    'prefix' => 'user', 
    'as' => 'user.', 
    'namespace' => 'User', 
    'middleware' => ['auth']
], function () {
    Route::get('/', 'HomeController@index')->name('home');
});	

Notice: we give the same name to the routes: ->name('home'). But since Route::group() parts have different prefix, the actual route names will be different: admin.home and user.home.

Now, we have two separate designs and pages for admins and users.

Step 4. Check Role: Redirect after login

By default in Laravel, the page to redirect after login is defined in app/Http/Controllers/Auth/LoginController.php, in property $redirectTo:

class LoginController extends Controller
{
    // This is code in Laravel 7 
    // In earlier version it may be different
    protected $redirectTo = RouteServiceProvider::HOME;	

    // ... other code

We need to override it, and we can do it by just defining a method called redirectPath() in the same LoginController.

And we need to check the role - if the user is administrator, or not. Luckily, QuickAdminPanel has generated a helper method inside of app/User.php model:

class User extends Authenticatable
{
    // ...

    public function getIsAdminAttribute()
    {
        return $this->roles()->where('id', 1)->exists();
    }

So, here's what we would need to do in LoginController:

class LoginController extends Controller
{
    // ...

    public function redirectPath()
    {
        $user = auth()->user()->is_admin ? 'admin' : 'user';
        return route($user . '.home');
    }
}	

If you don't understand how getIsAdminAttribute() became auth()->user()->is_admin, you can read more about Eloquent Accessors here in the official Laravel docs.

So, now, every user will be redirected to their own page/section after login. So simple users wouldn't even see the administrator page design.

But wait, they can still access it if they enter the URL in the browser! Let's work on changing the permissions now - it will be our final step.

Step 5. Remove Admin Permissions from User

First, let's remove a piece of code in routes/web.php which automatically redirects to admin.home - we don't need this anymore:

Route::get('/home', function () {
    if (session('status')) {
        return redirect()->route('admin.home')->with('status', session('status'));
    }

    return redirect()->route('admin.home');
});

Next, we need to remove the permissions from Users. They are assigned in a file database/seeds/PermissionRoleTableSeeder.php:

public function run()
{
    // These are administrator permissions, they should stay
    $admin_permissions = Permission::all();
    Role::findOrFail(1)->permissions()->sync($admin_permissions->pluck('id'));

    // These are users permissions to admin area
    // That block should be removed
    $user_permissions = $admin_permissions->filter(function ($permission) {
        return substr($permission->title, 0, 5) != 'user_' && substr($permission->title, 0, 5) != 'role_' && substr($permission->title, 0, 11) != 'permission_';
    });
    Role::findOrFail(2)->permissions()->sync($user_permissions);
}	

After you remove everything related to $user_permissions you need to re-seed the database from scratch, by running this command:

php artisan migrate:fresh --seed

IMPORTANT! This command above will delete ALL YOUR DATABASE and migrate/seed from zero. So if you already have important data, you better remove permissions manually - by deleting entries in permission_role DB table with role_id = 2.

Finally, let's create a Middleware class that we would assign to the Route::group of administrators - it will allow those routes to be accessed only by administrators.

php artisan make:middleware IsAdminMiddleware	

And then we put this code in app/Http/Middleware/IsAdminMiddleware.php:

class IsAdminMiddleware
{
    public function handle($request, Closure $next)
    {
        if (!auth()->user()->is_admin) {
            return redirect()->route('user.home');
        }
        
        return $next($request);
    }
}

We just redirect to user's area, if they are not an administrator.

Now, we need to assign that Middleware class to the routes. To do that, we need to give it a name. Let's call it "admin", and we register it in app/Http/Kernel.php:

class Kernel extends HttpKernel
{
    // ...

    protected $routeMiddleware = [
        'auth' => \Illuminate\Auth\Middleware\Authenticate::class,

        // ... other routes

        'admin' => \App\Http\Middleware\IsAdminMiddleware::class,
    ];
}	

And now we can assign it to the Route group in routes/web.php:

Route::group([
    'prefix' => 'admin', 
    'as' => 'admin.', 
    'namespace' => 'Admin', 
    'middleware' => ['auth', 'admin'] // <= This is our new middleware
], function () {
    Route::get('/', 'HomeController@index')->name('home');
    // ... other admin routes
});	

And that's it, if some simple user would try to load /admin/[something] in the URL, they would automatically be redirected to /user homepage.

The code with all the changes, is in this repository: https://github.com/LaravelDaily/QuickAdminPanel-Front-User-Permissions

Also, we released a separate video on how to implement a front-end theme in 6 steps:

Last updated