3 namespace Drupal\Tests\Core\Session;
5 use Drupal\Component\Utility\Crypt;
6 use Drupal\Core\Session\PermissionsHashGenerator;
7 use Drupal\Core\Site\Settings;
8 use Drupal\Tests\UnitTestCase;
11 * @coversDefaultClass \Drupal\Core\Session\PermissionsHashGenerator
14 class PermissionsHashGeneratorTest extends UnitTestCase {
17 * The mocked super user account.
19 * @var \Drupal\user\UserInterface|\PHPUnit_Framework_MockObject_MockObject
26 * @var \Drupal\user\UserInterface|\PHPUnit_Framework_MockObject_MockObject
31 * An "updated" mocked account.
33 * @var \Drupal\user\UserInterface|\PHPUnit_Framework_MockObject_MockObject
35 protected $account2Updated;
38 * A different account.
40 * @var \Drupal\user\UserInterface|\PHPUnit_Framework_MockObject_MockObject
45 * The mocked private key service.
47 * @var \Drupal\Core\PrivateKey|\PHPUnit_Framework_MockObject_MockObject
49 protected $privateKey;
52 * The mocked cache backend.
54 * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
59 * The mocked cache backend.
61 * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
63 protected $staticCache;
66 * The permission hash class being tested.
68 * @var \Drupal\Core\Session\PermissionsHashGeneratorInterface
70 protected $permissionsHash;
75 protected function setUp() {
78 new Settings(['hash_salt' => 'test']);
80 // The mocked super user account, with the same roles as Account 2.
81 $this->account1 = $this->getMockBuilder('Drupal\user\Entity\User')
82 ->disableOriginalConstructor()
83 ->setMethods(['getRoles', 'id'])
85 $this->account1->expects($this->any())
88 $this->account1->expects($this->never())
91 // Account 2: 'administrator' and 'authenticated' roles.
92 $roles_1 = ['administrator', 'authenticated'];
93 $this->account2 = $this->getMockBuilder('Drupal\user\Entity\User')
94 ->disableOriginalConstructor()
95 ->setMethods(['getRoles', 'id'])
97 $this->account2->expects($this->any())
99 ->will($this->returnValue($roles_1));
100 $this->account2->expects($this->any())
104 // Account 3: 'authenticated' and 'administrator' roles (different order).
105 $roles_3 = ['authenticated', 'administrator'];
106 $this->account3 = $this->getMockBuilder('Drupal\user\Entity\User')
107 ->disableOriginalConstructor()
108 ->setMethods(['getRoles', 'id'])
110 $this->account3->expects($this->any())
112 ->will($this->returnValue($roles_3));
113 $this->account3->expects($this->any())
117 // Updated account 2: now also 'editor' role.
118 $roles_2_updated = ['editor', 'administrator', 'authenticated'];
119 $this->account2Updated = $this->getMockBuilder('Drupal\user\Entity\User')
120 ->disableOriginalConstructor()
121 ->setMethods(['getRoles', 'id'])
123 $this->account2Updated->expects($this->any())
125 ->will($this->returnValue($roles_2_updated));
126 $this->account2Updated->expects($this->any())
130 // Mocked private key + cache services.
131 $random = Crypt::randomBytesBase64(55);
132 $this->privateKey = $this->getMockBuilder('Drupal\Core\PrivateKey')
133 ->disableOriginalConstructor()
134 ->setMethods(['get'])
136 $this->privateKey->expects($this->any())
138 ->will($this->returnValue($random));
139 $this->cache = $this->getMockBuilder('Drupal\Core\Cache\CacheBackendInterface')
140 ->disableOriginalConstructor()
142 $this->staticCache = $this->getMockBuilder('Drupal\Core\Cache\CacheBackendInterface')
143 ->disableOriginalConstructor()
146 $this->permissionsHash = new PermissionsHashGenerator($this->privateKey, $this->cache, $this->staticCache);
152 public function testGenerate() {
153 // Ensure that the super user (user 1) always gets the same hash.
154 $super_user_hash = $this->permissionsHash->generate($this->account1);
156 // Ensure that two user accounts with the same roles generate the same hash.
157 $hash_2 = $this->permissionsHash->generate($this->account2);
158 $hash_3 = $this->permissionsHash->generate($this->account3);
159 $this->assertSame($hash_2, $hash_3, 'Different users with the same roles generate the same permissions hash.');
161 $this->assertNotSame($hash_2, $super_user_hash, 'User 1 has a different hash despite having the same roles');
163 // Compare with hash for user account 1 with an additional role.
164 $updated_hash_2 = $this->permissionsHash->generate($this->account2Updated);
165 $this->assertNotSame($hash_2, $updated_hash_2, 'Same user with updated roles generates different permissions hash.');
171 public function testGeneratePersistentCache() {
172 // Set expectations for the mocked cache backend.
173 $expected_cid = 'user_permissions_hash:administrator,authenticated';
175 $mock_cache = new \stdClass();
176 $mock_cache->data = 'test_hash_here';
178 $this->staticCache->expects($this->once())
180 ->with($expected_cid)
181 ->will($this->returnValue(FALSE));
182 $this->staticCache->expects($this->once())
184 ->with($expected_cid, $this->isType('string'));
186 $this->cache->expects($this->once())
188 ->with($expected_cid)
189 ->will($this->returnValue($mock_cache));
190 $this->cache->expects($this->never())
193 $this->permissionsHash->generate($this->account2);
199 public function testGenerateStaticCache() {
200 // Set expectations for the mocked cache backend.
201 $expected_cid = 'user_permissions_hash:administrator,authenticated';
203 $mock_cache = new \stdClass();
204 $mock_cache->data = 'test_hash_here';
206 $this->staticCache->expects($this->once())
208 ->with($expected_cid)
209 ->will($this->returnValue($mock_cache));
210 $this->staticCache->expects($this->never())
213 $this->cache->expects($this->never())
215 $this->cache->expects($this->never())
218 $this->permissionsHash->generate($this->account2);
222 * Tests the generate method with no cache returned.
224 public function testGenerateNoCache() {
225 // Set expectations for the mocked cache backend.
226 $expected_cid = 'user_permissions_hash:administrator,authenticated';
228 $this->staticCache->expects($this->once())
230 ->with($expected_cid)
231 ->will($this->returnValue(FALSE));
232 $this->staticCache->expects($this->once())
234 ->with($expected_cid, $this->isType('string'));
236 $this->cache->expects($this->once())
238 ->with($expected_cid)
239 ->will($this->returnValue(FALSE));
240 $this->cache->expects($this->once())
242 ->with($expected_cid, $this->isType('string'));
244 $this->permissionsHash->generate($this->account2);
249 namespace Drupal\Core\Session;
251 // @todo remove once user_role_permissions() can be injected.
252 if (!function_exists('user_role_permissions')) {
253 function user_role_permissions(array $roles) {
254 $role_permissions = [];
255 foreach ($roles as $rid) {
256 $role_permissions[$rid] = [];
258 return $role_permissions;