I need to add a global scope to the user model based on data from Auth::user(). For example, users belong to accounts, so users should only see other users that belong to their accounts. I need to scope by Auth::user()->account_id. However, after wasting hours trying to get it to work, I found this - https://github.com/laravel/framework/issues/18218. Basically, it can't be done.
I created a local scope that works great for scoping by Account, but I also need to scope by Departments and Roles and potentially other attributes all at once. Writing local scopes for all of them and chaining them together will get tedious and causes other problems as the app grows. Global scopes are the answer.
So, I created a new model AuthUser model class and used that to handle authentication. My regular User model will hold the global scopes that access Auth::user() which is now based on the AuthUser model. It seemed like a great solution. However, my users also have roles and the roles implementation uses polymorphic relationships that reference the model in a table column ('model_type' => 'App\User').
How can I implement a single user model class that will allow me access Auth::user() in a global scope? Or, implement two classes that won't mess with my polymorphic relationships?
Relevant code:
Won't work
// Scopes\AccountScope.php
class AccountScope implements Scope
{
/**
* Apply the scope to a given Eloquent query builder.
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @param \Illuminate\Database\Eloquent\Model $model
* @return void
*/
public function apply(Builder $builder, Model $model)
{
$builder->where('account_id', Auth::user()->account_id);
}
}
// App\Models\AuthUser
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Spatie\Permission\Traits\HasRoles;
use App\Scopes\AccountScope;
use Auth;
class AuthUser extends Authenticatable
{
use HasRoles;
//...
protected static function boot()
{
parent::boot();
static::addGlobalScope(new AccountScope);
}
}
Works, but messes up polymorphic relationships (specifically on Roles, but I have others in the app).
// App\Models\AuthUser
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Spatie\Permission\Traits\HasRoles;
use App\Scopes\AccountScope;
use Auth;
class AuthUser extends Authenticatable
{
use HasRoles;
//...
}
// App\Models\User
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\Scopes\AccountScope;
use Auth;
class User extends Model
{
use HasRoles;
//...
protected static function boot()
{
parent::boot();
static::addGlobalScope(new AccountScope);
}
//...
}
// SomeController.php
Auth::user()->hasRole('admin') //returns false
$user = User::find(Auth::id())->hasRole('admin') //returns true