laravel-permission
laravel-permission copied to clipboard
Incorrect result of $user->hasRole('admin'); within the laravel model
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?
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
I test boot
, everything is working as expected
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.
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
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.
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