You can simply add a permissions pivot table which stores the permission (user ID) to an image.
In your images schema add an additional coulmn called is_public.
Finally, if a user hits route /images you simply has to fetch all public images + all images which the user has permission to (something like Images::ownedBy($userId)->get() or User::with('images')->get())
// User model
use Illuminate\Database\Eloquent\Relations\Relation;
...
public function images()
{
if ($this->isAdmin()) // place proper condition here depending on your implementation
{
return Relation::noConstraints(function () {
return $this->hasMany('Image');
});
}
return $this->hasMany('Image')->orWhere('public', 1);
}
For belongsToMany you can't do that (because it will return only the ones with entry in pivot table due to join), so you can do this in place:
if ($user->isAdmin) { $images = Image::all() }
else
{
$images = Image::whereHas('users', function ($q) use ($user) {
$q->where('users.id', $user->id);
})->orWhere('public', 1)->get();
}