How can I get my custom gate working in Laravel?

1.7k views Asked by At

I am trying to create a custom gate that allows users of the "Administrator" team to access the Users index page. However, it functions exactly the opposite of what I want to achieve and I do not seem to understand where am I wrong here.

It always returns "false" regardless of the user belongs to an Admin team or not.

Help is appreciated. Thank you.

User.php :

public function AdminTeam(string $team)
{
   return null !== $this->teams()->where('name', $team)->first();
}

AuthServiceProvider.php :

/**
 * Register any authentication / authorization services.
 *
 * @return void
 */
public function boot()
{
    $this->registerPolicies();

    Gate::define('is-admin', function ($user){
       return $user->AdminTeam('Administrator');
    });
}

UserController.php :

 /**
 * Display a listing of the resource.
 *
 * @return \Illuminate\Http\Response
 */
public function index()
{
    if (Gate::allows('is-admin')) {
        return view('admin.users.index', ['users' => User::paginate(10)]);
    }
    dd('you need to be admin!');
    
}

index.blade.php :

@can('is-admin')
                @foreach($users as $user)
                    <tr>
                        <th scope="row">{{ $user->user_id }}</th>
                        <td>{{ $user->name }}</td>
                        <td>{{ $user->email }}</td>
                        <td>{{ $user->created_at }}</td>
                        <td>{{ $user->updated_at }}</td>
                        <td>
                            <a class="btn btn-sm btn-primary" href="{{ route('admin.users.edit', $user->user_id) }}"
                               role="button">Bearbeiten</a>
                            <button type="button" class="btn btn-sm btn-danger"
                                    onclick="event.preventDefault();
                                        document.getElementById('delete-user-form-{{ $user->user_id }}').submit()">
                                Löschen
                            </button>
                            <form id="delete-user-form-{{ $user->user_id }}"
                                  action="{{ route('admin.users.destroy', $user->user_id) }}" method="POST"
                                  style="display: none">
                                @csrf
                                @method("DELETE")
                            </form>
                        </td>
                    </tr>
                @endforeach
            @endcan

Output :

Image

1

There are 1 answers

0
Raj On BEST ANSWER

So after a couple of days of debugging, I realized that my teams() method should be team() inside the User model as the user has only one team and BelongsTo relation will only return one record.

Credits: https://www.reddit.com/r/laravel/comments/ldvtgd/custom_admin_gate_not_working/ https://laracasts.com/discuss/channels/laravel/admin-gate-not-working?page=1#reply=687840

Here are the changes :

User.php

public function team()
    {
        return $this->belongsTo(Team::class);
    }

     /**
     * Check if the user belongs to Admin Team
     * @param string $team
     * @return bool
     */

    public function isAdmin(string $team)
    {

        return $this->team()->where('name', $team)->exists();

    }

AuthServiceProvider.php

public function boot()
    {
        $this->registerPolicies();

        Gate::define('is-admin', function (User $user){
           return $user->isAdmin('Admin');
        });
    }

UserController.php

public function index()
    {
        if (Gate::allows('is-admin')) {
            return view('admin.users.index', ['users' => User::paginate(10)]);

        }

        dd('you need to be admin!');
        
    }