Blagoh
Blagoh

Reputation: 1235

Use relationship with policy of another model

I am using Laravel v5.5.14.

I have an endpoint, for App\Message in routes/api.php:

Route::group(['middleware' => 'auth:api'], function() {

    Route::put('messages/{message}', 'MessageController@update')->middleware('can:view,pet');

});

I want to apply the policy of can:view,pet which is defined in my PetPolicy.php here:

namespace App\Policies;

use App\User;
use App\Pet;
use Illuminate\Auth\Access\HandlesAuthorization;

class PetPolicy
{
    use HandlesAuthorization;

    public function view(User $user, Pet $pet)
    {
        return $user->pets()->where('pet_id', $pet->id)->exists();
    }
}

Every App\Message has a App\Pet I declare that pets have many messages (one-to-many) relationship in my models. And every App\User can have many App\Pet so many-to-many.

app/Pet.php:

namespace App;

use Illuminate\Database\Eloquent\Model;

class Pet extends Model
{
    protected $fillable = ['name'];

    public function messages()
    {
        // one-to-many hasMany belongsTo
        return $this->hasMany('App\Message');
    }

    public function users()
    {
        // many-to-many belongsToMany "
        return $this->belongsToMany('App\User');
    }
}

app/Message.php:

namespace App;

use Illuminate\Database\Eloquent\Model;

class Message extends Model
{
    protected $fillable = ['body', 'kind'];

    public function pet()
    {
        // one-to-many hasMany belongsTo
        return $this->belongsTo('App\Pet');
    }
}

app/User.php:

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Notifiable;

    // ....

    public function pets()
    {
        // many-to-many belongsToMany "
        return $this->belongsToMany('App\Pet');
    }    

    public function messages()
    {
        // one-to-many hasMany belongsTo
        return $this->hasMany('App\Message');
    }
}

However my policy is failing, it is always giving unauthorized. Did I make a mistake somewhere?

This is my app/AuthServiceProvider.php:

namespace App\Providers;

use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class AuthServiceProvider extends ServiceProvider
{
    protected $policies = [
        'App\Pet' => 'App\Policies\PetPolicy',
        'App\Message' => 'App\Policies\MessagePolicy'
    ];

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

Thanks

Upvotes: 3

Views: 3081

Answers (1)

Maraboc
Maraboc

Reputation: 11093

Test it with this query :

namespace App\Policies;

use App\User;
use App\Pet;
use Illuminate\Auth\Access\HandlesAuthorization;

class PetPolicy
{
    use HandlesAuthorization;

    public function view(User $user, Pet $pet)
    {
        return User::where('id', $user->id)
                    ->whereHas('pets', function ($query) use($pet) {
                            $query->where('id', $pet->id);
                        })
                    ->exists();
    }
}

Or just like this if you want :

return $user->pets->contains($pet->id);

Or like this :

return DB::table('pet_user')
    ->whereUserId($user->id)
    ->wherePetId($pet->id)
    ->count() > 0;

Upvotes: 3

Related Questions