Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
100.00% |
1 / 1 |
|
100.00% |
4 / 4 |
CRAP | |
100.00% |
25 / 25 |
PermissionsHashGenerator | |
100.00% |
1 / 1 |
|
100.00% |
4 / 4 |
8 | |
100.00% |
25 / 25 |
__construct | |
100.00% |
1 / 1 |
1 | |
100.00% |
4 / 4 |
|||
generate | |
100.00% |
1 / 1 |
4 | |
100.00% |
15 / 15 |
|||
doGenerate | |
100.00% |
1 / 1 |
2 | |
100.00% |
5 / 5 |
|||
hash | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
<?php | |
/** | |
* @file | |
* Contains \Drupal\Core\Session\PermissionsHashGenerator. | |
*/ | |
namespace Drupal\Core\Session; | |
use Drupal\Core\PrivateKey; | |
use Drupal\Core\Cache\Cache; | |
use Drupal\Core\Cache\CacheBackendInterface; | |
use Drupal\Core\Site\Settings; | |
/** | |
* Generates and caches the permissions hash for a user. | |
*/ | |
class PermissionsHashGenerator implements PermissionsHashGeneratorInterface { | |
/** | |
* The private key service. | |
* | |
* @var \Drupal\Core\PrivateKey | |
*/ | |
protected $privateKey; | |
/** | |
* The cache backend interface to use for the persistent cache. | |
* | |
* @var \Drupal\Core\Cache\CacheBackendInterface | |
*/ | |
protected $cache; | |
/** | |
* The cache backend interface to use for the static cache. | |
* | |
* @var \Drupal\Core\Cache\CacheBackendInterface | |
*/ | |
protected $static; | |
/** | |
* Constructs a PermissionsHashGenerator object. | |
* | |
* @param \Drupal\Core\PrivateKey $private_key | |
* The private key service. | |
* @param \Drupal\Core\Cache\CacheBackendInterface $cache | |
* The cache backend interface to use for the persistent cache. | |
* @param \Drupal\Core\Cache\CacheBackendInterface | |
* The cache backend interface to use for the static cache. | |
*/ | |
public function __construct(PrivateKey $private_key, CacheBackendInterface $cache, CacheBackendInterface $static) { | |
$this->privateKey = $private_key; | |
$this->cache = $cache; | |
$this->static = $static; | |
} | |
/** | |
* {@inheritdoc} | |
* | |
* Cached by role, invalidated whenever permissions change. | |
*/ | |
public function generate(AccountInterface $account) { | |
// User 1 is the super user, and can always access all permissions. Use a | |
// different, unique identifier for the hash. | |
if ($account->id() == 1) { | |
return $this->hash('is-super-user'); | |
} | |
$sorted_roles = $account->getRoles(); | |
sort($sorted_roles); | |
$role_list = implode(',', $sorted_roles); | |
$cid = "user_permissions_hash:$role_list"; | |
if ($static_cache = $this->static->get($cid)) { | |
return $static_cache->data; | |
} | |
else { | |
$tags = Cache::buildTags('config:user.role', $sorted_roles, '.'); | |
if ($cache = $this->cache->get($cid)) { | |
$permissions_hash = $cache->data; | |
} | |
else { | |
$permissions_hash = $this->doGenerate($sorted_roles); | |
$this->cache->set($cid, $permissions_hash, Cache::PERMANENT, $tags); | |
} | |
$this->static->set($cid, $permissions_hash, Cache::PERMANENT, $tags); | |
} | |
return $permissions_hash; | |
} | |
/** | |
* Generates a hash that uniquely identifies the user's permissions. | |
* | |
* @param string[] $roles | |
* The user's roles. | |
* | |
* @return string | |
* The permissions hash. | |
*/ | |
protected function doGenerate(array $roles) { | |
// @todo Once Drupal gets rid of user_role_permissions(), we should be able | |
// to inject the user role controller and call a method on that instead. | |
$permissions_by_role = user_role_permissions($roles); | |
foreach ($permissions_by_role as $role => $permissions) { | |
sort($permissions); | |
// Note that for admin roles (\Drupal\user\RoleInterface::isAdmin()), the | |
// permissions returned will be empty ($permissions = []). Therefore the | |
// presence of the role ID as a key in $permissions_by_role is essential | |
// to ensure that the hash correctly recognizes admin roles. (If the hash | |
// was based solely on the union of $permissions, the admin roles would | |
// effectively be no-ops, allowing for hash collisions.) | |
$permissions_by_role[$role] = $permissions; | |
} | |
return $this->hash(serialize($permissions_by_role)); | |
} | |
/** | |
* Hashes the given string. | |
* | |
* @param string $identifier | |
* The string to be hashed. | |
* | |
* @return string | |
* The hash. | |
*/ | |
protected function hash($identifier) { | |
return hash('sha256', $this->privateKey->get() . Settings::getHashSalt() . $identifier); | |
} | |
} |