3 namespace Drupal\Tests\node\Kernel;
5 use Drupal\Component\Render\FormattableMarkup;
6 use Drupal\Core\Session\AccountInterface;
7 use Drupal\KernelTests\KernelTestBase;
8 use Drupal\node\NodeInterface;
9 use Drupal\simpletest\ContentTypeCreationTrait;
10 use Drupal\simpletest\NodeCreationTrait;
11 use Drupal\simpletest\UserCreationTrait;
12 use Drupal\user\RoleInterface;
15 * Tests basic node_access functionality.
19 class NodeAccessTest extends KernelTestBase {
21 use NodeCreationTrait {
22 getNodeByTitle as drupalGetNodeByTitle;
23 createNode as drupalCreateNode;
25 use UserCreationTrait {
26 createUser as drupalCreateUser;
27 createRole as drupalCreateRole;
28 createAdminRole as drupalCreateAdminRole;
30 use ContentTypeCreationTrait {
31 createContentType as drupalCreateContentType;
37 public static $modules = [
50 * @var \Drupal\Core\Entity\EntityAccessControlHandlerInterface
52 protected $accessHandler;
57 protected function setUp() {
59 $this->installSchema('system', 'sequences');
60 $this->installSchema('node', 'node_access');
61 $this->installEntitySchema('user');
62 $this->installEntitySchema('node');
63 $this->installConfig('filter');
64 $this->installConfig('node');
65 $this->accessHandler = $this->container->get('entity_type.manager')
66 ->getAccessControlHandler('node');
67 // Clear permissions for authenticated users.
68 $this->config('user.role.' . RoleInterface::AUTHENTICATED_ID)
69 ->set('permissions', [])
72 // Create user 1 who has special permissions.
73 $this->drupalCreateUser();
75 // Create a node type.
76 $this->drupalCreateContentType([
78 'name' => 'Basic page',
79 'display_submitted' => FALSE,
84 * Runs basic tests for node_access function.
86 public function testNodeAccess() {
87 // Ensures user without 'access content' permission can do nothing.
88 $web_user1 = $this->drupalCreateUser([
89 'create page content',
90 'edit any page content',
91 'delete any page content',
93 $node1 = $this->drupalCreateNode(['type' => 'page']);
94 $this->assertNodeCreateAccess($node1->bundle(), FALSE, $web_user1);
95 $this->assertNodeAccess([
99 ], $node1, $web_user1);
101 // Ensures user with 'bypass node access' permission can do everything.
102 $web_user2 = $this->drupalCreateUser(['bypass node access']);
103 $node2 = $this->drupalCreateNode(['type' => 'page']);
104 $this->assertNodeCreateAccess($node2->bundle(), TRUE, $web_user2);
105 $this->assertNodeAccess([
109 ], $node2, $web_user2);
111 // User cannot 'view own unpublished content'.
112 $web_user3 = $this->drupalCreateUser(['access content']);
113 $node3 = $this->drupalCreateNode([
115 'uid' => $web_user3->id(),
117 $this->assertNodeAccess(['view' => FALSE], $node3, $web_user3);
119 // User cannot create content without permission.
120 $this->assertNodeCreateAccess($node3->bundle(), FALSE, $web_user3);
122 // User can 'view own unpublished content', but another user cannot.
123 $web_user4 = $this->drupalCreateUser([
125 'view own unpublished content',
127 $web_user5 = $this->drupalCreateUser([
129 'view own unpublished content',
131 $node4 = $this->drupalCreateNode([
133 'uid' => $web_user4->id(),
135 $this->assertNodeAccess([
138 ], $node4, $web_user4);
139 $this->assertNodeAccess(['view' => FALSE], $node4, $web_user5);
141 // Tests the default access provided for a published node.
142 $node5 = $this->drupalCreateNode();
143 $this->assertNodeAccess([
147 ], $node5, $web_user3);
149 // Tests the "edit any BUNDLE" and "delete any BUNDLE" permissions.
150 $web_user6 = $this->drupalCreateUser([
152 'edit any page content',
153 'delete any page content',
155 $node6 = $this->drupalCreateNode(['type' => 'page']);
156 $this->assertNodeAccess([
160 ], $node6, $web_user6);
162 // Tests the "edit own BUNDLE" and "delete own BUNDLE" permission.
163 $web_user7 = $this->drupalCreateUser([
165 'edit own page content',
166 'delete own page content',
168 // User should not be able to edit or delete nodes they do not own.
169 $this->assertNodeAccess([
173 ], $node6, $web_user7);
175 // User should be able to edit or delete nodes they own.
176 $node7 = $this->drupalCreateNode([
178 'uid' => $web_user7->id(),
180 $this->assertNodeAccess([
184 ], $node7, $web_user7);
188 * Test operations not supported by node grants.
190 public function testUnsupportedOperation() {
191 $this->enableModules(['node_access_test_empty']);
192 $web_user = $this->drupalCreateUser(['access content']);
193 $node = $this->drupalCreateNode();
194 $this->assertNodeAccess(['random_operation' => FALSE], $node, $web_user);
198 * Asserts that node access correctly grants or denies access.
201 * An associative array of the expected node access grants for the node
202 * and account, with each key as the name of an operation (e.g. 'view',
203 * 'delete') and each value a Boolean indicating whether access to that
204 * operation should be granted.
205 * @param \Drupal\node\NodeInterface $node
206 * The node object to check.
207 * @param \Drupal\Core\Session\AccountInterface $account
208 * The user account for which to check access.
210 public function assertNodeAccess(array $ops, NodeInterface $node, AccountInterface $account) {
211 foreach ($ops as $op => $result) {
212 $this->assertEquals($result, $this->accessHandler->access($node, $op, $account), $this->nodeAccessAssertMessage($op, $result, $node->language()
218 * Asserts that node create access correctly grants or denies access.
220 * @param string $bundle
221 * The node bundle to check access to.
222 * @param bool $result
223 * Whether access should be granted or not.
224 * @param \Drupal\Core\Session\AccountInterface $account
225 * The user account for which to check access.
226 * @param string|null $langcode
227 * (optional) The language code indicating which translation of the node
228 * to check. If NULL, the untranslated (fallback) access is checked.
230 public function assertNodeCreateAccess($bundle, $result, AccountInterface $account, $langcode = NULL) {
231 $this->assertEquals($result, $this->accessHandler->createAccess($bundle, $account, [
232 'langcode' => $langcode,
233 ]), $this->nodeAccessAssertMessage('create', $result, $langcode));
237 * Constructs an assert message to display which node access was tested.
239 * @param string $operation
240 * The operation to check access for.
241 * @param bool $result
242 * Whether access should be granted or not.
243 * @param string|null $langcode
244 * (optional) The language code indicating which translation of the node
245 * to check. If NULL, the untranslated (fallback) access is checked.
248 * An assert message string which contains information in plain English
249 * about the node access permission test that was performed.
251 public function nodeAccessAssertMessage($operation, $result, $langcode = NULL) {
252 return new FormattableMarkup(
253 'Node access returns @result with operation %op, language code %langcode.',
255 '@result' => $result ? 'true' : 'false',
257 '%langcode' => !empty($langcode) ? $langcode : 'empty',