Dalam penggunaan aplikasi sebenarnya kita akan membutuhkan permission misal untuk akses misal create, read, update, delete ke suatu Modul baik berdasarkan UserId maupun UserRoles.
Disini kita akan menggunakan suatu library bernama Spatie untuk memanage Roles & Permission tersebut berdasarkan User ataupun Rolesnya.
Asumsi :
Lanjut installasi menggunakan Composer
composer require spatie/laravel-permission
publish migrasi dan config/permission.php config dengan perintah :
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
Pada log kita bisa melihat ada file migration baru untuk table permissions dan role dari package spatie laravel-permission. Selanjutnya kita run migration. Namun sebelumnya kita clear cache dahulu.
php artisan optimize:clear
# or
php artisan config:clear
php artisan migrate
Setelah kita run migration, kita bisa lihat ada beberapa table baru dari package ini dan juga table users di database.
Untuk menggunakan spatie laravel-permission, kita bisa menambahkan trait Spatie\Permission\Traits\HasRoles ke dalam User model. Buka app/Models/User.php, lalu kita tambahkan statement use di dalam class User model.
...
use Spatie\Permission\Traits\HasRoles;
...
class User extends Authenticatable
{
use HasRoles, HasApiTokens, HasFactory, Notifiable;
...
Untuk melakukan test, kita coba buat simulasi penambahan Permission menggunakan Seeder.
php artisan make:seeder PermissionDemo1Seeder
forgetCachedPermissions();
// create permissions
Permission::create(['name' => 'view posts']);
Permission::create(['name' => 'create posts']);
Permission::create(['name' => 'edit posts']);
Permission::create(['name' => 'delete posts']);
Permission::create(['name' => 'publish posts']);
Permission::create(['name' => 'unpublish posts']);
//create roles and assign existing permissions
$writerRole = Role::create(['name' => 'writer']);
$writerRole->givePermissionTo('view posts');
$writerRole->givePermissionTo('create posts');
$writerRole->givePermissionTo('edit posts');
$writerRole->givePermissionTo('delete posts');
$adminRole = Role::create(['name' => 'admin']);
$adminRole->givePermissionTo('view posts');
$adminRole->givePermissionTo('create posts');
$adminRole->givePermissionTo('edit posts');
$adminRole->givePermissionTo('delete posts');
$adminRole->givePermissionTo('publish posts');
$adminRole->givePermissionTo('unpublish posts');
$superadminRole = Role::create(['name' => 'super-admin']);
// gets all permissions via Gate::before rule
// create demo users
$user = User::factory()->create([
'name' => 'Andi',
'email' => 'andi@ombagoes.com',
'password' => bcrypt('12345678')
]);
$user->assignRole($writerRole);
$user = User::factory()->create([
'name' => 'Susi',
'email' => 'susi@ombagoes.com',
'password' => bcrypt('12345678')
]);
$user->assignRole($writerRole);
$user = User::factory()->create([
'name' => 'Bambang',
'email' => 'bambang@ombagoes.com',
'password' => bcrypt('12345678')
]);
$user->assignRole($adminRole);
$user = User::factory()->create([
'name' => 'Bagoes',
'email' => 's.bagoes@gmail.com',
'password' => bcrypt('12345678')
]);
$user->assignRole($superadminRole);
}
}
Penjelasan
Post memiliki permission :
Terdapat 3 role yang dapat mengakses Post yaitu :
Masing2 role memiliki anggota yaitu :
Langsung jalankan Seeder sekalian refresh database untuk memastikan kode yang ditulis sebelumnya tidak ada kesalahan di antara kita.
php artisan migrate:fresh --seed --seeder=PermissionDemo1Seeder
Di class PermissionDemo1Seeder, kita menambahkan role super-admin dan di dalamnya dengan permission kosong untuk role tersebut. Hal tersebut dikarenakan kita menyiapkan super-admin sebagai role utama atau root dimana role tersebut dapat mengakses segalanya.
Di sini kita akan coba memberikan akses super admin melalui gate di dalam AuthServiceProvider. Buka file app/Providers/AuthServiceProvider.php, lalu kita modifikasi method boot().
*/
protected $policies = [
// 'App\Models\Model' => 'App\Policies\ModelPolicy',
];
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
// Implicitly grant "Super Admin" role all permission checks using can()
Gate::before(function ($user, $ability) {
if ($user->hasRole('super-admin')) {
return true;
}
});
}
}
Pada baris kode di atas, ketika super admin login ke dalam web, semua pengecekan permission yang memanggil function call() atau @can() akan bernilai true. Ya, super admin bebas mau melakukan apa saja.
Untuk menggunakan middleware dari spatie laravel-permission, kita harus mendefinisikan middleware-nya terlebih dahulu. Buka file app/Http/Kernel.php, lalu cek sekitar baris 56 terdapat $routeMiddleware, properties dari class Kernel. Kita tambahkan route middleware untuk role, permission dan role_or_permission dari spatie laravel-permission.
protected $routeMiddleware = [
...
'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
'role_or_permission' => \Spatie\Permission\Middlewares\RoleOrPermissionMiddleware::class,
];
Pada artikel sebelumnya kita pernah membuat CRUD Post. Disana ada tampilan untuk melakukan CRUD pada Module Post. Sekarang kita akan menambahkan beberapa action yaitu publish dan unpublish
resources/views/posts/index.blade.php
@extends('layouts.app')
@section('content')
@if($message = Session::get('success'))
{{ $message }}
@endif
{{ $title }}
@can('create posts', Post::class)
Add
@endcan
Title
Content
Category
Action
@if(count($data) > 0)
@foreach($data as $row)
{{ $row->title }}
{{ substr($row->content,1,100) }}
{{ $row->category->name }}
@can('edit posts', Post::class)
Edit
@endcan
@can('delete posts', Post::class)
@endcan
@can('publish posts', Post::class)
@endcan
@can('unpublish posts', Post::class)
@endcan
@endforeach
@else
No Data Found
@endif
{!! $data->appends(['sort','title'])->links() !!}
@endsection('content')
app/Http/Controllers/PostController.php
orderBy('id','desc')->paginate(10);
return view('dashboard.modules.post.standard.index',compact('title','data'));
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
$title = 'Post';
$categories = Category::all();
return view('dashboard.modules.post.standard.create', compact('title','categories'));
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$request->validate([
'title' => 'required|string|max:255',
'content' => 'required',
'category_id' => 'required|exists:App\Models\Category,id'
]);
Post::create([
'title' => $request->title,
'slug' => \Str::slug($request->title),
'content' => $request->content,
'category_id' => $request->category_id,
]);
return redirect()->route('posts.index')->with('status', 'Post Created Successfully');
}
/**
* Display the specified resource.
*
* @param \App\Models\Post $post
* @return \Illuminate\Http\Response
*/
public function show(Post $post)
{
return view('dashboard.modules.post.standard.show', compact('post'));
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\Post $post
* @return \Illuminate\Http\Response
*/
public function edit(Post $post)
{
$title = 'Post';
$categories = Category::all();
return view('dashboard.modules.post.standard.edit', compact('title','categories', 'post'));
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param \App\Models\Post $post
* @return \Illuminate\Http\Response
*/
public function update(Request $request, Post $post)
{
$request->validate([
'title' => 'required|string|max:255',
'content' => 'required',
'category_id' => 'required|exists:App\Models\Category,id',
]);
$post->title = $request->title;
$post->slug = \Str::slug($request->title);
$post->content = $request->content;
$post->category_id = $request->category_id;
$post->save();
return redirect()->route('posts.index')->with('status', 'Post Updated Successfully');
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\Post $post
* @return \Illuminate\Http\Response
*/
public function destroy(Post $post)
{
$post->delete();
return redirect()->route('posts.index')->with('status', 'Post Delete Successfully');
}
public function publish(Post $post)
{
return redirect()->route('posts.index')->with('status', 'Berhasil di Publish');
}
public function unpublish(iPost $post)
{
return redirect()->route('posts.index')->with('status', 'Berhasil di Unpublish');
}
}
routes/web.php
...
Route::middleware('auth')->group(function () {
Route::resource('posts', \App\Http\Controllers\PostController::class);
Route::put('post/{id}/publish', [\App\Http\Controllers\PostController::class, 'publish'])->name('post.publish');
Route::put('post/{id}/unpublish', [\App\Http\Controllers\PostController::class, 'unpublish'])->name('post.unpublish');
...
});
Login dengan user Susi atau Andi, maka tampilannya akan seperti berikut.
Logout lalu login kembali dengan user Bambang, maka tampilannya akan seperti berikut.
Untuk mempermudah pengaturannya kita memerlukan UI, dimana spatie tidak menyediakan tampilannya. Tetapi untungnya banyak yang menyediakan UI nya salah satunya bisa dilihat disini.
https://github.com/LaravelDaily/laravel-permission-ui
Berikut capture tampilannya :
Tinggal disesuaikan dengan kreatifitas anda untuk di masukan ke dalam template anda sendiri.