KodeJs
Tutorial Multi-User Laravel 13 Pakai Gate & Policy (Lengkap)
Laravel3 menit baca

Tutorial Multi-User Laravel 13 Pakai Gate & Policy (Lengkap)

Kembali ke Blog
Egi Samsul Mu'arifEgi Samsul Mu'arif4 September 20263 menit baca

Panduan mudah membuat hak akses multi-user (Admin & User) di Laravel 13 menggunakan Gate dan Policy. Dijamin rapi, aman, dan mudah dipahami!

Setelah berhasil membuat fitur autentikasi (login/register), tantangan berikutnya dalam membangun aplikasi nyata adalah mengelola Otorisasi (Authorization).

Tidak semua pengguna yang sudah masuk ke sistem boleh melakukan aksi yang sama. Pengguna biasa (User) umumnya hanya bisa melihat data mereka sendiri, sementara pengelola (Admin) memiliki hak penuh untuk mengubah atau menghapus data siapapun.

Di Laravel 13, pengelolaan hak akses ditangani secara rapi dan modular menggunakan dua fitur utama: Gate dan Policy.

Memahami Perbedaan Gate dan Policy

Sebelum masuk ke teknis penulisan kode, pahami perbedaan mendasar keduanya:

  • Gate: Cocok untuk memeriksa izin akses yang bersifat global atau tidak terikat pada model tertentu (misal: memeriksa apakah user memiliki role admin).

  • Policy: Cocok untuk mengorganisir logika izin akses yang berpusat pada Resource / Model spesifik (misal: memeriksa apakah seorang user boleh mengubah data Post milik orang lain).

┌─────────────────────────────────────────────────────────────────────────┐
│                    STRUKTUR HAK AKSES DI LARAVEL                        │
├────────────────────────────────┬────────────────────────────────────────┤
│ Gate (Aturan Global / Role)    │ Policy (Aturan berbasis Model Data)    │
├────────────────────────────────┼────────────────────────────────────────┤
│ • `Gate::allows('admin-only')` │ • `UserPolicy::update(User $user)`    │
│ • Pengecekan role umum         │ • CRUD izin pada resource spesifik    │
└────────────────────────────────┴────────────────────────────────────────┘

1. Persiapan: Tambahkan Kolom role pada Tabel Users

Buka file migration tabel users atau buat migration baru untuk menambahkan kolom role:

Bash

php artisan make:migration add_role_to_users_table

Isi migration dengan definisi kolom enum/string:

PHP

// database/migrations/xxxx_add_role_to_users_table.php
public function up(): void
{
    Schema::table('users', function (Blueprint $table) {
        $table->string('role')->default('user')->after('email'); // 'admin' atau 'user'
    });
}

Jalankan migrasi di terminal:

Bash

php artisan migrate

Buka model app/Models/User.php dan pastikan kolom role masuk ke dalam properti $fillable:

PHP

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

2. Mendefinisikan Gate (Aturan Global)

Buka file app/Providers/AppServiceProvider.php dan daftarkan aturan Gate di dalam method boot():

PHP

namespace App\Providers;

use App\Models\User;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        // Mendefinisikan Gate khusus Admin
        Gate::define('admin-only', function (User $user) {
            return $user->role === 'admin';
        });
    }
}

Cara Memakai Gate di Controller & Blade View:

  • Di Controller:

    PHP

    if (Gate::denies('admin-only')) {
        abort(403, 'Akses Ditolak! Anda Bukan Admin.');
    }
    
  • Di File Blade View:

    HTML

    @can('admin-only')
        <a href="/admin/dashboard" class="btn btn-primary">Menu Rahasia Admin</a>
    @endcan
    

3. Membuat Policy (Aturan berbasis Model)

Misalkan kita punya model Article. Kita ingin mengatur bahwa artikel hanya boleh diubah atau dihapus oleh pemiliknya sendiri, kecuali jika yang login adalah Admin.

Jalankan perintah Artisan untuk membuat Policy yang terhubung langsung dengan model Article:

Bash

php artisan make:policy ArticlePolicy --model=Article

Buka file app/Policies/ArticlePolicy.php dan sesuaikan method update serta delete:

PHP

namespace App\Policies;

use App\Models\Article;
use App\Models\User;

class ArticlePolicy
{
    /**
     * Menentukan apakah user boleh memperbarui artikel ini.
     */
    public function update(User $user, Article $article): bool
    {
        // Admin selalu boleh edit, atau user pemilik artikel tersebut
        return $user->role === 'admin' || $user->id === $article->user_id;
    }

    /**
     * Menentukan apakah user boleh menghapus artikel ini.
     */
    public function delete(User $user, Article $article): bool
    {
        return $user->role === 'admin' || $user->id === $article->user_id;
    }
}

4. Menerapkan Policy di Controller

Buka ArticleController.php dan manfaatkan method $this->authorize() atau Gate::authorize():

PHP

namespace App\Http\Controllers;

use App\Models\Article;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;

class ArticleController extends Controller
{
    public function edit(Article $article)
    {
        // Memeriksa aturan 'update' yang ada di ArticlePolicy
        Gate::authorize('update', $article);

        return view('articles.edit', compact('article'));
    }

    public function destroy(Article $article)
    {
        // Memeriksa aturan 'delete' yang ada di ArticlePolicy
        Gate::authorize('delete', $article);

        $article->delete();

        return redirect()->route('articles.index')->with('success', 'Artikel berhasil dihapus');
    }
}

Jika pengguna yang tidak berhak mencoba mengakses route tersebut, Laravel 13 akan secara otomatis menghentikan proses dan menampilkan halaman 403 Forbidden.

Kesimpulan

Dengan memisahkan logika hak akses ke dalam Gate dan Policy, struktur kode di Laravel 13 milikmu menjadi jauh lebih bersih (clean code), tidak menumpuk di controller, serta terhindar dari kebocoran keamanan akses data.


Egi Samsul Mu'arif

Ditulis oleh

Egi Samsul Mu'arif

Web & Mobile Developer

Artikel Terkait

Lihat semua