Are this package support user specific permission #2285
-
$user->can('...') If we execute "can directives" ( policy ) , i have checked in query log and show this two query every time but not in subsequece call. This two query basically find the user permission and role. How we can cache this behaviour select `permissions`.*, `model_has_permissions`.`model_id` as `pivot_model_id`, `model_has_permissions`.`permission_id` as `pivot_permission_id`, `model_has_permissions`.`model_type` as `pivot_model_type` from `permissions` inner join `model_has_permissions` on `permissions`.`id` = `model_has_permissions`.`permission_id` where `model_has_permissions`.`model_id` = ? and `model_has_permissions`.`model_type` = ? {"bindings":[13,"App\\User"],"time":8.67}
select `roles`.*, `model_has_roles`.`model_id` as `pivot_model_id`, `model_has_roles`.`role_id` as `pivot_role_id`, `model_has_roles`.`model_type` as `pivot_model_type` from `roles` inner join `model_has_roles` on `roles`.`id` = `model_has_roles`.`role_id` where `model_has_roles`.`model_id` = ? and `model_has_roles`.`model_type` = ? {"bindings":[13,"App\\User"],"time":8.31}
//some example code
class Policy {
public function view(User $user)
{
//
if ($user->can('list-accs')) { //this
return true;
} else {
return false;
}
}
} There is some reference but it does not re-cache again when we change permission ...etc Reference Is there any idea of caching user specific permission and good fit in policy ? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 5 replies
-
That is an expected behavior Maybe this PR helps you |
Beta Was this translation helpful? Give feedback.
-
I have integrate with #1833 (comment) . it still hits one of the query select `roles`.*, `model_has_roles`.`model_id` as `pivot_model_id`, `model_has_roles`.`role_id` as `pivot_role_id`, `model_has_roles`.`model_type` as `pivot_model_type` from `roles` inner join `model_has_roles` on `roles`.`id` = `model_has_roles`.`role_id` where `model_has_roles`.`model_id` in (10) and `model_has_roles`.`model_type` = ? {"bindings":["App\\User"],"time":8.98} There is how i intergrate your code //user.php
use App\Traits\HasPermissionsCache;
class User extends Authenticatable
{
use HasPermissionsCache;
//
public function load($relation)
{
$method = 'forgetModelCached' . ucfirst($relation);
if (in_array($relation, ['roles', 'permissions']) && method_exists($this, $method)) {
$this->$method();
return $this->loadCachedRelation($relation);
}
return parent::load($relation);
}
} <?php
namespace App\Traits;
use Illuminate\Database\Eloquent\Collection;
use Log;
use Spatie\Permission\PermissionRegistrar;
trait HasPermissionsCache
{
protected function getPermissionCacheKey(string $relation): string
{
return sprintf(PermissionRegistrar::$cacheKey . '.' . str_replace('\\', '.', $this->getMorphClass()) . '.%d.%d.' . $relation, $this->getKey(), $this->session['empr_id'] ?? session('empr_id'));
}
private function getCachedPermissions(string $relation)
{
Log::debug("relation : " . $relation);
if ($this->relationLoaded($relation)) {
return $this->getRelationValue($relation);
}
$cache = app(PermissionRegistrar::class)->getCacheRepository();
$cacheIsTaggable = $cache->getStore() instanceof \Illuminate\Cache\TaggableStore;
$class = $relation === 'roles' ? $this->getRoleClass() : $this->getPermissionClass();
$collection = $class::hydrate(
collect(($cacheIsTaggable ? $cache->tags(['permissions']) : $cache)->remember($this->getPermissionCacheKey($relation), config('session.lifetime', 120) * 60, function () use ($relation) {
return $this->getRelationValue($relation)->map(function ($data) {
return ['i' => $data->id, 'n' => $data->name, 'g' => $data->guard_name];
})->all();
}))
->map(function ($item) {
return ['id' => $item['i'], 'name' => $item['n'], 'guard_name' => $item['g']];
})->all()
);
Log::debug("Permission key : " . $this->getPermissionCacheKey($relation));
$this->setRelation($relation, $collection);
return $collection;
}
public function getRolesAttribute(): Collection
{
return $this->getCachedPermissions('roles');
}
public function getPermissionsAttribute(): Collection
{
return $this->getCachedPermissions('permissions');
}
public function forgetModelAssignedPermissions()
{
$cache = app(PermissionRegistrar::class)->getCacheRepository();
$cache->forget($this->getPermissionCacheKey('roles'));
$cache->forget($this->getPermissionCacheKey('permissions'));
}
public static function forgetAllModelsAssignedPermissions()
{
$cache = app(PermissionRegistrar::class)->getCacheRepository();
$cacheIsTaggable = $cache->getStore() instanceof \Illuminate\Cache\TaggableStore;
if ($cacheIsTaggable) {
$cache->tags(['permissions'])->flush();
} else {
static::select((new static)->getKeyName())->get()->each(function ($model) use ($cache) {
$cache->forget($model->getPermissionCacheKey('roles'));
$cache->forget($model->getPermissionCacheKey('permissions'));
});
}
}
} This is the screenshot comes from redis Is that i missing something ? Thanks @erikn69 for your help |
Beta Was this translation helpful? Give feedback.
That is an expected behavior
Maybe this PR helps you
#1392 (comment)
#1833 (comment)
#1760 (comment)