Aplikasi Laundry (Laravel 5.8 - Vue.js - SPA) #6: Role & User Permissions

Aplikasi Laundry (Laravel 5.8 - Vue.js - SPA) #6: Role & User Permissions

Pendahuluan

Kopi hitam itu mengeluarkan aroma yang begitu menggoda, tak butuh waktu lama bagi barista cafe ini untuk menyajikannya. Tangannnya begitu telaten mencampurkan semua hal yang dibutuhkan agar kopi buatannya terasa nikmat. Sambil menikmati secangkir kopi ini, kutuliskan serial lanjutan membuat Aplikasi Laundry menggunakan Laravel 5.8 & Vue.js dengan metode SPA (Single Page Application) yang telah memasuki serial ke-6 nya dengan topik pembahasan adalah Role & Permission.

Fitur ini begitu penting karena berfungsi untuk memberikan sekat antar pengguna sehingga ada batasan yang dimiliki oleh masing-masing user guna melindungi dari apa yang tidak seharusnya bisa dilihatnya. Sebenarnya materi ini sudah pernah dibahas dalam artikel Membuat Aplikasi Point of Sales (POS) , namun pada materi ini, penyajiannya sedikit berbeda karena yang akan digunakan oleh Vue.js sebagai client.

Baca Juga: Aplikasi Laundry (Laravel 5.8 - Vue.js - SPA) #5: Manage Laundry Products

Create Role & Permission Schema

Tampaknya kopi ini benar-benar menggoda, begitupun dengan schema role & permission bukan perkara sulit untuk menyajikannya karena telah tersedia sebuah library besutan Spatie - Role & Permission.

Tahap pertama, install library tersebut dengan command:

composer require spatie/laravel-permission

Kemudian publish migration-nya dengan command:

php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="migrations"

Lanjut, eksekusi migration yang telah di-publish menggunakan command:

php artisan migrate

Terakhir, buka file app/User.php dan tambahkan use statement:

use Spatie\Permission\Traits\HasRoles;

//didalam class
use Notifiable, HasRoles;

role permission laravel vuejs

Adapun fitur untuk membuat role-nya (CRUD) akan kita skip karena bisa mengikuti artikel Aplikasi POS (Role Permission), sedangkan pada artikel ini kita akan menggunakan cara cepatnya saja dengan fungsi artisan command. Pada command line, jalankan perintah dibawah ini satu persatu.

php artisan permission:create-role superadmin
php artisan permission:create-role admin
php artisan permission:create-role finance
php artisan permission:create-role courier

Dan untuk permission-nya masih dengan artisan command:

php artisan permission:create-permission "read outlets"
php artisan permission:create-permission "create outlets"
php artisan permission:create-permission "edit outlets"
php artisan permission:create-permission "delete outlets"

php artisan permission:create-permission "read couriers"
php artisan permission:create-permission "create couriers"
php artisan permission:create-permission "edit couriers"
php artisan permission:create-permission "delete couriers"

php artisan permission:create-permission "read products"
php artisan permission:create-permission "create products"
php artisan permission:create-permission "edit products"
php artisan permission:create-permission "delete products"

Assign Role Permissions

Setiap kopi punya cara menikmatinya sendiri, begitupun dengan role, setiap role harus memiliki permission-nya masing-masing. Pada sub-chapter ini kita akan membuat fitur agar memungkinkan user untuk memberikan permission pada masing-masing role yang ada.

Pertama kita akan membuat index halamannya terlebih dahulu, definisikan routing berikut pada vue.js dengan membuat file resources/js/router.js dan tambahkan code:

{
    path: '/setting',
    component: Setting,
    meta: { requiresAuth: true },
    children: [
        {
            path: 'role-permission',
            name: 'role.permissions',
            component: SetPermission,
            meta: { title: 'Set Permissions' }
        },
    ]
}

Masih dengan file yang sama, tambahkan code berikut pada bagian import statement:

import Setting from './pages/setting/Index.vue'
import SetPermission from './pages/setting/roles/SetPermission.vue'

Terdapat dua buah file yang diperlukan, pertama buat file Index.vue di dalam folder /pages/setting dan tambahkan code:

<template>
    <div class="container">
        <section class="content-header">
            <h1>
                Settings Page
            </h1>
            <breadcrumb></breadcrumb>
        </section>

        <section class="content">
            <div class="row">
                <router-view></router-view>
            </div>
        </section>
    </div>
</template>
<script>
    import Breadcrumb from '../../components/Breadcrumb.vue'
    export default {
        name: 'IndexSetting',
        components: {
            'breadcrumb': Breadcrumb
        }
    }
</script>

Note: Tidak ada yang spesial dari code di atas, karena hanya berfungsi sebagai induk pages.

Kemudian buat file SetPermission.vue di dalam folder /pages/setting/roles dan tambahkan code:

<template>
    <div class="col-md-12">
        <div class="row">
            <div class="col-md-5">
                <div class="panel">
                    <div class="panel-heading">
                        <h3 class="panel-title">Assign Role to User</h3>
                    </div>
                  	
                  	<!-- FORM UNTUK MENAMBAHKAN ROLE KE USERS -->
                    <div class="panel-body">
                        <div class="alert alert-success" v-if="alert_role">Role Has Been Added</div>
                        <div class="form-group">
                            <label for="">Role</label>
                            <select class="form-control" v-model="role_user.role">
                                <option value="">Pilih</option>
                                <option v-for="(row, index) in roles" :value="row.name" :key="index">{{ row.name }}</option>
                            </select>
                            <p class="text-danger" v-if="errors.role_id">{{ errors.role_id[0] }}</p>
                        </div>
                        <div class="form-group">
                            <label for="">User</label>
                            <select class="form-control" v-model="role_user.user_id">
                                <option value="">Pilih</option>
                                <option v-for="(row, index) in users" :value="row.id" :key="index">{{ row.name }} ({{row.email}})</option>
                            </select>
                        </div>
                        <div class="form-group">
                            <button class="btn btn-danger btn-sm" @click="setRole">Set Role</button>
                        </div>
                    </div>
                    <!-- FORM UNTUK MENAMBAHKAN ROLE KE USERS -->
                  
                </div>
            </div>
            <div class="col-md-7">
                <div class="panel">
                    <div class="panel-heading"><h3 class="panel-title">Set Permission</h3></div>
                  	<!-- FORM UNTUK MENAMBAHKAN PERMISSION KE MASING-MASING ROLE -->
                    <div class="panel-body">
                        <div class="form-group">
                            <label for="">Role</label>
                            <select class="form-control" v-model="role_selected">
                                <option value="">Pilih</option>
                                <option v-for="(row, index) in roles" :value="row.id" :key="index">{{ row.name }}</option>
                            </select>
                            <p class="text-danger" v-if="errors.role_id">{{ errors.role_id[0] }}</p>
                        </div>
                        <div class="form-group">
                            <button class="btn btn-primary btn-sm" @click="checkPermission">{{ loading ? 'Loading...':'Check' }}</button>
                        </div>
                        <div class="form-group">
                            <div class="alert alert-success" v-if="alert_permission">Permission has been assigned</div>
                            <div class="nav-tabs-custom">
                                <ul class="nav nav-tabs">
                                    <li class="active">
                                        <a href="#tab_1" data-toggle="tab">Permissions</a>
                                    </li>
                                </ul>
                                <div class="tab-content">
                                    <div class="tab-pane active" id="tab_1">
                                        <template v-for="(row, index) in permissions">
                                            <input type="checkbox" 
                                                class="minimal-red" 
                                                :key="index"
                                                :value="row.name"
                                                :checked="role_permission.findIndex(x => x.name == row.name) != -1"
                                                @click="addPermission(row.name)"
                                                > {{ row.name }} <br :key="'row' + index">
                                            <br :key="'enter' + index" v-if="(index+1) %4 == 0">
                                        </template>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="pull-right">
                            <button class="btn btn-primary btn-sm" @click="setPermission">
                                <i class="fa fa-send"></i> Set Permission
                            </button>
                        </div>
                    </div>
                    <!-- FORM UNTUK MENAMBAHKAN PERMISSION KE MASING-MASING ROLE -->
                  
                </div>
            </div>
        </div>
    </div>
</template>
<script>
    import { mapActions, mapState, mapMutations } from 'vuex'
    
    export default {
        name: 'SetPermission',
        data() {
            return {
                role_user: {
                    role: '',
                    user_id: ''
                },
                role_selected: '',
                new_permission: [],
                loading: false,
                alert_permission: false,
                alert_role: false
            }
        },
        created() {
            //KETIKA COMPONENT DI-LOAD, MAKA KITA AKAN ME-REQUEST 3 DATA BERIKUT
            this.getRoles() //DATA ROLES
            this.getAllPermission() //DATA PERMISSIONS
            this.getUserLists() //DATA USERS
        },
        computed: {
            ...mapState(['errors']), //ME-LOAD STATE ERRORS
            ...mapState('user', {
                users: state => state.users, //ME-LOAD STATE USERS
                roles: state => state.roles, //ME-LOAD STATE ROLES
                permissions: state => state.permissions, //ME-LOAD STATE PERMISSION
                
                //STATE YANG MENAMPUNG PERMISSION YG TELAH DI-ASSIGN
                role_permission: state => state.role_permission
            })
        },
        methods: {
            //LOAD SEMUA FUNGSI YANG ADA DI MODULE STORE USER
            ...mapActions('user', [
                'getUserLists', 
                'getRoles', 
                'getAllPermission', 
                'getRolePermission', 
                'setRolePermission',
                'setRoleUser'
            ]),
            //LOAD MUTATIONS DARI STORE USER
            ...mapMutations('user', ['CLEAR_ROLE_PERMISSION']),
            //FUNGSI INI AKAN BERJALAN KETIKA TOMBOL SET ROLE DIKLIK
            setRole() {
                //KIRIM PERMINTAAN KE BACKEND
                this.setRoleUser(this.role_user).then(() => {
                    this.alert_role = true //AKTIFKAN ALERT JIKA BERHASIL
                    setTimeout(() => {
                        //BEBERAPA DETIK KEMUDIAN, SET DEFAULT ROLE USER
                        this.role_user = {
                            role: '',
                            user_id: ''
                        }
                        //MATIKAN ALERT
                        this.alert_role = false
                    }, 1000)
                })
            },
            //KETIKA LIST PERMISSION DI CENTANG, MAKA FUNGSI INI BERJALAN
            addPermission(name) {
                //DICEK KE NEW_PERMISSION BERDASARKAN NAME
                let index = this.new_permission.findIndex(x => x == name)
                //APABIL TIDAK TERSEDIA, INDEXNYA -1
                if (index == -1) {
                    //MAKA TAMBAHKAN KE LIST
                    this.new_permission.push(name)
                } else {
                    //JIKA SUDAH ADA, MAKA HAPUS DARI LIST
                    this.new_permission.splice(index, 1)
                }
            },
            //KETIKA TOMBOL CHECK DITEKAN, MAKA FUNGSI INI BERJALAN
            //FUNGSI INI UNTUK MENGAMBIL LIST PERMISSION YANG TELAH DI ASSIGN
            //KE DALAM ROLE YANG DIPILIH
            checkPermission() {
                this.loading = true //AKTIFKAN LOADING TOMBOL
                //KIRIM PERMINTAAN KE BACKEND
                this.getRolePermission(this.role_selected).then(() => {
                    //APABILA BERHASIL, MATIKAN LOADING
                    this.loading = false
                    //PERMISSION YANG TELAH DIASSIGN AKAN DI MERGE KE NEW_PERMISSION
                    this.new_permission = this.role_permission
                })
            },
            //FUNGSI INI BERJALAN KETIKA TOMBOL SET PERMISSION DITEKAN
            setPermission() {
                //KIRIM PERMINTAAN KE SERVER
                this.setRolePermission({
                    role_id: this.role_selected,
                    permissions: this.new_permission
                }).then((res) => {
                    //APABIL BERHASIL
                    if (res.status == 'success') {
                        //NYALAKAN ALERT
                        this.alert_permission = true
                        setTimeout(() => {
                            //BEBERAPA DETIK KEMUDIAN, KEMBALIKAN KE DEFAULT
                            this.role_selected = ''
                            this.new_permission = []
                            this.loading = false
                            this.alert_permission = false
                            this.CLEAR_ROLE_PERMISSION()
                        }, 1000)
                    }
                })
            }
        }
    }
</script>

<style type="text/css">
    .tab-pane{
        height:150px;
        overflow-y:scroll;
    }
</style>

File di atas membutuhkan role module user untuk mengelola request dan state yang dibutuhkan, buat file user.js di dalam folder /stores dan tambahkan code:

import $axios from '../api.js'

const state = () => ({
    users: [], //MENAMPUNG LIST USER
    roles: [], //MENAMPUNG LIST ROLES
    permissions: [], //MENAMPUNG LIST PERMISSION
    role_permission: [], //MENAMPUNG PERMISSION YANG DIMILIKI OLEH ROLE
    authenticated: [] //MENAMPUNG USER YANG SEDANG LOGIN
})

const mutations = {
    ASSIGN_USER(state, payload) {
        state.users = payload
    },
    ASSIGN_ROLES(state, payload) {
        state.roles = payload
    },
    ASSIGN_PERMISSION(state, payload) {
        state.permissions = payload
    },
    ASSIGN_ROLE_PERMISSION(state, payload) {
        state.role_permission = payload
    },
    CLEAR_ROLE_PERMISSION(state, payload) {
        state.role_permission = []
    },
    ASSIGN_USER_AUTH(state, payload) {
        state.authenticated = payload
    }
}

const actions = {
    //FUNGSI INI UNTUK MENGAMBIL DATA USER
    getUserLists({ commit }) {
        return new Promise((resolve, reject) => {
            //KIRIM PERMINTAAN KE BACKEND
            $axios.get(`/user-lists`)
            .then((response) => {
                //SIMPAN DATANYA KE STATE USERS MENGGUNAKAN MUTATIONS
                commit('ASSIGN_USER', response.data.data)
                resolve(response.data)
            })
        })
    },
    //FUNGSI INI UNTUK MENGATUR ROLE TIAP USER
    setRoleUser({commit}, payload) {
        return new Promise((resolve, reject) => {
            commit('CLEAR_ERRORS', '', {root: true}) //STATE ERROR DIBERSIHKAN
            //KIRIM PERMINTAAN KE BACKEND
            $axios.post(`/set-role-user`, payload)
            .then((response) => {
                resolve(response.data)
            })
            .catch((error) => {
                //APABILA TERJADI ERROR VALIDASI, SET ERRONYA AGAR DAPAT DITAMPILKAN
                if (error.response.status == 422) {
                    commit('SET_ERRORS', error.response.data.errors, { root: true })
                }
            })
        })
    },
    //UNTUK MENGAMBIL LIST ROLES
    getRoles({ commit }) {
        return new Promise((resolve, reject) => {
            //KIRIM PERMINTAAN KE BACKEND
            $axios.get(`/roles`)
            .then((response) => {
                //SIMPAN DATANYA KE DALAM STATE ROLES
                commit('ASSIGN_ROLES', response.data.data)
                resolve(response.data)
            })
        })
    },
    //MENGAMBIL LIST PERMISSIONS
    getAllPermission({ commit }) {
        return new Promise((resolve, reject) => {
            //KIRIM PERMINTAAN KE BACKEND
            $axios.get(`/permissions`)
            .then((response) => {
                //SIMPAN DATA YANG DITERIMA KE DALAM STATE PERMISSIONS
                commit('ASSIGN_PERMISSION', response.data.data)
                resolve(response.data)
            })
        })
    },
    //MENGAMBIL PERMISSION YANG TELAH DIMILIKI OLEH ROLE TERTENTU
    getRolePermission({ commit }, payload) {
        return new Promise((resolve, reject) => {
            commit('CLEAR_ERRORS', '', {root: true}) //BERSIHKAN STATE ERRORS
            //KIRIM PERMINTAAN KE BACKEND BERDASARKAN ROLE_ID
            $axios.post(`/role-permission`, {role_id: payload})
            .then((response) => {
                //SIMPAN DATANYA DENGAN MUTATIONS
                commit('ASSIGN_ROLE_PERMISSION', response.data.data)
                resolve(response.data)
            })
        })
    },
    //BERFUNGSI UNTUK MENGATUR PERMISSION SETIAP ROLEH YANG DIPILIH
    setRolePermission({ commit }, payload) {
        return new Promise((resolve, reject) => {
            commit('CLEAR_ERRORS', '', {root: true})
            //KIRIM PERMINTAAN KE BACKEND
            $axios.post(`/set-role-permission`, payload)
            .then((response) => {
                resolve(response.data)
            })
            .catch((error) => {
                //APABILA TERJADI ERROR VALIDASI
                if (error.response.status == 422) {
                    //SET ERRORNYA AGAR DAPAT DITAMPILKAN
                    commit('SET_ERRORS', error.response.data.errors, { root: true })
                }
            })
        })
    },
    //MENGAMBIL DATA USER YANG SEDANG LOGIN
    getUserLogin({ commit }) {
        return new Promise((resolve, reject) => {
            $axios.get(`user-authenticated`)
            .then((response) => {
                //SIMPAN DATA USER TERSEBUT
                commit('ASSIGN_USER_AUTH', response.data.data)
                resolve(response.data)
            })
        })
    }
}

export default {
    namespaced: true,
    state,
    actions,
    mutations
}

Daftarkan module tersebut agar dapat digunakan, buka file store.js dan tambahkan:

import user from './stores/user.js'

//[.. CODE SEBELUMNYA ..]
modules: {
    auth,
    outlet,
    courier,
    product,
    user //TAMBAHKAN LINE INI
},

Dari sisi client sudah beres, saatnya berpindah pada sisi server, dimana dalam hal ini akan di-handle oleh Laravel. Pada command line, buat controller berikut dengan command:

php artisan make:controller API/RolePermissionController

Buka file RolePermissionController.php dan modifikasi menjadi:

<?php

namespace App\Http\Controllers\API;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
use DB;
use App\User;

class RolePermissionController extends Controller
{
    //METHOD INI UNTUK MENGAMBIL SEMUA ROLE YANG TERSEDIA
    public function getAllRole()
    {
        $roles = Role::all();
        return response()->json(['status' => 'success', 'data' => $roles]);
    }

    //METHOD INI UNTUK MENGAMBIL SEMUA PERMISSION YANG TERSEDIA 
    public function getAllPermission()
    {
        $permission = Permission::all();
        return response()->json(['status' => 'success', 'data' => $permission]);
    }

    //METHOD UNTUK MENGAMBIL PERMISSION YANG DIMILIKI OLEH ROLE TERTENTU
    public function getRolePermission(Request $request)
    {   
        //MELAKUKAN QUERY UNTUK MENGAMBIL PERMISSION NAME BERDASARKAN ROLE_ID
        $hasPermission = DB::table('role_has_permissions')
            ->select('permissions.name')
            ->join('permissions', 'role_has_permissions.permission_id', '=', 'permissions.id')
            ->where('role_id', $request->role_id)->get();
        return response()->json(['status' => 'success', 'data' => $hasPermission]);
    }

    //FUNGSI INI UNTUK MENGATUR PERMISSION DARI ROLE YANG DIPILIH
    public function setRolePermission(Request $request)
    {
        //VALIDASI
        $this->validate($request, [
            'role_id' => 'required|exists:roles,id'
        ]);

        $role = Role::find($request->role_id); //AMBIL ROLE BERDASARKAN ID
        $role->syncPermissions($request->permissions); //SET PERMISSION UNTUK ROLE TERSEBUT
        //syncPermissions BEKERJA CARA MENGHAPUS SEMUA ROLE YANG DIMILIKI, KEMUDIAN
        //MENYIMPAN DATA YANG BARU
        //PARAMETER PERMISSIONS ADALAH ARRAY YANG BERISI NAME PERMISSIONS
        return response()->json(['status' => 'success']);
    }

    //UNTUK MENGATUR ROLE SETIAP USER
    public function setRoleUser(Request $request)
    {
        //VALIDASI
        $this->validate($request, [
            'user_id' => 'required|exists:users,id',
            'role' => 'required'
        ]);

        $user = User::find($request->user_id); //AMBIL USER BERDASARKAN ID
        $user->syncRoles([$request->role]); //SET ROLE UNTUK USER TERKAIT
        return response()->json(['status' => 'success']);
    }
}

Definisikan routing dari method yang terdapat pada controller di atas, buka file routes/api.php dan tambahkan code:

Route::get('roles', 'API\RolePermissionController@getAllRole')->name('roles');
Route::get('permissions', 'API\RolePermissionController@getAllPermission')->name('permission');
Route::post('role-permission', 'API\RolePermissionController@getRolePermission')->name('role_permission');
Route::post('set-role-permission', 'API\RolePermissionController@setRolePermission')->name('set_role_permission');
Route::post('set-role-user', 'API\RolePermissionController@setRoleUser')->name('user.set_role');

Masih melanjutkan pada sisi backend, buka file UserController.php dan tambahkan method:

public function userLists()
{
    $user = User::where('role', '!=', 3)->get();
    return new UserCollection($user);
}

public function getUserLogin()
{
    $user = request()->user(); //MENGAMBIL USER YANG SEDANG LOGIN
    $permissions = [];
    foreach (Permission::all() as $permission) {
        //JIKA USER YANG SEDANG LOGIN PUNYA PERMISSION TERKAIT
        if (request()->user()->can($permission->name)) {
            $permissions[] = $permission->name; //MAKA PERMISSION TERSEBUT DITAMBAHKAN
        }
    }
    $user['permission'] = $permissions; //PERMISSION YANG DIMILIKI DIMASUKKAN KE DALAM DATA USER.
    return response()->json(['status' => 'success', 'data' => $user]);
}

Penjelasan: Jadi kita mengambil data user yang memiliki role tidak sama dengan 3, karena role 3 adalah miliki kurir, dimana kurir sudah memiliki module tersendiri untuk mengelolanya.

Adapun pada method store() dengan file yang sama, kita modifikasi sedikit menjadi:

public function store(Request $request)
{
    $this->validate($request, [
        'name' => 'required|string|max:150',
        'email' => 'required|email|unique:users,email',
        'password' => 'required|min:6|string',
        'outlet_id' => 'required|exists:outlets,id',
        'photo' => 'required|image'
    ]);

    DB::beginTransaction();
    try {
        $name = NULL;
        if ($request->hasFile('photo')) {
            $file = $request->file('photo');
            $name = $request->email . '-' . time() . '.' . $file->getClientOriginalExtension();
            $file->storeAs('public/couriers', $name);
        }
        $user = User::create([ //MODIFIKASI BAGIAN INI DENGAN MEMASUKKANYA KE DALAM VARIABLE $USER
            'name' => $request->name,
            'email' => $request->email,
            'password' => $request->password,
            'role' => $request->role,
            'photo' => $name,
            'outlet_id' => $request->outlet_id,
            'role' => 3
        ]);
        $user->assignRole('courier'); //TAMBAHKAN BAGIAN UNTUK MENAMBAHKAN ROLE COURIER
        DB::commit();
        return response()->json(['status' => 'success'], 200);
    } catch (\Exception $e) {
        DB::rollback();
        return response()->json(['status' => 'error', 'data' => $e->getMessage()], 200);
    }
}

Jangan lupa, pada file UserController tambahkan use statement:

use Spatie\Permission\Models\Permission;

Kembali ke file routes/api.php, tambahkan kedua route berikut:

Route::get('user-authenticated', 'API\UserController@getUserLogin')->name('user.authenticated');
Route::get('user-lists', 'API\UserController@userLists')->name('user.index');

role permission vuejs

Use Permission With Vue.js

Udara dingin kota ini membuat hangatnya kopi tak bisa bertahan lama, maka sesegera mungkin kopi ini harus tuntas sebelum kenikmatannya direnggut oleh udara ini. Selaras dengan itu, kutuliskan cara untuk menggunakan permission yang telah dimiliki oleh user yang sedang login.

Pertama, buat file permission.js di dalam folder resources/js/mixins (buat foldernya mixins jika belum ada), kemudian tambahkan code:

export default {
    methods: {
        $can(permissionName) {
            let Permission = this.$store.state.user.authenticated.permission
            if (typeof Permission != 'undefined') {
                return Permission.indexOf(permissionName) !== -1;
            }
        },
    },
};

Kemudian buka file app.js dan import file di atas:

import Permissions from './mixins/Permission.js'
Vue.mixin(Permissions)

import { mapActions, mapGetters } from 'vuex'

Masih dengan file yang sama, tambahkan code di bawah ini:

//[.. CODE SEBELUMNYA ..]
computed: {
    ...mapGetters(['isAuth'])
},
methods: {
    ...mapActions('user', ['getUserLogin'])
},
created() {
    if (this.isAuth) {
        this.getUserLogin() //REQUEST DATA YANG SEDANG LOGIN
    }
}

Untuk membatasi menu yang ditampilkan berdasarkan permission yang dimiliki, buka file resources/js/components/Header.vue dan modifikasi beberapa bagian berikut:

<ul class="nav navbar-nav">
    <li><router-link to="/">Home <span class="sr-only">(current)</span></router-link></li>
    <li v-if="$can('read outlets')"><router-link :to="{ name: 'outlets.data' }">Outlets</router-link></li>
    <li v-if="$can('read couriers')"><router-link :to="{ name: 'couriers.data' }">Couriers</router-link></li>
    <li v-if="$can('read products')"><router-link :to="{ name: 'products.data' }">Products</router-link></li>
    <li class="dropdown" v-if="authenticated.role == 0">
        <a href="javascript:void(0)" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="true">Settings <span class="caret"></span></a>
        <ul class="dropdown-menu" role="menu">
            <li><router-link :to="{name: 'role.permissions'}">Role Permission</router-link></li>
        </ul>
    </li>
</ul>

Penjelasan: Tag diatas adalah pada bagian link navigasi yang kita modifikasi dengan menambahkan v-if="$can('nama permission')"

Masih dengan file yang sama, pada bagian tag script, modifikasi manjadi:

import { mapState } from 'vuex'
export default {
    computed: {
        ...mapState('user', {
            authenticated: state => state.authenticated //ME-LOAD STATE AUTHENTICATED
        })
    },
    methods: {
        //KETIKA TOMBOL LOGOUT DITEKAN, FUNGSI INI DIJALANKAN
        logout() {
            return new Promise((resolve, reject) => {
                localStorage.removeItem('token') //MENGHAPUS TOKEN DARI LOCALSTORAGE
                resolve()
            }).then(() => {
                //MEMPERBAHARUI STATE TOKEN
                this.$store.state.token = localStorage.getItem('token')
                this.$router.push('/login') //REDIRECT KE PAGE LOGIN
            })
        }
    }
}

Lagi-lagi dengan file yang sama, modifikasi tepat pada bagian tag berikut:

<li class="dropdown user user-menu">
  <a href="#" class="dropdown-toggle" data-toggle="dropdown">
      <img src="https://via.placeholder.com/160" class="user-image" alt="User Image">
    	
    	<!-- MODIFIKASI BAGIAN INI -->
      <span class="hidden-xs">{{ authenticated.name }}</span>
  </a>
  <ul class="dropdown-menu">
      <li class="user-header">
          <img src="https://via.placeholder.com/160" class="img-circle" alt="User Image">
          
          <!-- MODIFIKASI BAGIAN INI -->
          <p>{{ authenticated.name }}</p>
      </li>
      <li class="user-body">
          <div class="row">
              <!-- <div class="col-xs-4 text-center">
                  <a href="#">Followers</a>
              </div>
              <div class="col-xs-4 text-center">
                  <a href="#">Sales</a>
              </div>
              <div class="col-xs-4 text-center">
                  <a href="#">Friends</a>
              </div> -->
          </div>
      </li>
      <li class="user-footer">
          <div class="pull-left">
              <a href="#" class="btn btn-default btn-flat">Profile</a>
          </div>
          <div class="pull-right">
              
              <!-- MODIFIKASI BAGIAN INI -->
              <a href="javascript:void(0)" @click="logout" class="btn btn-default btn-flat">Sign out</a>
            
          </div>
      </li>
  </ul>
</li>

Fungsi untuk mengambil data sedang login kita tempatkan di dalam file app.js pada bagian created(), sehingga fungsi tersebut berjalan ketika page di-load, akan tetapi masalahnya adalah jika kondisi user belum login, maka fungsi tersebut tidak akan dijalankan. Jadi kita perlu membuat sedikit trik, ketika user berhasil login dan meninggalkan page /login, maka fungsi untuk mengambil data yang sedang login dijalankan.

Buka file Login.vue dan tambahkan code berikut:

methods: {
    ...mapActions('auth', ['submit']),
    ...mapActions('user', ['getUserLogin']), //TAMBAHKAN BAGIAN INI
    
    //[.. CODE SETELAHNYA ..]
},
//TAMBAHKAN BAGIAN INI
destroyed() {
    this.getUserLogin()
}
//TAMBAHKAN BAGIAN INI

Note: Fungsi getUserLogin() akan berjalankan ketika component Login.vue di-destroy (ditinggalkan).

Tugas selanjutnya adalah melakukan modifikasi pada bagian konfigurasi axios, buka file api.js dan modifikasi menjadi:

import axios from 'axios';
import store from './store.js' //IMPORT BAGIAN INI

const $axios = axios.create({
    baseURL: '/api',
    headers: {
        //MATIKAN BAGIAN INI
        // Authorization: localStorage.getItem('token') != 'null' ? 'Bearer ' + localStorage.getItem('token'):'',
        'Content-Type': 'application/json'
    }
});

//KONFIGURASINYA KITA PINDAHKAN MENGGUNAKAN INTERCEPTORS
$axios.interceptors.request.use (
    function (config) {
        const token = store.state.token
        if (token) config.headers.Authorization = `Bearer ${token}`;
        return config;
    },
    function (error) {
        return Promise.reject (error);
    }
);
  
export default $axios;

Sampai pada tahap ini, semua yang dibutuhkan sudah selesai bersamaan dengan habisnya segelas kopi hari ini yang berarti akan kita akhiri artikel ini. Akan tetapi, pada artikel sebelumnya saya membuat kesalahan dimana pada saat menyimpan password pada data kurir, kita tidak melakukan enkripsi menggunakan bcrypt(), sehingga password yang disimpan masih dalam bentuk string aslinya. Buka file User.php dan tambahkan Mutator berikut:

public function setPasswordAttribute($value)
{
    $this->attributes['password'] = bcrypt($value);
}

Baca Juga: Tips Optimasi Meningkatkan Performance Laravel

Kesimpulan

Adapun untuk proses testing fungsi yang telah kita buat, hapus semua data kurir terlebih dahulu. Kemudian tambahkan lagi dengan data yang baru dan jangan lupa set permission untuk administrator dan kurir sesuai batasan akses yang kamu inginkan.

Adapun dokumentasi code dapat kamu lihat di Github.

Category:
Share:

Comments