6

I've created an anonimus global scope in the users model as below in order to get only public users in the frontend:

protected static function boot()
{
    parent::boot();

    static::addGlobalScope('is_public', function(Builder $builder) {
        $builder->where('is_public', '=', 1);
    });
}

But... when i need to perform the login in the backend i need of course to check for not-public users so i need to exclude the global scope.

Is this possibile using the default AuthController of laravel?

Many Thanks!!

manuelprojects
  • 213
  • 3
  • 10

4 Answers4

7

You just need to create two Models - one without global scope (i.e. AuthUser) and another with the global scope that extends the first one (i.e. User).

Then you can use AuthUser for authentication And User everywhere else.

Anže Časar
  • 404
  • 2
  • 3
  • 1
    This is a good way to handle this problem, furthermore, it creates a separation between the authentication functionality with the users funcionalities – Ricardo Vigatti Feb 19 '16 at 14:22
0

You can remove any global scope on the fly with the following method:

User::withoutGlobalScope('is_public')->get();

Ben V.
  • 211
  • 1
  • 3
0

I resolved it by creating the new package.

mpyw/scoped-auth: Apply specific scope for user authentication.

Run composer require mpyw/scoped-auth and modify your User model like this:

<?php

namespace App;

use Illuminate\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Authenticatable as UserContract;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Mpyw\ScopedAuth\AuthScopable;

class User extends Model implements UserContract, AuthScopable
{
    use Authenticatable;

    public function scopeForAuthentication(Builder $query): Builder
    {
        return $query->where('is_public', '=', 1);
    }
}

Thats' all.

mpyw
  • 5,526
  • 4
  • 30
  • 36
0

Either creating two separate models, I would prefer to put condition on the global scope because if you want to access the relationship methods from both models then you need to include those methods in both models or you have to extend one model to another. I think that is not a good solution.

create new file for the global scope:

<?php

namespace App\Scopes;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Support\Facades\Auth;

class IsPublicScope implements Scope
{
    public function apply(Builder $builder, Model $model)
    {
        if (Auth::hasUser()) {
            $builder->where('is_public', '=', 1);
        }
    }
    }
?>

and add this method to your user model:

protected static function boot()
{
    parent::boot();
    static::addGlobalScope(new IsPublicScope());
}

Thanks @mpyw for the correction.

  • Don't call `Auth::check()` without checking by `Auth::hasUser()`. Refer to this: https://stackoverflow.com/questions/41824174/can-not-call-auth-class-inside-scope-class-in-laravel-5-2/59298361#59298361 – mpyw Dec 12 '19 at 05:47
  • Auth::user or Auth::hasUser will always return false here because session is not initialize yet when boot is called – Abhi Burk Jul 20 '20 at 06:05