create laravel project with multi auth and roll permission and light mode and dark mode
Creating a Laravel Project with Multi-Auth, Role Permissions, and Theme Toggle
I'll guide you through creating a Laravel project with multiple authentication guards, role-based permissions, and a light/dark mode toggle. Let's break this down into steps:
1. Create a Laravel Project
First, let's create a new Laravel project using Composer 1:
composer create-project laravel/laravel multi-auth-app
cd multi-auth-app
2. Set Up Database Connection
You can use Supabase as your PostgreSQL database 1. Update your .env
file with your database credentials:
DB_CONNECTION=pgsql
DB_URL=postgres://postgres.xxxx:password@xxxx.pooler.supabase.com:5432/postgres
And modify your config/database.php
to use a custom schema 1:
'pgsql' => [
'driver' => 'pgsql',
'url' => env('DB_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '5432'),
'database' => env('DB_DATABASE', 'laravel'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', ''),
'charset' => env('DB_CHARSET', 'utf8'),
'prefix' => '',
'prefix_indexes' => true,
'search_path' => 'laravel',
'sslmode' => 'prefer',
],
3. Implement Multi-Authentication
Let's create models and migrations for different user types:
php artisan make:model Admin -m
php artisan make:model User -m
Update Migrations
For the users
table migration:
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
For the admins
table migration:
Schema::create('admins', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
Configure Auth Guards
Update config/auth.php
:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false,
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Models\Admin::class,
],
],
4. Implement Role and Permission System
Create models and migrations for roles and permissions:
php artisan make:model Role -m
php artisan make:model Permission -m
php artisan make:migration create_role_user_table
php artisan make:migration create_permission_role_table
Update Migrations
For the roles
table:
Schema::create('roles', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('slug')->unique();
$table->timestamps();
});
For the permissions
table:
Schema::create('permissions', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('slug')->unique();
$table->timestamps();
});
For the role_user
pivot table:
Schema::create('role_user', function (Blueprint $table) {
$table->id();
$table->foreignId('role_id')->constrained()->onDelete('cascade');
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->timestamps();
});
For the permission_role
pivot table:
Schema::create('permission_role', function (Blueprint $table) {
$table->id();
$table->foreignId('permission_id')->constrained()->onDelete('cascade');
$table->foreignId('role_id')->constrained()->onDelete('cascade');
$table->timestamps();
});
Update Models
Update the User
model:
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
protected $fillable = [
'name', 'email', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
protected $casts = [
'email_verified_at' => 'datetime',
];
public function roles()
{
return $this->belongsToMany(Role::class);
}
public function hasRole($role)
{
return $this->roles->contains('slug', $role);
}
public function hasPermission($permission)
{
return $this->roles->flatMap->permissions->contains('slug', $permission);
}
}
Create the Role
model:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
protected $fillable = ['name', 'slug'];
public function permissions()
{
return $this->belongsToMany(Permission::class);
}
public function users()
{
return $this->belongsToMany(User::class);
}
}
Create the Permission
model:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Permission extends Model
{
protected $fillable = ['name', 'slug'];
public function roles()
{
return $this->belongsToMany(Role::class);
}
}
5. Create Authentication Controllers
php artisan make:controller Auth/UserLoginController
php artisan make:controller Auth/AdminLoginController
User Login Controller
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class UserLoginController extends Controller
{
public function showLoginForm()
{
return view('auth.user-login');
}
public function login(Request $request)
{
$credentials = $request->validate([
'email' => 'required|email',
'password' => 'required',
]);
if (Auth::guard('web')->attempt($credentials)) {
$request->session()->regenerate();
return redirect()->intended('/dashboard');
}
return back()->withErrors([
'email' => 'The provided credentials do not match our records.',
]);
}
public function logout(Request $request)
{
Auth::guard('web')->logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect('/');
}
}
Admin Login Controller
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class AdminLoginController extends Controller
{
public function showLoginForm()
{
return view('auth.admin-login');
}
public function login(Request $request)
{
$credentials = $request->validate([
'email' => 'required|email',
'password' => 'required',
]);
if (Auth::guard('admin')->attempt($credentials)) {
$request->session()->regenerate();
return redirect()->intended('/admin/dashboard');
}
return back()->withErrors([
'email' => 'The provided credentials do not match our records.',
]);
}
public function logout(Request $request)
{
Auth::guard('admin')->logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect('/admin/login');
}
}
6. Create Middleware for Role-Based Access
php artisan make:middleware CheckRole
Update the middleware:
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class CheckRole
{
public function handle(Request $request, Closure $next, $role)
{
if (!$request->user() || !$request->user()->hasRole($role)) {
abort(403, 'Unauthorized action.');
}
return $next($request);
}
}
Register the middleware in app/Http/Kernel.php
:
protected $routeMiddleware = [
// Other middleware...
'role' => \App\Http\Middleware\CheckRole::class,
];
7. Set Up Routes
Update routes/web.php
:
use App\Http\Controllers\Auth\UserLoginController;
use App\Http\Controllers\Auth\AdminLoginController;
// Public routes
Route::get('/', function () {
return view('welcome');
});
// User routes
Route::get('/login', [UserLoginController::class, 'showLoginForm'])->name('login');
Route::post('/login', [UserLoginController::class, 'login']);
Route::post('/logout', [UserLoginController::class, 'logout'])->name('logout');
Route::middleware(['auth:web'])->group(function () {
Route::get('/dashboard', function () {
return view('dashboard');
})->name('dashboard');
});
// Admin routes
Route::prefix('admin')->group(function () {
Route::get('/login', [AdminLoginController::class, 'showLoginForm'])->name('admin.login');
Route::post('/login', [AdminLoginController::class, 'login']);
Route::post('/logout', [AdminLoginController::class, 'logout'])->name('admin.logout');
Route::middleware(['auth:admin'])->group(function () {
Route::get('/dashboard', function () {
return view('admin.dashboard');
})->name('admin.dashboard');
});
});
// Role-based routes
Route::middleware(['auth:web', 'role:editor'])->group(function () {
Route::get('/editor', function () {
return view('editor');
})->name('editor');
});
8. Implement Light/Dark Mode Toggle
Add Theme Toggle JavaScript
Create a new file resources/js/theme.js
:
// Check for saved theme preference or use the system preference
const getTheme = () => {
if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) {
return localStorage.getItem('theme');
}
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
};
// Apply the theme by adding or removing the 'dark' class
const applyTheme = (theme) => {
const root = document.documentElement;
if (theme === 'dark') {
root.classList.add('dark');
} else {
root.classList.remove('dark');
}
localStorage.setItem('theme', theme);
};
// Initialize theme
document.addEventListener('DOMContentLoaded', () => {
applyTheme(getTheme());
// Add event listener for theme toggle button
const themeToggle = document.getElementById('theme-toggle');
if (themeToggle) {
themeToggle.addEventListener('click', () => {
const currentTheme = getTheme();
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
applyTheme(newTheme);
});
}
});
Add CSS for Theme
Create or update resources/css/app.css
:
:root {
--background-color: #ffffff;
--text-color: #333333;
--primary-color: #4f46e5;
--secondary-color: #e5e7eb;
}
.dark {
--background-color: #1f2937;
--text-color: #f3f4f6;
--primary-color: #818cf8;
--secondary-color: #374151;
}
body {
background-color: var(--background-color);
color: var(--text-color);
transition: background-color 0.3s, color 0.3s;
}
/* Add more theme-specific styles as needed */
Update Layout Template
Create or update resources/views/layouts/app.blade.php
:
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Styles -->
<link rel="stylesheet" href="{{ asset('css/app.css') }}">
<!-- Scripts -->
<script src="{{ asset('js/app.js') }}" defer></script>
<script src="{{ asset('js/theme.js') }}"></script>
</head>
<body>
<div class="min-h-screen">
<nav class="bg-secondary-color p-4">
<div class="container mx-auto flex justify-between items-center">
<div class="flex items-center">
<a href="{{ url('/') }}" class="text-lg font-semibold">
{{ config('app.name', 'Laravel') }}
</a>
</div>
<div class="flex items-center">
<button id="theme-toggle" class="p-2 rounded-full">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" />
</svg>
</button>
@auth
<div class="ml-4">
<span>{{ Auth::user()->name }}</span>
<form method="POST" action="{{ route('logout') }}" class="inline">
@csrf
<button type="submit" class="ml-2 text-sm">Logout</button>
</form>
</div>
@else
<a href="{{ route('login') }}" class="ml-4">Login</a>
@endauth
</div>
</div>
</nav>
<main class="py-4">
@yield('content')
</main>
</div>
</body>
</html>
9. Compile Assets
Update webpack.mix.js
:
const mix = require('laravel-mix');
mix.js('resources/js/app.js', 'public/js')
.js('resources/js/theme.js', 'public/js')
.postCss('resources/css/app.css', 'public/css', [
require('tailwindcss'),
]);
10. Run Migrations and Seed Database
php artisan migrate
# Create a seeder for roles and permissions
php artisan make:seeder RolesAndPermissionsSeeder
Update the seeder:
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\Role;
use App\Models\Permission;
class RolesAndPermissionsSeeder extends Seeder
{
public function run()
{
// Create permissions
$viewDashboard = Permission::create(['name' => 'View Dashboard', 'slug' => 'view-dashboard']);
$editContent = Permission::create(['name' => 'Edit Content', 'slug' => 'edit-content']);
$manageUsers = Permission::create(['name' => 'Manage Users', 'slug' => 'manage-users']);
// Create roles
$admin = Role::create(['name' => 'Administrator', 'slug' => 'admin']);
$editor = Role::create(['name' => 'Editor', 'slug' => 'editor']);
$user = Role::create(['name' => 'User', 'slug' => 'user']);
// Assign permissions to roles
$admin->permissions()->attach([$viewDashboard->id, $editContent->id, $manageUsers->id]);
$editor->permissions()->attach([$viewDashboard->id, $editContent->id]);
$user->permissions()->attach([$viewDashboard->id]);
}
}
Run the seeder:
php artisan db:seed --class=RolesAndPermissionsSeeder
11. Start the Application
php artisan serve
Your Laravel application with multi-authentication, role-based permissions, and light/dark mode toggle is now ready! Visit http://127.0.0.1:8000 to see it in action.