diff --git a/core/core.services.yml b/core/core.services.yml index 193ffbb7dac..3cff960a50c 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -1599,7 +1599,7 @@ services: Drupal\Core\Session\AccountSwitcherInterface: '@account_switcher' user_permissions_hash_generator: class: Drupal\Core\Session\PermissionsHashGenerator - arguments: ['@private_key', '@cache.bootstrap', '@cache.static'] + arguments: ['@private_key', '@cache.bootstrap', '@cache.static', '@entity_type.manager'] Drupal\Core\Session\PermissionsHashGeneratorInterface: '@user_permissions_hash_generator' current_user: class: Drupal\Core\Session\AccountProxy diff --git a/core/lib/Drupal/Core/Session/PermissionsHashGenerator.php b/core/lib/Drupal/Core/Session/PermissionsHashGenerator.php index e17253782fb..db837b7691f 100644 --- a/core/lib/Drupal/Core/Session/PermissionsHashGenerator.php +++ b/core/lib/Drupal/Core/Session/PermissionsHashGenerator.php @@ -2,6 +2,7 @@ namespace Drupal\Core\Session; +use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\PrivateKey; use Drupal\Core\Cache\Cache; use Drupal\Core\Cache\CacheBackendInterface; @@ -42,11 +43,17 @@ class PermissionsHashGenerator implements PermissionsHashGeneratorInterface { * The cache backend interface to use for the persistent cache. * @param \Drupal\Core\Cache\CacheBackendInterface $static * The cache backend interface to use for the static cache. + * @param \Drupal\Core\Entity\EntityTypeManagerInterface|null $entityTypeManager + * The entity type manager. */ - public function __construct(PrivateKey $private_key, CacheBackendInterface $cache, CacheBackendInterface $static) { + public function __construct(PrivateKey $private_key, CacheBackendInterface $cache, CacheBackendInterface $static, protected ?EntityTypeManagerInterface $entityTypeManager = NULL) { $this->privateKey = $private_key; $this->cache = $cache; $this->static = $static; + if ($this->entityTypeManager === NULL) { + @trigger_error('Calling ' . __METHOD__ . '() without the $entityTypeManager argument is deprecated in drupal:10.1.0 and will be required in drupal:11.0.0. See https://www.drupal.org/node/3348138', E_USER_DEPRECATED); + $this->entityTypeManager = \Drupal::entityTypeManager(); + } } /** @@ -93,18 +100,17 @@ class PermissionsHashGenerator implements PermissionsHashGeneratorInterface { * 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); + $permissions_by_role = []; + /** @var \Drupal\user\RoleInterface[] $entities */ + $entities = $this->entityTypeManager->getStorage('user_role')->loadMultiple($roles); + foreach ($roles as $role) { // 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; + $permissions_by_role[$role] = isset($entities[$role]) ? $entities[$role]->getPermissions() : []; } return $this->hash(serialize($permissions_by_role)); } diff --git a/core/modules/user/tests/src/Kernel/LegacyUserTest.php b/core/modules/user/tests/src/Kernel/LegacyUserTest.php new file mode 100644 index 00000000000..b0f5b55d764 --- /dev/null +++ b/core/modules/user/tests/src/Kernel/LegacyUserTest.php @@ -0,0 +1,56 @@ +expectDeprecation('user_role_permissions() is deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. There is no replacement beyond loading the roles and calling \Drupal\user\Entity\Role::getPermissions(). See https://www.drupal.org/node/3348138'); + + $expected = [ + RoleInterface::ANONYMOUS_ID => [], + RoleInterface::AUTHENTICATED_ID => [], + ]; + $permissions = user_role_permissions(array_keys($expected)); + $this->assertSame($expected, $permissions); + + $permission = 'administer permissions'; + $role = Role::create([ + 'id' => 'admin', + 'label' => 'Test', + 'is_admin' => TRUE, + 'permissions' => [$permission], + ]); + $role->save(); + $permissions = user_role_permissions([$role->id()]); + $this->assertSame([$role->id() => []], $permissions); + $role + ->setIsAdmin(FALSE) + ->grantPermission($permission) + ->save(); + $permissions = user_role_permissions([$role->id()]); + $this->assertSame([$role->id() => [$permission]], $permissions); + } + +} diff --git a/core/modules/user/user.module b/core/modules/user/user.module index 791e8bbe464..87370338ca0 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -227,8 +227,15 @@ function user_validate_name($name) { * @return array * An array indexed by role ID. Each value is an array of permission strings * for the given role. + * + * @deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. There is no + * replacement beyond loading the roles and calling + * \Drupal\user\Entity\Role::getPermissions(). + * + * @see https://www.drupal.org/node/3348138 */ function user_role_permissions(array $roles) { + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. There is no replacement beyond loading the roles and calling \Drupal\user\Entity\Role::getPermissions(). See https://www.drupal.org/node/3348138', E_USER_DEPRECATED); if (defined('MAINTENANCE_MODE') && MAINTENANCE_MODE == 'update') { return _user_role_permissions_update($roles); } @@ -253,8 +260,14 @@ function user_role_permissions(array $roles) { * @return array * An array indexed by role ID. Each value is an array of permission strings * for the given role. + * + * @deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. There is no + * replacement. + * + * @see https://www.drupal.org/node/3348138 */ function _user_role_permissions_update($roles) { + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. There is no replacement. See https://www.drupal.org/node/3348138', E_USER_DEPRECATED); $role_permissions = []; foreach ($roles as $rid) { $role_permissions[$rid] = \Drupal::config("user.role.$rid")->get('permissions') ?: []; diff --git a/core/tests/Drupal/Tests/Core/Session/PermissionsHashGeneratorTest.php b/core/tests/Drupal/Tests/Core/Session/PermissionsHashGeneratorTest.php index 1736593194a..182128863e4 100644 --- a/core/tests/Drupal/Tests/Core/Session/PermissionsHashGeneratorTest.php +++ b/core/tests/Drupal/Tests/Core/Session/PermissionsHashGeneratorTest.php @@ -3,9 +3,11 @@ namespace Drupal\Tests\Core\Session; use Drupal\Component\Utility\Crypt; +use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Session\PermissionsHashGenerator; use Drupal\Core\Site\Settings; use Drupal\Tests\UnitTestCase; +use Drupal\user\RoleStorageInterface; /** * @coversDefaultClass \Drupal\Core\Session\PermissionsHashGenerator @@ -142,8 +144,20 @@ class PermissionsHashGeneratorTest extends UnitTestCase { $this->staticCache = $this->getMockBuilder('Drupal\Core\Cache\CacheBackendInterface') ->disableOriginalConstructor() ->getMock(); + $entityTypeManager = $this->getMockBuilder(EntityTypeManagerInterface::class) + ->disableOriginalConstructor() + ->getMock(); - $this->permissionsHash = new PermissionsHashGenerator($this->privateKey, $this->cache, $this->staticCache); + $roleStorage = $this->getMockBuilder(RoleStorageInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $entityTypeManager->expects($this->any()) + ->method('getStorage') + ->with('user_role') + ->willReturn($roleStorage); + + $this->permissionsHash = new PermissionsHashGenerator($this->privateKey, $this->cache, $this->staticCache, $entityTypeManager); } /** @@ -245,18 +259,3 @@ class PermissionsHashGeneratorTest extends UnitTestCase { } } - -namespace Drupal\Core\Session; - -// @todo remove once user_role_permissions() can be injected. -if (!function_exists('user_role_permissions')) { - - function user_role_permissions(array $roles) { - $role_permissions = []; - foreach ($roles as $rid) { - $role_permissions[$rid] = []; - } - return $role_permissions; - } - -}