Autentikasi Laravel-Vue.js Multiple Roles: User, Admin, Manager

wahyunanangwidodo

wahyunanangwidodo Kamis, 17 Juni 2021

Autentikasi Laravel-Vue.js Multiple Roles: User, Admin, Manager

Membangun aplikasi yang diperuntukan untuk banyak pengguna dan kita ingin memberi batasan untuk beberapa tindakan tertentu, atau mencegah agar pengguna tidak dapat mengakses informasi yang tidak berkaitan, salah satu caranya adalah dengan membuat kontrol akses berbasis peran.

Metode Yang di Pakai

Banyak metode bisa kita buat atau gunakan. Jika kita membangun aplikasi menggunakan vue.js, kita bisa manfaatkan fitur navigation guard yang ada pada vue router, untuk tindakan pemeriksaan, pengalihan, menjaga setiap route atau navigasi yang kita miliki dengan mudah.

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) {
    // this route requires auth, check if logged in
    // if not, redirect to login page.
    if (!auth.loggedIn()) {
      next({
        path: '/login',
        query: { redirect: to.fullPath }
      })
    } else {
      let roles = ['user', 'admin', 'manager'];
      if (roles.includes('admin')) { //true
        next({ name: 'Admin' }) // admin dashboard 
      } else {
        next()
      }
    }
  } else {
    next()
  }
})

includes() adalah metode javascript untuk mencari nilai di dalam array yang akan mengembalikan nilai true apabila ditemukan.

Untuk contoh nyata bagaimana navigasi dilindungi atau membuka halaman dengan syarat hak akses, mari bersama kita buat aplikasi autentukasi sederhana dan menerapkan navigation guard seperti di atas.

Yang akan dibuat

Kita akan membuat aplikasi sederhana dan bekerja dengan banyak peran yang dimiliki user atau pengguna.

  • Login dan Registrasi User.
  • Membuat ROLES. Satu pengguna dapat memiliki lebih dari satu peran.
  • Otorisasi token JWT.
  • Desain CSS menggunkan Bootstrap 5.
  • Navigasi menggunakan Vue-Router.
  • Database menggunakan MySQL.

Persyaratan

  • Terbiasa dengan package manager seperti npm, yarn, dan sebagainya.
  • Dapat menyesuaikan perintah apabila package manager yang digunakan berbeda.
  • Mengetahui penggunaan aplikasi Postman untuk testing.
  • Memahami perintah artisan laravel.
  • Memahami baris perintah MySQL.

DEMO

Autentikasi Laravel-Vue.js: Instalasi

Kita mulai dari instalasi laravel dan library atau modul pendukung. Kita install semua apa yang kita butuhkan sekaligus. Silahkan jalankan perintah di bawah ini secara berurutan.

laravel new lavueroles

cd lavueroles  

npm i

npm i vue vue-loader vue-template-compiler resolve-url-loader --save-dev

npm i bootstrap jquery popper.js sass sass-loader --save-dev

npm i vue-router @popperjs/core

composer require tymon/jwt-auth:dev-develop --prefer-source

php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"

php artisan jwt:secret

Membuat Database

Setelah proses instalasi di atas selesai, kita lanjutkan membuat database MySQL baru dan dihubungkan dengan aplikasi.

//mysql command
MariaDB [(none)]> create database db_lavueroles;
Query OK, 1 row affected (0.002 sec)

//.env
DB_DATABASE=db_lavueroles
DB_USERNAME=root
DB_PASSWORD=

Membuat Tabel

Kita buat file migrasi baru untuk menyimpan daftar peran pengguna.

php artisan make:model Role -m

Kita akan membuat relasi, menghubungkan tabel users dan tabel roles. Agar satu user dapat memiliki lebih dari satu peran, kita gunakan tabel lain sebagai perantara.

Mari kita buat kembali sebuah file migrasi baru.

php artisan make:migration create_role_user_table

Kita buat tabel dengan nama role_user. Tabel ini akan menyimpan key / ID dari user dan juga role.

Selanjutnya kita tambahkan kolom pada file migrasi yang telah dibuat, seperti di bawah ini.

//...create_roles_table.php
public function up()
{
    Schema::create('roles', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->timestamps();
    });
}
//...create_role_user_table.php
public function up()
{
    Schema::create('role_user', function (Blueprint $table) {
        $table->id();
        $table->foreignId('user_id');
        $table->foreignId('role_id');
        $table->timestamps();
    });
}

Terakhir, kita lakukan migrasi.

php artisan migrate
MariaDB [db_lavueroles]> show tables;
+-------------------------+
| Tables_in_db_lavueroles |
+-------------------------+
| failed_jobs             |
| migrations              |
| password_resets         |
| role_user               |
| roles                   |
| users                   |
+-------------------------+
6 rows in set (0.001 sec)

Tabel database telah dibuat dan siap digunakan.

Seeding: Menambahkan Role

Kita buat seeder untuk mengisi tabel Roles dengan beberapa role / peran. Silahkan jalankan perintah di bawah ini.

php artisan make:seeder RolesTableSeeder

Buka file seeder RolesTableSeeder.php, pada metode run() buat seperti di bawah ini.

public function run()
{
    $roles = [
        [
            'name' => "user", 
            'created_at' => new \DateTime,
            'updated_at' => null,
        ], 
        [
            'name' => "admin", 
            'created_at' => new \DateTime,
            'updated_at' => null,
        ], 
        [
            'name' => "manager", 
            'created_at' => new \DateTime,
            'updated_at' => null,
        ], 

    ];

    \DB::table('roles')->insert($roles);
}

Kemudian tambahkan class seeder pada file DatabaseSeeder.php seperti di bawah ini.

public function run()
{ 
    $this->call([ RolesTableSeeder::class ]);
}

Terahir, jalankan seeder.

php artisan db:seed

Setelah seeding berhasil, kita lihat pada tabel roles di database. Kita sudah memiliki beberapa peran yang siap digunakan.

MariaDB [db_lavueroles]> select id, name from roles;
+----+---------+
| id | name    |
+----+---------+
|  1 | user    |
|  2 | admin   |
|  3 | manager |
+----+---------+
3 rows in set (0.001 sec)

API Request: Registrasi

Kita lanjutkan membuat request, menyimpan data ke database. Kita akan kerjakan terlebih dahulu proses registrasi / pendaftaran pengguna baru.

Mari kita buat sebuah controller. Kita buat controller baru dengan nama UserController.

php artisan make:controller UserController

Kemudian buka UserController.php, buat seperti di bawah ini.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use Illuminate\Support\Facades\Hash; 
use App\Models\User; 

class UserController extends Controller
{
    public function register(Request $request)
    { 
        $request->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users',
            'password' => 'required|string|confirmed|min:8',
        ]);

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

        $user->roles()->attach(1); 
        
        return response()->json(['message' => 'Registration Successful.'], 201);
    }
}

Mari kita lihat metode attach() di atas. Kita gunakan metode ini untuk menambahkan atau melampirkan ID dari role yang ada pada tabel roles. Kita buat default value nya 1 untuk ID peran 'user'.

Kemudian agar kita dapat mengambil ID role pada tabel roles, kita perlu menjalin hubungkan. Sekarang kita buka model User.php, tambakan relasi dibawah ini.

public function roles()
{
    return $this->belongsToMany(Role::class);
}

Kita lanjutkan membuat route. Buka file route api.php, tambahkan route di bawah ini.

use App\Http\Controllers\UserController;

Route::post('/register', [UserController::class, 'register']);

Selanjutnya kita coba melakukan pendaftaran. Buka aplikasi postman, buat request seperti pada gambar di bawah.

  • Method => POST
  • URL => http://localhost:8000/api/register
  • Headers => key: Accept, value: application/json.
  • Body => form-data
Autentikasi Laravel-Vue.js Multiple Roles: User, Admin, Manager

Jika di lihat pada tabel role_user, akan berisi ID role dan ID user.

MariaDB [db_lavueroles]> select * from role_user;
+----+---------+---------+------------+------------+
| id | user_id | role_id | created_at | updated_at |
+----+---------+---------+------------+------------+
|  1 |       1 |       1 | NULL       | NULL       |
+----+---------+---------+------------+------------+
1 row in set (0.001 sec)

Postingan terkait Relasi: Belajar Relasi Eloquent Laravel

API Request: Login

Kita lanjutkan membuat request login user. Untuk langkah pertama kita lakukan konfigurasi JWT terlebih dahulu agar dapat menggunakannya dan menghasilkan token.

Silahkan buka model User.php, tambahkan JWTSubject, getJWTIdentifier(), dan getJWTCustomClaims(), seperti di bawah ini.

<?php

... 

use Tymon\JWTAuth\Contracts\JWTSubject;

class User extends Authenticatable implements JWTSubject
{
    ...

    public function getJWTIdentifier()
    {
        return $this->getKey();
    }
 
    public function getJWTCustomClaims()
    {
        return [];
    }
      
}

Kemudian buka config > auth.php, ubah guard dan api driver menjadi jwt seperti di bawah ini.

'defaults' => [ 
     'guard' => 'api',
     'passwords' => 'users',
],

'guards' => [
    ...
    
    'api' => [
        'driver' => 'jwt',
        'provider' => 'users',
        'hash' => false,
    ],
],

Setelah itu kita ke UserController.php, silahkan tambahkan metode login di bawah ini.

use Auth; 
use JWTAuth;
...

public function login(Request $request)
{  
    $credentials = $request->validate([
        'email' => ['required', 'email'],
        'password' => ['required'],
    ]);

    if (Auth::attempt($credentials)) { 
        $status = 200; 
        $user = Auth::user(); 
        $response = [ 
                'user' => array_merge($user->toArray(), 
                            ['roles' => $user->roles()->get()->toArray()]), 
                'token' => JWTAuth::fromUser($user), 
        ]; 
    }  else { 
        $status = 422;
        $response = ['error' => 'The email or password is incorrect.'];
    }

    return response()->json($response, $status);
}

Kita gunakan array_merge untuk menggabungkan elemen 'roles' ke properti 'user' agar menjadi satu objek.

Selanjutnya kita tambahkan route di api.php.

Route::post('login', [UserController::class, 'login']);

Sampai disini, mari kita coba untuk login. Buka kembali postman, buat request baru.

  • Method => POST
  • URL => http://localhost:8000/api/login
  • Headers => key: Accept, value: application/json.
  • Body => form-data
Autentikasi Laravel-Vue.js Multiple Roles: User, Admin, Manager
//response
{
    "user": {
        "id": 1,
        "name": "user",
        "email": "user@mail.com",
        "email_verified_at": null,
        "created_at": "2021-06-10T09:34:56.000000Z",
        "updated_at": "2021-06-10T09:34:56.000000Z",
        "roles": [
            {
                "id": 1,
                "name": "user",
                "created_at": "2021-06-10T07:47:17.000000Z",
                "updated_at": null,
                "pivot": {
                    "user_id": 1,
                    "role_id": 1
                }
            }
        ]
    },
    "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9sb2NhbGhvc3Q6O..."
}

Login berhasil. Sampai disini kita telah selesai membuat request API login dan registrasi user.

API Request: User

Selanjutnya kita buat request menampilkan / mengambil objek user. Silahkan buka UserController.php, tambahkan method di bawah ini.

public function getUser()
{
    $user = auth()->user();
    $data = array_merge($user->toArray(), ['roles' => $user->roles()->get()->toArray()]);
    return response()->json($data, 200);
}

Kemudian tambahkan route di api.php dan dengan menambahkan middleware auth:api, seperti di bawah ini.

Route::get('/user',[UserController::class, 'getUser'])->middleware('auth:api');  

Kita harus melewati verifikasi atau otorisasi token header untuk mendapatkan respon permintaan.

Buka kembali postman, kita buat request baru.

  • Method => GET
  • URL => http://localhost:8000/api/user
  • Headers => key: Accept, value: application/json.

Copas token dari hasil login pada header Authorization dengan format Bearer [token], seperti gambar di bawah ini.

Autentikasi Laravel-Vue.js Multiple Roles: User, Admin, Manager
//response
{
    "id": 1,
    "name": "user",
    "email": "user@mail.com",
    "email_verified_at": null,
    "created_at": "2021-06-10T09:34:56.000000Z",
    "updated_at": "2021-06-10T09:34:56.000000Z",
    "roles": [
        {
            "id": 1,
            "name": "user",
            "created_at": "2021-06-10T07:47:17.000000Z",
            "updated_at": null,
            "pivot": {
                "user_id": 1,
                "role_id": 1
            }
        }
    ]
}

Sampai disini, token sudah dapat digunakan untuk otorisasi.

Konfigurasi Vue dan Bootstrap

Kita beralih ke user interface, membuat komponen vue untuk halaman-halaman yang diperlukan dan membuat permintaan http ke api.

Kita mulai dari mengatur vue instance, vue router dan compiling css bootsrap terlebih dahulu; memastikan semua bekerja dan dapat digunakan.

Pertama, buka resources > js > app.js, buat seperti di bawah ini.

require('./bootstrap');

import Vue from 'vue';
import VueRouter from 'vue-router'

Vue.use(VueRouter)

import App from './components/App.vue'

const router = new VueRouter({
  mode: 'history',
  routes: [
     //
  ],
})

new Vue({
  el: '#app',
  components: { App },
  router,
});

Kemudian buat folder baru di direktori resources > js dengan nama components dan tambahkan component App.vue di dalamnya, lalu copas template dibawah ini.

<template>
  <div>
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
      <div class="container-fluid">
        <a class="navbar-brand" href="#">Navbar</a> 
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
          <ul class="navbar-nav me-auto mb-2 mb-lg-0">
            <li class="nav-item">
              <a class="nav-link active" aria-current="page" href="#">Home</a>
            </li>
          </ul>
          <ul class="navbar-nav">
            <li class="nav-item">
              <a href="#" class="nav-link">Login</a> 
            </li>
            <li class="nav-item"> 
              <a href="#" class="nav-link">Register</a> 
            </li>
          </ul>
        </div>
      </div>
    </nav>
    <main class="container-fluid py-4">
      <router-view></router-view>
    </main>
  </div>
</template>

Setelah itu, silahkan buat folder baru di direktori resources dengan nama sass dan tambakan file app.scss di dalamnya. Kemudian import bootstrap pada file app.scss.

//resources/sass/app.scss
@import '~bootstrap/scss/bootstrap';

Buka resources > bootstrap.js, tambahkan di bawah ini.

 try {
  window.Popper = require('popper.js').default;
  window.$ = window.jQuery = require('jquery');

  require('bootstrap');
} catch (e) {}

Buka file welcome.blade.php, ubah html yang ada dengan di bawah ini.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="csrf-token" content="{{csrf_token()}}">
    <title>Title</title>
    <link href=" {{ mix('css/app.css') }}" rel="stylesheet">
  </head>
  <body>
    <div id="app">
      <app></app>
    </div>
    <script src="{{ mix('js/app.js') }}"></script>
  </body>
</html>

Terakhir, buka webpack.mix.js, ubah path mix yang ada dengan di bawah ini.

mix.js('resources/js/app.js', 'public/js').vue()
   .sass('resources/sass/app.scss', 'public/css')
   .sourceMaps();

Lalu lakukan compiling.

npm run dev

Setelah selesai, jalankan aplikasi dan lihat pada browser.

php artisan serve
Autentikasi Laravel-Vue.js Multiple Roles: User, Admin, Manager

Vue, Vue Router dan Bootsrap siap digunakan.

Menambahkan komponen

Kita lanjutkan untuk membuat komponen-komponen vue yang diperlukan. Pada direktori components, silahkan buat beberapa komponen berikut:

  • Home.vue
  • Login.vue
  • Register.vue
  • User.vue
  • Admin.vue
  • Manager.vue
//Home.vue
<template>
  <div>
    Home
  </div>
</template>
//Login.vue
<template>
  <div>
    Login
  </div>
</template>
//Register.vue
<template>
  <div>
    Register
  </div>
</template>
//User.vue
<template>
  <div>
    User
  </div>
</template>
//Admin.vue
<template>
  <div>
    Admin
  </div>
</template>
//Manager.vue
<template>
  <div>
    Manager
  </div>
</template>

Kemudian import dan buat route untuk masing-masing komponen di app.js.

import Home from './components/Home.vue'
import Login from './components/Login.vue'
import Register from './components/Register.vue'
import User from './components/User.vue'
import Admin from './components/Admin.vue'
import Manager from './components/Manager.vue'

const router = new VueRouter({
  mode: 'history',
  routes: [
      {
          path: '/',
          name: 'home',
          component: Home
      },
      {
          path: '/login',
          name: 'login',
          component: Login
      },
      {
          path: '/register',
          name: 'register',
          component: Register
      },   
      {
          path: '/user',
          name: 'user',
          component: User
      },
      {
          path: '/admin',
          name: 'admin',
          component: Admin 
      }, 
      {
          path: '/manager',
          name: 'manager',
          component: Manager 
      } 
  ],
})

Buka file web.php, ubah route yang ada dengan di bawah ini.

Route::get('/{any}', function(){
    return view('welcome');
})->where('any', '.*');

Axios POST Request: Login

Setelah selesai membuat semua komponen, kita akan lanjutkan membuat http request menggunakan axios.

Kita kerjakan komponen login terlebih dahulu. Silahkan buka component Login.vue, buat seperti di bawah ini.

<template>
  <div class="row justify-content-md-center">
    <div class="col-5">
      <div class="card">
        <div class="card-body">  
          <div v-if="message" class="alert alert-success" role="alert">
              {{message}}
          </div>
          <h4 class="card-title">Login</h4>
          <h6 class="card-subtitle mb-2 text-muted">Login to your account</h6>
          <hr>
          <div v-if="error" class="alert bg-danger text-white ">
            {{ error }}
          </div>
          <form @submit.prevent="loginForm">
            <div class="mb-3">
              <label for="email" class="form-label">Email address</label>
              <input type="email" v-model="email" class="form-control" id="email" required>
            </div>
            <div class="mb-3">
              <label for="password" class="form-label">Password</label>
              <input type="password" v-model="password" class="form-control" id="password" required>
            </div>
            <button type="submit" class="btn btn-primary">Login</button>
          </form>
        </div>
      </div>
    </div>
  </div>
</template>
 
<script>
export default {
  data() {
      return {
        email: '',
        password: '',
        error: null,
        message: ''
      }
    },
    created() {
      if (this.$route.params.message !== undefined) {
        this.message = this.$route.params.message + ' Please login!'
      }
    },
    methods: {
      loginForm() {
        axios.post('api/login', {
            email: this.email,
            password: this.password
          })
          .then(response => {
            localStorage.setItem('user', JSON.stringify(response.data.user))
            localStorage.setItem('token', response.data.token)

            let loginType = response.data.user.roles[0].name
            if (loginType === 'user') {
              this.$router.push('user')
            } else if (loginType === 'admin') {
              this.$router.push('admin')
            } else if (loginType === 'manager') {
              this.$router.push('manager')
            } else {
              this.$router.push('home')
            }

            this.$emit('loggedIn')

          })
          .catch(error => {
            this.error = error.response.data.error;
          });
      }
    }
}
</script>

Mari kita lihat method loginForm() diatas. Pertama, ketika login berhasil, respon yang ada yaitu 'user' dan 'token' kita kirim atau simpan ke local storage browser. Kemudian respon array 'roles' kita lakukan mapping untuk mengambil value role.

Karena satu pengguna dapat memiliki banyak peran, kita hanya memilih peran utama dari user berdasarkan index pertama ([0]) array roles saat login.

Kita juga melakukan emit event untuk menyetel data ke DOM, membuat perubahan agar reaktif. Penerapanya, kita buat untuk bagian nav merubah status user.

Mari kita lanjutkan untuk membuat event listener, menangkap event. Kita buka komponen App.vue, pada <router-view>, buat seperti di bawah ini.

<router-view @loggedIn="setUser"></router-view>

Masih di komponen App.vue, tambahkan methods dan data properti seperti bawah ini.

<script>
export default {
  data() {
      return {
        user: null,
        isLoggedIn: false
      }
    },
    mounted() {
      this.setUser()
    },
    methods: {
      setUser() {
          this.user = JSON.parse(localStorage.getItem('user'))
          this.isLoggedIn = localStorage.getItem('token') != null

        },
        logout() {
          localStorage.removeItem('token')
          localStorage.removeItem('user')
          this.setUser()

          this.$router.push('/')
        }
    }
}
</script>

Lalu ubah semua tag a yang ada di bagian nav dengan router-link seperti di bawah ini.

<ul class="navbar-nav">
  <template v-if="isLoggedIn">
    <div v-for="role in user.roles" :key="role.id">
      <li class="nav-item">
        <router-link :to="{name: role.name}" class="nav-link">{{role.name}}</router-link>
      </li>
    </div>
    <li class="nav-item"><span class="nav-link" @click="logout">Logout</span></li>
  </template>
  <template v-if="!isLoggedIn">
    <li class="nav-item">
      <router-link :to="{name: 'login'}" class="nav-link">Login</router-link>
    </li>
    <li class="nav-item">
      <router-link :to="{name: 'register'}" class="nav-link">Register</router-link>
    </li>
  </template>
</ul>

Axios GET Request: User (pengguna saat ini)

Selanjutnya kita buat request api user. Silahkan copy template di bawah dan paste di 3 komponen, User.vue, Admin.vue, dan Manager.vue.

Silahkan ubah judul pada tag h1, sesuaikan dengan nama komponen.

//User.vue, Admin.vue, Manager.vue
<template>
  <div>
    <div class="row align-items-md-stretch">
      <div class="col-md-6">
        <div class="h-100 p-5 text-white bg-dark rounded-3">
          <h1>Dashboard, Admin.</h1>
          <label>Login sebagai:</label>
          <h2>{{loginType}}</h2>
        </div>
      </div>
      <div class="col-md-6">
        <div class="h-100 p-5 bg-light border rounded-3">
          <p>Peran yang dimiliki:</p>
          <ul v-for="role in user.roles" :key="role.id">
            <li> {{ role.name }} </li>
          </ul>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
      return {
        user: '',
        loginType: ''
      }
    },
    created() {
      axios.defaults.headers.common['Content-Type'] = 'application/json'
      axios.defaults.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('token')

      axios.get(`/api/user`)
        .then(response => {
          this.user = response.data
          this.loginType = response.data.roles[0].name
        })
        .catch(error => {
          if (error.response.status === 401) {
            localStorage.clear();
            this.$router.push('/login')
          }
          console.error(error);
        })
    }
}
</script>

Sampai disini, mari kita coba untuk login. Buat dua tab, jalankan npm run watch dan php artisan serve.

Buka http://localhost:8000/login, dan silahkan login.

  • email: user@mail.com
  • password: 12345678
Autentikasi Laravel-Vue.js Multiple Roles: User, Admin, Manager

Karena pengguna diatas memiliki peran 'user', maka menuju ke halaman atau dashbord user.

Axios POST Request: Register

Kita lanjutkan mengerjakan halaman register. Silahkan copas template di bawah ini pada komponen Register.vue.

<template>
  <div class="row justify-content-md-center">
    <div class="col-5">
      <div class="card">
        <div class="card-body">
          <h4 class="card-title">Register</h4>
          <h6 class="card-subtitle mb-2 text-muted">Create your account</h6>
          <hr>
          <div v-if="errors" class="alert bg-danger text-white ">
            <div v-for="(v, k) in errors" :key="k">
              <p v-for="error in v" :key="error" class="text-sm">
                {{ error }}
              </p>
            </div>
          </div>
          <form @submit.prevent="submitForm">
            <div class="mb-3">
              <label for="name" class="form-label">Name</label>
              <input type="text" v-model="user.name" class="form-control" id="name" required>
            </div>
            <div class="mb-3">
              <label for="email" class="form-label">Email address</label>
              <input type="email" v-model="user.email" class="form-control" id="email" required>
            </div>
            <div class="mb-3">
              <label for="password" class="form-label">Password</label>
              <input type="password" v-model="user.password" class="form-control" id="password" required>
            </div>
            <div class="mb-3">
              <label for="password confirmation" class="form-label">Confirm Password</label>
              <input type="password" v-model="user.password_confirmation" class="form-control" id="password_confirmation" required>
            </div>
            <button type="submit" class="btn btn-primary">Register</button>
          </form>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
      return {
        user: {
          name: '',
          email: '',
          password: '',
          password_confirmation: '',
        },
        errors: null,
      }
    },
    methods: {
      submitForm() {
        axios.post('api/register', this.user)
          .then(response => {
            this.$router.push({
              name: 'login',
              params: {
                message: response.data.message
              }
            })
          })
          .catch(error => {
            this.errors = error.response.data.errors;
          });
      }
    }
}
</script>

Setelah berhasil melakukan pendaftaran, kita mengalihkan dan mengirim respon ke halaman login.

Silahkan coba melakukan pendaftaran.

Autentikasi Laravel-Vue.js Multiple Roles: User, Admin, Manager

Setelah berhasil mendaftar, kita ubah terlebih dahulu peran user kedua yang baru mendaftar secara manual pada tabel role_user di database.

MariaDB [db_lavueroles]> select id, user_id, role_id from role_user;
+----+---------+---------+
| id | user_id | role_id |
+----+---------+---------+
|  1 |       1 |       1 |
|  2 |       2 |       2 |
+----+---------+---------+
2 rows in set (0.000 sec)

User dengan ID 2 memiliki role / peran 'admin'. Setelah diubah, silahkan coba login.

Autentikasi Laravel-Vue.js Multiple Roles: User, Admin, Manager

Proteksi Route

Selanjutnya yang akan kita kerjakan, dan yang terakhir, adalah memproteksi route. Kita akan membuat pemeriksaan route berdasarkan role dari pengguna.

Pada tahap ini kita menggunakan navigation guard dan membuat pernyataan kondisional.

Mari kita buka file app.js, silahkan tambahkan navigation guard di bawah ini, letakan di atas vue instance.

//app.js
...

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) {
    let token = localStorage.getItem('token') != null;
    if (!token) {
      next({
        path: '/login',
        query: {
          redirect: to.fullPath
        }
      })
    } else {
      let user = JSON.parse(localStorage.getItem('user'))
      let roles = user.roles.map(role => role.name)
      console.log(roles[0]);
      if (to.matched.some(record => record.meta.isUser)) {
        if (roles.includes('user')) next()
        else if (roles[0] === 'admin') {
          next({
            name: 'admin'
          })
        } else if (roles[0] === 'manager') {
          next({
            name: 'manager'
          })
        } else next({
          name: 'home'
        })
      } else if (to.matched.some(record => record.meta.isAdmin)) {
        if (roles.includes('admin')) next()
        else if (roles[0] === 'manager') {
          next({
            name: 'manager'
          })
        } else if (roles[0] === 'user') {
          next({
            name: 'user'
          })
        } else next({
          name: 'home'
        })

      } else if (to.matched.some(record => record.meta.isManager)) {
        if (roles.includes('manager')) next()
        else if (roles[0] === 'user') {
          next({
            name: 'user'
          })
        } else if (roles[0] === 'admin') {
          next({
            name: 'admin'
          })
        } else next({
          name: 'home'
        })

      } else {
        next()
      }
    }
  } else {
    next()
  }
})


new Vue({
  el: '#app',
  components: { App },
  router,
});

Diatas, kita buat setiap pengguna ketika akan menggunakan aplikasi, pengidentifikasian di lakukan pada proses masuk atau login.

Setelah login, pengidentifikasian dilakukan setiap pengguna membuka route yang di beri guard, dan akan menunda untuk dilakukan pemeriksaan, apakah di lanjutkan atau dikembalikan.

Selanjutnya tambakan properti meta pada route, seperti di bawah ini.

{
   path: '/user',
   name: 'user',
   component: User,
   meta: {
     requiresAuth: true,
     isUser: true
   }
}, {
   path: '/admin',
   name: 'admin',
   component: Admin,
   meta: {
      requiresAuth: true,
      isAdmin: true
   }
}, {
   path: '/manager',
   name: 'manager',
   component: Manager,
   meta: {
     requiresAuth: true,
     isManager: true
  }
}

Sampai disini tinggal mencobanya. Silahkan coba tahapan pengujian berikut untuk melihat bagaimana guard di atas bekerja:

  • Sebelum login, buka semua route yang ditambahkan meta field seperti di atas.
  • Setelah login, buka semua route dengan pengguna yang hanya memiliki satu peran.
  • Tambahkan peran pengguna. Buat satu pengguna memiliki semua peran dan buka semua route.

Selesai

Tahapan pembuatan autentikasi user dengan multiple role dan perlindungan navigasi selesai sampai disini.

Kita telah menerapkan kontrol akses berbasis peran. Silahkan dicoba, dikembangkan, dan lakukan eksperimen.

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel

Berlangganan

Berlangganan untuk mendapat pemberitahuan artikel terbaru via email.