By Sheldon L | Published at 2020-08-08 | Updated at 2020-08-08 |
start a project
.env
: set database environment
AppServiceProvider
: set schema boot, Schema::defaultStringLength(255);
composer require laravel/ui --dev
php artisan ui bootstrap --auth
npm install && npm run dev
php artisan make:model Admin -mc
create_admins_table.php
, the schema is the same as User.
Admin.php
, make this class the same as User, but $guard
attribute.
class Admin extends Authenticatable
{
use Notifiable;
protected $guard = 'admin';
# ... keep as it was
}
config/auth.php
, set up guards
, providers
, and password
:'guards' => [
// as it wars
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
],
'providers' => [
// as it was
'admins' => [
'driver' => 'eloquent',
'model' => App\Admin::class,
],
],
'passwords' => [
// as it was
'admins' => [
'provider' => 'admins',
'table' => 'password_resets',
'expire' => 60,
'throttle' => 60,
],
],
php artisan migrate
# Web
Route::get('/', function () {
return view('welcome');
});
# User
Auth::routes();
Route::get('/home', 'HomeController@index')->name('home');
# customed user logout, user must be logged out if want to login to admin
Route::post('/user/logout', 'Auth\LoginController@userLogout')->name('user.logout');
# Admin
Route::prefix('admin')->group(function () {
# Dashboard
Route::get('/', 'AdminController@index')->name('admin.dashboard');
# Login and Logout
Route::get('/login', 'Auth\AdminLoginController@showLoginForm')->name('admin.login');
Route::post('/login', 'Auth\AdminLoginController@login')->name('admin.login.submit');
Route::post('/logout', 'Auth\AdminLoginController@logout')->name('admin.logout');
# No register, only can add admin in tinker for safe consideration
});
home.blade.php
to admin/dashboard.blade.php
;// need `app.blade` because admin need logout button
@extends('layouts.app')
<div class="container" style="margin-top:79px">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header bg-primary text-light"></div>
# AdminController.php
public function __construct()
{
$this->middleware('auth:admin');
}
public function index()
{
return view('admin.dashboard');
}
php artisan make:controller Auth/AdminLoginController
// only logged out visitor can have access
public function __construct()
{
$this->middleware('guest:admin')->except('logout'); // logout()
}
public function showLoginForm()
{
return view('auth.admin-login');
}
public function login(Request $request)
{
$this->validate($request,
[
'email'=>'required|email|string',
'password'=>'required|string|min:8'
],
);
// attempt to login as admin
if (Auth::guard('admin')->attempt(['email' => $request->email, 'password' => $request->password], $request->remember)) {
// if success, redirect to intended route or dashboard
return redirect()->intended(route('admin.dashboard'));
}
// if failed, redirect to login page with remember fields
return redirect()->back()->with($request->only('email', 'remember'));
}
public function logout(Request $request)
{
Auth::guard('admin')->logout();
return redirect('/');
}
Auth/LoginController
# user must be logged out if want to login to admin
public function __construct()
{
$this->middleware('guest')->except('logout', 'userLogout'); // userLogout
}
public function userLogout(Request $request)
{
Auth::guard('web')->logout();
return redirect('/');
}
app.blade
add ‘Logout’ button for admin@if (\Illuminate\Support\Facades\Auth::guard('admin')->check())
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href=""
onclick="event.preventDefault();
document.getElementById('admin-logout-form').submit();">
</a>
<form id="admin-logout-form" action="" method="POST" style="display: none;">
@csrf
</form>
</div>
@else
# User Logout, keep the same
@endif
app.blade
to admin-app.blade
# delete all except content, for no need navbar for admin login
<body>
<main class="py-4">
@yield('content')
</main>
</body>
app/Http/Middleware/RedirectIfAuthenticated.php
public function handle($request, Closure $next, $guard = null)
{
switch ($guard) {
# if guard is admin, redirect to dashboard
case 'admin':
if (Auth::guard($guard)->check()) {
return redirect()->route('admin.dashboard');
}
break;
# if guard is web or default, redirect to home
default:
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
}
break;
}
return $next($request);
}
auth/login.blade
to auth/admin-login.blade
<div class="container" style="margin-top:79px">
// keep the same
<div class="card-header bg-primary text-light"></div>
<div class="card-body">
<form method="POST" action="">
// keep the same
</form>
Exceptions/Handler.php
, create unauthenticated method.# if guard is admin, redirect to admin login
# if web or default, redirect to default login
protected function unauthenticated($request, AuthenticationException $exception)
{
if ($request->expectsJson()) {
return response()->json(['error' => 'Unauthenticated'], 401);
}
$guard = Arr::get($exception->guards(), 0);
switch ($guard) {
case 'admin':
$login = 'admin.login';
break;
default:
$login = 'login';
break;
}
return redirect()->guest(route($login));
}
php artisan tinker
$admin = new App\Admin
$admin->name = 'Admin'
$admin->email = 'admin@qizhong.land'
$admin->password = Hash::make('12345678')
$admin->save()
exit
# Admin
Route::prefix('admin')->group(function () {
# keep the same
# Reset Password
Route::get('/password/reset', 'Auth\AdminForgotPasswordController@showLinkRequestForm')->name('admin.password.request');
Route::post('/password/email', 'Auth\AdminForgotPasswordController@sendResetLinkEmail')->name('admin.password.email');
Route::get('/password/reset/{token}', 'Auth\AdminResetPasswordController@showResetForm')->name('admin.password.reset');
Route::post('/password/reset', 'Auth\AdminResetPasswordController@reset')->name('admin.password.update');
});
php artisan make:controller Auth/AdminForgotPasswordController
use SendsPasswordResetEmails;
public function __construct()
{
# only logged out visitor can have access
$this->middleware('guest:admin');
}
public function broker()
{
return Password::broker('admins');
}
public function showLinkRequestForm()
{
return view('auth.passwords.admin-email');
}
admin-login.blade
@if (Route::has('admin.password.request'))
<a class="btn btn-link" href="">
</a>
@endif
auth/passwords/admin-email.blade
# copy `auth/passwords/email.blade`
@extends('layouts.admin-app')
<div class="container" style="margin-top:79px">
// ...
<div class="card-header bg-primary text-light"></div>
// ...
<form method="POST" action="">
auth/passwords/admin-reset.blade
# copy `auth/passwords/reset.blade`
@extends('layouts.admin-app')
<div class="container" style="margin-top:79px">
// ...
<div class="card-header bg-primary text-light"></div>
// ...
<form method="POST" action="">
php artisan make:notification AdminResetPasswordNotification
# app/Notifications/AdminResetPasswordNotification
public $token;
public function __construct($token)
{
$this->token = $token;
}
public function toMail($notifiable)
{
return (new MailMessage)
->line('You requested to reset your password.')
->action('Reset Password', route('admin.password.reset', $this->token))
->line('Thank you for using our application!');
}
App.php
# Send Password Reset Notification
public function sendPasswordResetNotification($token)
{
$this->notify(new AdminResetPasswordNotification($token));
}
php artisan make:controller Auth/AdminResetPasswordController
# Redirect to reset form
use ResetsPasswords;
/**
* Where to redirect users after resetting their password.
*
* @var string
*/
protected $redirectTo = '/admin';
protected function guard()
{
return Auth::guard('admin');
}
protected function broker()
{
return Password::broker('admins');
}
public function showResetForm(Request $request, $token = null)
{
return view('auth.passwords.admin-reset')->with(
[
'token' => $token,
'email' => $request->email,
],
);
}