Membuat Access Control Laravel – Chapter 1

Membuat Access Control Laravel – Chapter 1

Memulai kisah baru dalam seri belajar laravel bareng Daengweb.id. Kali ini kita akan belajar tentang access control yang akan kita rangkai menjadi beberapa chapter. Tapi cerita kita merupakan lanjutan dari cerita-cerita sebelumnya. Maka apa yang telah dibuat sebelumnya akan kita manfaatkan pada tutorial kali ini.

Secara default user dapat melakukan registrasi dan login, akan tetapi tidak memiliki batasan untuk mengontrol user tersebut. Sebagai contoh, seharusnya terdapat user yang dapat mengedit sebuah post ? Ataukah hanya dibatasi pada user yang membuat post tersebut ? Dan tentu saja untuk mewujudkan hal tersebut, alangkah lebih baik jika kita membuat admin area untuk membuat access control tersebut.

Menggunakan Trait

Kita bisa menambahkan sebuah method ke user model yang akan mengecek apakah terdapat records yang dimiliki oleh user tersebut, namun pada tutorial ini saya lebih prefer menggunakan sebuah trait. Alasannya sederhana, agar lebih rapi dan maintenable.

Langsung saja kita buat sebuah folder dengan nama AuthTraits pada folder App/Http. Kemudian kita buat sebuah file dengan nama OwnsRecord.php, yang terlihat seperti ini :

Kita telah memiliki sebuah file dengan nama OwnsRecord.php yang terdapat didalam folder AuthTraits. Tambahkan syntax berikut :

<?php
namespace App\Http\AuthTraits;
use Illuminate\Support\Facades\Auth;

trait OwnsRecord
{
	public function userNotOwnerOf($modelRecord)
	{
		return $modelRecord->user_id != Auth::id();
	}

	public function currentUserOwns($modelRecord)
	{
		return $modelRecord->user_id === Auth::id();
	}

	public function adminOrCurrentUserOwns($modelRecord)
	{
		if (Auth::user()->is_admin == 1) {
			return true;
		}
		return $modelRecord->user_id === Auth::id();
	}
}

Seperti yang terlihat, terdapat namespace sesuai directory trait dan juga menggunakan Auth Facade:

namespace App\Http\AuthTraits;
use Illuminate\Support\Facades\Auth;

Kita akan menggunakan Auth::id(), yang akan me-return id user yang sedang login untuk kemudian mencek atribut user_id pada model yang sedang menanganinya. Sebagai contoh, pada Post mode, kita memiliki user_id, yang menyimpan sekaligus menjadi pengenal user yang mana yang membuat record tersebut. Dan tugas kita selanjutnya adalah memastikan kecocokan id, jadi anda dapat melihatnya pada method currentUserOwns:

public function currentUserOwns($modelRecord)
{
    return $modelRecord->user_id === Auth::id();
}

fungsi method diatas adalah mengecek atribut user_id dan Auth::id() apakah terdapat kecocokan. Pada method yang berbeda kita juga memiliki sebuah method yang berfungsi untuk mengecek jika terdapat ketidakcocokkan user_id dan Auth::id(), yakni pada method userNotOwnerOf:

public function userNotOwnerOf($modelRecord)
{
    return $modelRecord->user_id != Auth::id();
}

Dengan memanfaatkan trait yang telah kita buat, maka kita dapat melakukan hal seperti berikut :

if ($this->userNotOwnerOf($post)) {
    //throw new someException;
}

atau hal yang serupa dengan memanfaatkan method lainnya :

if (!this->currentUserOwns($post)) {
    //throw new SomeException
}

Tampaknya method userNotOwnerOf dan currentUserOwns serupa tapi tak sama, dan mungkin saja salah satunya saja sudah cukup untuk digunakan. Tapi dengan maksud pembelajaran saya membuatnya kedalam dua method. Kedepannya silahkan berkreasi dalam membuat dan memanfaatkan sebuah method.

Terakhir, kita memiliki sebuah method yang akan mengecek apa user yang login adalah pemilik record atau admin:

public function adminOrCurrentUserOwns($modelRecord)
{
	if (Auth::user()->is_admin == 1) {
		return true;
	}
	return $modelRecord->user_id === Auth::id();
}

Ini akan sangat berguna jika anda ingin mengizinkan admin dan juga pemilik record untuk mengedit sebuah record.

Agar kita bisa melihat apakah is_admin sama dengan satu, dalam artian adalah benar maka kita harus memiliki field tersebut pada users table. Kita akan menambahkan beberapa field pada user table, tapi sebelum melakukannya. Kita akan melakukan testing pada trait yang telah dibuat. Silahkan tambahkan trait pada PostContorller:

class PostController extends Controller
{
    use OwnsRecord;

Dan juga tambahkan use statement pada use statements section :

use App\Http\AuthTraits\OwnsRecord;

Kemudian mari kita tambahkan salah satu trait method kedalam update method seperti berikut :

public function update(Request $request)
{
    $this->validate($request, [
       'title' => 'required|max:255|unique:posts,title'
    ]);

    $post = Post::find($id);
    if ($this->userNotOwnerOf($post)){
       dd('kamu bukan pemilik post ini');
    }

    $post->update([
        'user_id' => Auth::id(), 
        'title' => $request->title
    ]);
    return redirect(route('post'))
}

Seperti yang anda lihat, kita hanya menambahkan potongan code ini :

if ($this->userNotOwnerOf($post)){
  dd('kamu bukan pemilik post ini');
}

Untuk melakukan uji coba, pada record post yang telah ada, silahkan edit user_id dengan menggunakan id user yang sedang tidak login pada proses uji coba kali ini. Pada kasus kali ini, saya menggunakan user_id = 2, dimana id tersebut tidak terdapat pada users table.

Jadi ketika anda mencoba melakukan update data post, anda akan mendapatkan pesan berikut :

"kamu bukan pemilik post ini"

Dengan demonstrasi ini sekaligus kita belajar bagaimana menggunakan method dd() untuk memvalidasi dan mengetahui apakah anda mendapatkan hasil yang diharapkan atau tidak.

Tentunya, dalam real application, kita tidak bisa menggunakan die dan dump (dd), jadi yang akan kita lakukan selanjutnya adalah membuat pesan custom error menggunakan exception.  Opps, exception sudah disinggung tapi akan dilanjutkan pada artikel selanjutnya agar tidak jenuh. Jadi sampai jumpa di artikel selanjutnya. Semoga bermanfaat.

Category:
Share:

Comments