phplaravelinertiajslaravel-fortify

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


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>

Solution

  • 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>