tutorial laravel

Tutorial laravel Auth Permission, Aplikasi Inventory Part 2

Artikel Tutorial laravel Auth Permission ini merupakan lanjutan dari artikel sebelumnya (https://soft-gain.com/2019/10/17/laravel-aplikasi-stok-barang-part-1/) ini adalah artikel aplikasi stok barang dengan laravel part 2. Di bagian ini juga kita akan mengimplementasikan tutorial pembuatan auth permission menggunakan laravel, hal ini akan kita lakukan dengan memanfaatan middleware sesuai dengan artikel sebelumnnya juga yaitu (https://soft-gain.com/2020/05/09/menggunakan-middleware-pada-laravel/). Hak akses user menggunakan laravel yang akan kita implementasikan kali ini sederhana saja, hanya ada admin dan user, pada iplementasi nya bisa dikembangkan sesuai kebutuhan.

Langkah pertama adalah, buat lah lebih dahulu middleware baru dengan nama CheckUserStatus (langkah-langkah pembuatannya bisa di lihat di artikel tentang pembahasan middleware). Isi dari CheckUserStatus adalah sebagai berikut :

<?php

namespace App\Http\Middleware;

use Closure;

class CheckUserStatus
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if(\Auth::user()->role === 'admin') {
            return $next($request);
        }

        return redirect('restricted-page');
    }
}

Lalu tambahkan pada kernel.php pada bagian $routeMiddleware, karena kita akan memanfaatkan router untuk mengimplementasikan middleware yang sudah di buat. Kurang lebih jadi seperti ini :

protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
        'role' => \App\Http\Middleware\CheckUserStatus::class, // <--- INI MIDDLEWARE BARU KITA
    ];

Berikutnya, karena kita akan memanfaatkan table dan model yang sudah ada yaitu table dan model users, maka kita perlu membuat beberapa perubahan agar table dan model ini bisa kita modifikasi sesuai kebutuhan kita.

(Catatan : saya lebih memilih untuk membuat controller dan views baru dari pada merubah default yang sudah di sediakan oleh laravel, karena menurut saya ini akan lebih mudah di pahami dari pada merubah default milik laravel yang sudah banyak menggunakan class dari repositori bawaannya).

Selanjutnya buat lah migration, karena kita hendak meng-update table users yang sudah ada sebelumnya. Petunjuk pembuatan migration bisa di lihat di sini (https://soft-gain.com/2019/07/10/cara-dan-penjelasan-migration-pada-laravel/). Kurang lebih seperti ini lah migration yang di buat :

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class UpdateTableUsersAddColumnRole extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users',function($table){
            $table->string('role')->nullable();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users',function($table){
            $table->dropColumn('role');
        });
    }
}

Bisa di lihat di atas kita menambahkan kolom role pada table users, kolom ini lah yang akan kita jadikan acuan user memiliki hak akses atau tidak. Jangan lupa juga untuk modifikasi sedikit model users nya, kurang lebih jadi seperti ini :

protected $fillable = [
    'name', 'email', 'password', 'role',
];

Selanjutkan kita akan buat controller nya, di sini saya memberi nama sg_user.php, isi di dalamnya kurang lebih seperti ini :

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\User as model;
use Illuminate\Support\Facades\Hash;

class sg_user extends Controller
{
    public function index(){
    	$users = model::all();

    	return view('user.table',compact('users'));
    }

    public function create(){
    	return view('user.form');
    }

    public function store(Request $request){
    	if($request->password == '' || $request->password_confirmation == ''){
    		return \Redirect::back()->with('status','Error, Password Is Empty.');
    	}

    	if($request->password !== $request->password_confirmation){
    		return \Redirect::back()->with('status','Error, Password Confirmation Not Match.');
    	}

    	model::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
            'role' => $request->role,
        ]);

    	return redirect('user');
    }

    public function show(){
    	//
    }

    public function edit($id){
    	$editForm = true;
    	$users = model::find($id);

    	return view('user.form',compact('users','editForm'));
    }

    public function update(Request $request, $id){
    	$request = (object) $request->except('_method', '_token');

    	if($request->password !== '' && $request->password_confirmation !== '' && $request->password !== $request->password_confirmation){
    		return \Redirect::back()->with('status','Error, Password Confirmation Not Match.');
    	}

    	model::where('id',$id)->update([
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
            'role' => $request->role,
        ]);

    	return redirect('user');
    }

    public function destroy($id){
    	model::destroy($id);

    	return redirect('user');
    }
}

Jika tertarik tentang penjelasan controller di atas, bisa di lihat di artikel ini (https://soft-gain.com/2019/07/21/crud-pada-laravel-mysql/).

Berikutnya kita tambahkan menu untuk akses table user pada file home.blade.php, tambahkan bagian ini pada menu list :

<div class="links">
      <a href="{{ url('user') }}">Table User</a>
</div>

Selanjutnya kita akan buat tampilan untuk user list nya / table user nya, kita tambahkan folder baru dengan nama user pada folder views, lalu di dalamnya tambahkan file table.blade.php, isi dari file table.blade.php seperti ini :

@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">Table User</div>

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

                    <div class="table-responsive">
                        <a class="btn btn-primary" href="{{ url('user/create') }}">
                            Tambah Data
                        </a>
                        <p></p>
                        <table class="table table-hover table-striped table-bordered">
                            <thead>
                                <tr>
                                    <th class="text-center">Nama</th>
                                    <th class="text-center">Email</th>
                                    <th class="text-center">Role</th>
                                    <th class="text-center"> </th>
                                </tr>
                            </thead>
                            <tbody>
                                @foreach($users as $user)
                                    <tr>
                                        <td>{{ $user->name }}</td>
                                        <td>{{ $user->email }}</td>
                                        <td>{{ $user->role }}</td>
                                        <td>
                                            <a href="{{ URL::route('user.edit',$user->id) }}"><i class="fas fa-edit"></i></a>
                                            <a href="{{ url('user/destroy/'.$user->id) }}"><i class="fas fa-trash-alt"></i></a>
                                        </td>
                                    </tr>
                                @endforeach
                            </tbody>
                        </table>
                    </div>

                </div>
            </div>
        </div>
    </div>
</div>
@endsection

Selanjutnya kita buat juga file form.blade.php di folder yang sama, isi nya seperti ini :

@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">Table User</div>

                <div class="card-body">
                    @if (session('status'))
                        <div class="form-group col-xs-12 col-lg-12">
                            <div class="alert alert-danger" role="alert">
                                {{ session('status') }}
                            </div>
                        </div>
                    @endif

                    @if(isset($editForm))
                        {!! Form::model('', ['url' => url('/user/'.$users->id), 'method' => 'put']) !!}
                    @else
                        {!! Form::model('', ['url' => url('/user'), 'method' => 'post']) !!}
                    @endif
                        {{ csrf_field() }}
                        
                        <div class="form-group col-xs-12 col-lg-12">
                            <label class="control-label">Nama</label>
                            {{ Form::text('name', isset($users->name) ? $users->name : null, ['class' => 'form-control', 'required']) }}
                        </div>
                        <div class="form-group col-xs-12 col-lg-12">
                            <label class="control-label">Email</label>
                            {{ Form::email('email', isset($users->email) ? $users->email : null, ['class' => 'form-control', 'required']) }}
                        </div>
                        <div class="form-group col-xs-12 col-lg-12">
                            <label class="control-label">Password</label>
                            <input type="password" class="form-control" name="password" autocomplete="new-password">
                        </div>
                        <div class="form-group col-xs-12 col-lg-12">
                            <label class="control-label">Password Confirmation</label>
                            <input type="password" class="form-control" name="password_confirmation" autocomplete="new-password">
                        </div>
                        <div class="form-group col-xs-12 col-lg-12">
                            <label class="control-label">Role</label>
                            {{ Form::select('role', ['admin'=>'admin', 'user'=>'user'], isset($users->role) ? $users->role : null, ['class' => 'form-control', 'placeholder'=>'Pilih', 'required']) }}
                        </div>

                        <div class="form-group col-xs-12 col-lg-12">
                            <button type="submit" class="btn btn-success">
                                Simpan
                            </button>
                        </div>
                    {!! Form::close() !!}

                </div>
            </div>
        </div>
    </div>
</div>
@endsection

Berikutnya kita akan membuat file restricted-page.blade.php, file ini hanya berisi tampilan text saja yang akan menjadi landing page jika user yang hendak mengakses module tertantu tapi tidak memiliki akses, isi nya seperti ini :

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Laravel</title>

        <!-- Fonts -->
        <link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet">

        <!-- Styles -->
        <style>
            html, body {
                background-color: #fff;
                color: #636b6f;
                font-family: 'Nunito', sans-serif;
                font-weight: 200;
                height: 100vh;
                margin: 0;
            }

            .full-height {
                height: 100vh;
            }

            .flex-center {
                align-items: center;
                display: flex;
                justify-content: center;
            }

            .position-ref {
                position: relative;
            }

            .top-right {
                position: absolute;
                right: 10px;
                top: 18px;
            }

            .content {
                text-align: center;
            }

            .title {
                font-size: 84px;
            }

            .links > a {
                color: #636b6f;
                padding: 0 25px;
                font-size: 13px;
                font-weight: 600;
                letter-spacing: .1rem;
                text-decoration: none;
                text-transform: uppercase;
            }

            .m-b-md {
                margin-bottom: 30px;
            }
        </style>
    </head>
    <body>
        <div class="flex-center position-ref full-height">
            <div class="content">
                <div class="title m-b-md">
                    Sorry, You Has No Access.
                </div>
            </div>
        </div>
    </body>
</html>

Terakhir kita tambahkan beberapa baris baru ada router kita.

Route::get('/restricted-page', function () {
    return view('restricted-page');
});

Route::group(['prefix' => '', 'middleware' => ['role']], function() {
    Route::resource('/user', 'sg_user');
    Route::get('/user/destroy/{id}', 'sg_user@destroy');
});

Seperti yang terlihat di atas, kita menambahkan router untuk akses ke menu user di dalam router group yang kita sisipkan juga middleware yang baru saja kita buat sebelumnya (penamaan middleware role kita dapatkan sesuai dengan apa yang kita daftarkan sebelumnya pada file kernel.php). Jadi cara kerjanya adalah, hanya user dengan role admin lah yang bisa mengakses, selain itu di alihkan ke halaman restricted (hal itu di aplikasikan berdasarkan code bagian yang ini).

if(\Auth::user()->role === 'admin') {
    return $next($request);
}

return redirect('restricted-page');

Berikut ini tampilan dari apa yang sudah kita kerjakan di atas.

Tampilan Table User

Seperti yang bisa di lihat di atas, kita memiliki beberapa sample user dengan role yang berbeda, role yang di pakai di sini hanya 2 yaitu admin / user.

Tampilan Form User

Dan di atas ini adalah tampilan dari form user, baik buat baru atau edit yang sudah ada kita akan gunakan form yang sama.

Tampilan Halaman Tidak Memiliki Akses

Dan terakhir adalah landing page jika user tidak memiliki role akses yang di butuhkan.

Demikian lah cara pembuatan hak akses user pada laravel, seperti yang bisa di lihat di atas, ini hanya lah contoh yang sangat sederhana sekali dari sebuah skema access user controlling. Dengan memanfaatkan middlware ini pembatasan akses user bisa lebih di maksimalkan lagi dengan lebih dinamis, misalnya user A hanya bisa buat dan update data tetapi tidak bisa hapus data, sedangkan user B hanya bisa melihat list data tanpa bisa modifikasi data. Untuk full source nya bisa di ambil di git repo saya, ambil dari branch aplikasi-stok-barang (https://github.com/ImmanuelJL/belajar-laravel).

Sekian artikel ini, kiranya masih di berikan kesempatan untuk di lanjutkan lagi ke bagian 3. Terima kasih.

(Catatan : Setelah proses migration bisa di update manual column role nya karena value nya masih NULL, di lain kesempatan akan saya coba buatkan seeder nya supaya pada proses implemetasi bisa lebih efektif).

Leave a Reply

Your email address will not be published. Required fields are marked *