How to Add Roles and Permission to Laravel Fortify + Inertia + vue?
Asked Answered
C

2

6

my project use laravel fortify, inertia with vue. i have to add role based permissions (just like spatie permissions package). i'm still a beginner to fortify and inertia. but i have experience in spatie package. i'm stuck with how add roles and permission to fortify. currently i'm planning to create table structure like spatie package have(roles, permssions, roles_has_permissions ,etc). is there per-build package or better way to implement roles and permissions ? and use '@can' in vue files? thank you.

edit

hello guys,this is i'm currently did(im using this now ). it is working but still need some improvements, (any better solution i really appreciate it)

1)installed and configured as usual spatie/laravel-permission

2)added predefined permissions and roles to tables using seeder

  1. created function in user model to get permission array list

    // user model function
    public function getPermissionArray()
     {
         return $this->getAllPermissions()->mapWithKeys(function($pr){
             return [$pr['name'] => true];
         });
    
     }
    
  2. and added that function to inertia middleware

//App\Http\Middleware\HandleInertiaRequests
public function share(Request $request)
{
     return array_merge(parent::share($request), [
          'auth'=>['user' => $request->user() ?   $request->user()->only('id', 'name', 'email') : null,
                    'can' =>$request->user() ? $request->user()->getPermissionArray() : []
                ],
        ]);
}

now $page.props.auth.can can access globally

  1. added permission check in vue file
   <div class="row">
              <div class="col-sm-12 col-md-6" v-if="$page.props.auth.can['user_create']">
                <inertia-link
                  class="btn btn-primary"
                  :href="$route('admin.user.create')"
                  >Create New
                </inertia-link>
              </div>
   </div>
Caitiff answered 24/11, 2020 at 5:35 Comment(4)
I think this documentation may have a clue for you inertiajs.com/authorizationHypoxanthine
wow thanks. so its possible to use same spattie package and inject its function to this 'can' function?Caitiff
I never use spattie package for authorization, laravel authorization is quite enough for me.Hypoxanthine
i tried using inertia middleware . looks working. but don't know performance wise how reliable it.( i added it above)Caitiff
C
16

I resolved issue like below, first I'm sending permission array to UI.

in user model

<?php
    // user model function
    public function getPermissionArray()
     {
         return $this->getAllPermissions()->mapWithKeys(function($pr){
             return [$pr['name'] => true];
         });
    
     }

in inertia share middleware

<?php
//App\Http\Middleware\HandleInertiaRequests
public function share(Request $request)
{
     return array_merge(parent::share($request), [
          'auth'=>['user' => $request->user() ?   $request->user()->only('id', 'name', 'email') : null,
                    'can' =>$request->user() ? $request->user()->getPermissionArray() : []
                ],
        ]);
}

in app js file, I have added global function to check one or many permssion have user

import Vue from 'vue'


Vue.mixin({
  methods: {
    hasAnyPermission: function (permissions) {

      var allPermissions = this.$page.props.auth.can;
      var hasPermission = false;
      permissions.forEach(function(item){
        if(allPermissions[item]) hasPermission = true;     
      });
      return hasPermission;
    },
  },
})

in vue components :

<script>
       
   export default {
       data() {
            return {};
       },
      mounted: function () {},
      methods: {},
   };
</script>
        
<template>
      <div>  
          <li v-if="hasAnyPermission(['testiml_view', 'testiml_edit', 'testiml_create'])">
              <inertia-link
                :href="$route('admin.testimonial.index')"
                class="side-nav-link-a-ref"
              >
                <i class="fas fa-feather"></i>
                <span>Testimonial</span>
              </inertia-link>
            </li>
</div>
</template>
Caitiff answered 11/4, 2021 at 5:37 Comment(0)
P
7

in the share method on the Inertia Middleware: HandleInertiaRequest.php, I passed the permissions and the roles array to Vue using:

        $permissions = $user->getAllPermissions()->pluck('name');
        $roles = $user->roles()->pluck('name');
        return array_merge(parent::share($request), [
            'auth.user' => fn() => $request->user() ?
                $request->user()->only('id', 'name', 'email', 'roles')
                : null,
            'auth.user.permissions' => $permissions,
            'auth.user.roles' => $roles
        ]);
Phonics answered 20/9, 2021 at 20:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.