laravel-permission icon indicating copy to clipboard operation
laravel-permission copied to clipboard

Incorrect result of $user->hasRole('admin'); within the laravel model

Open abd1407 opened this issue 2 years ago • 5 comments

I have when using Role either in the blade or in the model code. I am using Role inside the model function to return records depending on user role. For a normal user, I will return only those records that were inserted by him, and for an admin, I am returning all records. However, when I use $user->hasRole('admin'); it returns true for all users, even if they do not have admin privileges. Any role name returns true when it is in the roles table. I printed the user id on the web page to ensure that the user did not have any database roles. When this issue happens, blade @hasRole('admin') returns true for the same not admin logged user.

spatie/laravel-permission package version is 5.5.4. PHP version:  7.3 Database version: 5.x

Steps to reproduce the behavior: Use @hasRole('admin') in any model inside the booted() function and it will return true even if the user didn't have this role.

Here is my example code and/or tests showing the problem in my app:

Example Application

protected static function booted()
    {
        if(!empty(Auth::user()))
        {
            parent::boot();
            $user = Auth::user();

            $user_info = User::where('id',$user->id)->with('driverInfo','clientInfo','launderInfo')->first();
   
            // echo $user_info->launderInfo;
            // die();

            if($user->hasRole('admin'))
            {
                return;
            }
            elseif($user->hasRole('launder') && !empty($user_info->launderInfo))
            {
                $launder_id = $user_info->launderInfo->id;
                static::addGlobalScope('launder_id', function (Builder $builder)  use ($launder_id)
                {
                    $builder->where('launder_id', '=', $launder_id);
                });
            }
            elseif($user->hasRole('user')  && !empty($user_info->clientInfo))
            {
                $client_id = $user_info->clientInfo->id;

                static::addGlobalScope('client_id', function (Builder $builder) use ($client_id)
                {
                    $builder->where('client_id', '=', $client_id);
                });
            }
            elseif($user->hasRole('driver') && !empty($user_info->driverInfo))
            {

                $driver_id = $user_info->driverInfo->id;
                static::addGlobalScope('driver_id', function (Builder $builder)  use ($driver_id)
                {
                    $builder->where('driver_id', '=', $driver_id);
                });
            }
            else
            {
                static::addGlobalScope('id', function (Builder $builder)
                {
                    $builder->where('id', '=', 0);
                });
            }

        }// end if user empty
        else
        {
            return true;
        }
    }

Expected behavior:

The role function should return true only when the current user is assigned to this role. and the blade @role is unaffected.

 Additional context By the way, am I using the best way to filter model results depending on user roles?

abd1407 avatar Aug 31 '22 08:08 abd1407

Really hard to read if you don't use markdown correctly ```php

Example:

if($user->hasRole('admin'))
{
    return;
}

Current version is 5.5.5, not 5.5.4, hasRole is tested, probably is a problem with your implementation

For the example application, you must follow the steps on documentation laravel-permission/example-application

PaolaRuby avatar Aug 31 '22 14:08 PaolaRuby

I test boot, everything is working as expected

erikn69 avatar Aug 31 '22 14:08 erikn69

Thank you for replay me. version updated to 5.5.5 but problem still. I found problem happened when I use data from 2 models that have booted function that including call for $user->hasRole() function. problem happened only when i use $user->hasRole() in model, this function return true to any role name exist in database although the current user never assigned to this role and false when this role not exist.

abd1407 avatar Aug 31 '22 19:08 abd1407

I test boot, everything is working as expected

Impossible to replicate

For the example application, you must follow the steps on documentation laravel-permission/example-application

Make a demo app on a fresh laravel instalation

erikn69 avatar Aug 31 '22 19:08 erikn69

I figured out exactly why the problem occurred. Occurs when User Model is used together hasRole function inside another model and both are called at the same time.

Model1

            $user_info = User::where('id',$user->id)->with('driverInfo','clientInfo','launderInfo')->first();

            if($user->hasRole('admin'))
            {
                return;
            }

Model2

             $user_info = User::where('id',$user->id)->with('launderInfo')->first();

            if($user->hasRole('admin'))
            {
                return;
            }

I change Model1 to :

            $driverInfo = Driver::where('user_id',$user->id)->first();
            $clientInfo = Client::where('user_id',$user->id)->first();
            $launderInfo = Launder::where('user_id',$user->id)->first();

Now every thing working fine. But this issue must be resolved from library side.

abd1407 avatar Aug 31 '22 19:08 abd1407

Mam podczas korzystania z roli albo w ostrzu, albo w kodzie modelu. Używam roli wewnątrz funkcji modelu do zwracania rekordów w zależności od roli użytkownika. Dla zwykłego użytkownika zwrócę tylko te rekordy, które zostały przez niego wstawione, a dla administratora zwracam wszystkie rekordy. Jednak gdy używam $user->hasRole('admin'); zwraca true dla wszystkich użytkowników, nawet jeśli nie mają uprawnień administratora. Każda nazwa roli zwraca prawdę, gdy znajduje się w tabeli ról. Wydrukowałem identyfikator użytkownika na stronie internetowej, aby upewnić się, że użytkownik nie ma żadnych ról w bazie danych. W przypadku wystąpienia tego problemu blade @hasRole('admin') zwraca wartość true dla tego samego użytkownika, który nie jest zalogowany jako administrator.

Wersja pakietu spatie/laravel-permission to 5.5.4. Wersja PHP: 7.3 Wersja bazy danych: 5.x

Kroki do odtworzenia zachowania: Użyj @hasRole('admin') w dowolnym modelu wewnątrz funkcji booted(), a zwróci true, nawet jeśli użytkownik nie miał tej roli.

Oto mój przykładowy kod i/lub testy pokazujące problem w mojej aplikacji:

Przykładowa aplikacja

protected static function booted()
    {
        if(!empty(Auth::user()))
        {
            parent::boot();
            $user = Auth::user();

            $user_info = User::where('id',$user->id)->with('driverInfo','clientInfo','launderInfo')->first();
   
            // echo $user_info->launderInfo;
            // die();

            if($user->hasRole('admin'))
            {
                return;
            }
            elseif($user->hasRole('launder') && !empty($user_info->launderInfo))
            {
                $launder_id = $user_info->launderInfo->id;
                static::addGlobalScope('launder_id', function (Builder $builder)  use ($launder_id)
                {
                    $builder->where('launder_id', '=', $launder_id);
                });
            }
            elseif($user->hasRole('user')  && !empty($user_info->clientInfo))
            {
                $client_id = $user_info->clientInfo->id;

                static::addGlobalScope('client_id', function (Builder $builder) use ($client_id)
                {
                    $builder->where('client_id', '=', $client_id);
                });
            }
            elseif($user->hasRole('driver') && !empty($user_info->driverInfo))
            {

                $driver_id = $user_info->driverInfo->id;
                static::addGlobalScope('driver_id', function (Builder $builder)  use ($driver_id)
                {
                    $builder->where('driver_id', '=', $driver_id);
                });
            }
            else
            {
                static::addGlobalScope('id', function (Builder $builder)
                {
                    $builder->where('id', '=', 0);
                });
            }

        }// end if user empty
        else
        {
            return true;
        }
    }

Oczekiwane zachowanie :

Funkcja roli powinna zwracać wartość true tylko wtedy, gdy bieżący użytkownik jest przypisany do tej roli. i ostrze@ROLEnie ma to wpływu.

 Dodatkowy kontekst A propos, czy używam najlepszego sposobu filtrowania wyników modelu w zależności od ról użytkownika?

art/logomark.svg

Sebastianoskiojoj avatar Oct 01 '22 01:10 Sebastianoskiojoj