Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\Tests\node\Functional;
|
Chris@0
|
4
|
Chris@0
|
5 use Drupal\Tests\Traits\Core\GeneratePermutationsTrait;
|
Chris@0
|
6
|
Chris@0
|
7 /**
|
Chris@0
|
8 * Tests user permissions for node revisions.
|
Chris@0
|
9 *
|
Chris@0
|
10 * @group node
|
Chris@0
|
11 */
|
Chris@0
|
12 class NodeRevisionPermissionsTest extends NodeTestBase {
|
Chris@0
|
13
|
Chris@0
|
14 use GeneratePermutationsTrait;
|
Chris@0
|
15
|
Chris@0
|
16 /**
|
Chris@0
|
17 * The node revisions.
|
Chris@0
|
18 *
|
Chris@0
|
19 * @var array
|
Chris@0
|
20 */
|
Chris@0
|
21 protected $nodeRevisions = [];
|
Chris@0
|
22
|
Chris@0
|
23 /**
|
Chris@0
|
24 * The accounts.
|
Chris@0
|
25 *
|
Chris@0
|
26 * @var array
|
Chris@0
|
27 */
|
Chris@0
|
28 protected $accounts = [];
|
Chris@0
|
29
|
Chris@0
|
30 // Map revision permission names to node revision access ops.
|
Chris@0
|
31 protected $map = [
|
Chris@0
|
32 'view' => 'view all revisions',
|
Chris@0
|
33 'update' => 'revert all revisions',
|
Chris@0
|
34 'delete' => 'delete all revisions',
|
Chris@0
|
35 ];
|
Chris@0
|
36
|
Chris@0
|
37 // Map revision permission names to node type revision access ops.
|
Chris@0
|
38 protected $typeMap = [
|
Chris@0
|
39 'view' => 'view page revisions',
|
Chris@0
|
40 'update' => 'revert page revisions',
|
Chris@0
|
41 'delete' => 'delete page revisions',
|
Chris@0
|
42 ];
|
Chris@0
|
43
|
Chris@0
|
44 protected function setUp() {
|
Chris@0
|
45 parent::setUp();
|
Chris@0
|
46
|
Chris@0
|
47 $types = ['page', 'article'];
|
Chris@0
|
48
|
Chris@0
|
49 foreach ($types as $type) {
|
Chris@0
|
50 // Create a node with several revisions.
|
Chris@0
|
51 $nodes[$type] = $this->drupalCreateNode(['type' => $type]);
|
Chris@0
|
52 $this->nodeRevisions[$type][] = $nodes[$type];
|
Chris@0
|
53
|
Chris@0
|
54 for ($i = 0; $i < 3; $i++) {
|
Chris@0
|
55 // Create a revision for the same nid and settings with a random log.
|
Chris@0
|
56 $revision = clone $nodes[$type];
|
Chris@0
|
57 $revision->setNewRevision();
|
Chris@0
|
58 $revision->revision_log = $this->randomMachineName(32);
|
Chris@0
|
59 $revision->save();
|
Chris@0
|
60 $this->nodeRevisions[$type][] = $revision;
|
Chris@0
|
61 }
|
Chris@0
|
62 }
|
Chris@0
|
63 }
|
Chris@0
|
64
|
Chris@0
|
65 /**
|
Chris@0
|
66 * Tests general revision access permissions.
|
Chris@0
|
67 */
|
Chris@0
|
68 public function testNodeRevisionAccessAnyType() {
|
Chris@0
|
69 // Create three users, one with each revision permission.
|
Chris@0
|
70 foreach ($this->map as $op => $permission) {
|
Chris@0
|
71 // Create the user.
|
Chris@0
|
72 $account = $this->drupalCreateUser(
|
Chris@0
|
73 [
|
Chris@0
|
74 'access content',
|
Chris@0
|
75 'edit any page content',
|
Chris@0
|
76 'delete any page content',
|
Chris@0
|
77 $permission,
|
Chris@0
|
78 ]
|
Chris@0
|
79 );
|
Chris@0
|
80 $account->op = $op;
|
Chris@0
|
81 $this->accounts[] = $account;
|
Chris@0
|
82 }
|
Chris@0
|
83
|
Chris@0
|
84 // Create an admin account (returns TRUE for all revision permissions).
|
Chris@0
|
85 $admin_account = $this->drupalCreateUser(['access content', 'administer nodes']);
|
Chris@0
|
86 $admin_account->is_admin = TRUE;
|
Chris@0
|
87 $this->accounts['admin'] = $admin_account;
|
Chris@0
|
88 $accounts['admin'] = $admin_account;
|
Chris@0
|
89
|
Chris@0
|
90 // Create a normal account (returns FALSE for all revision permissions).
|
Chris@0
|
91 $normal_account = $this->drupalCreateUser();
|
Chris@0
|
92 $normal_account->op = FALSE;
|
Chris@0
|
93 $this->accounts[] = $normal_account;
|
Chris@0
|
94 $accounts[] = $normal_account;
|
Chris@0
|
95 $revision = $this->nodeRevisions['page'][1];
|
Chris@0
|
96
|
Chris@0
|
97 $parameters = [
|
Chris@0
|
98 'op' => array_keys($this->map),
|
Chris@0
|
99 'account' => $this->accounts,
|
Chris@0
|
100 ];
|
Chris@0
|
101
|
Chris@0
|
102 $permutations = $this->generatePermutations($parameters);
|
Chris@0
|
103
|
Chris@0
|
104 $node_revision_access = \Drupal::service('access_check.node.revision');
|
Chris@0
|
105 foreach ($permutations as $case) {
|
Chris@0
|
106 // Skip this test if there are no revisions for the node.
|
Chris@0
|
107 if (!($revision->isDefaultRevision() && (db_query('SELECT COUNT(vid) FROM {node_field_revision} WHERE nid = :nid', [':nid' => $revision->id()])->fetchField() == 1 || $case['op'] == 'update' || $case['op'] == 'delete'))) {
|
Chris@0
|
108 if (!empty($case['account']->is_admin) || $case['account']->hasPermission($this->map[$case['op']])) {
|
Chris@0
|
109 $this->assertTrue($node_revision_access->checkAccess($revision, $case['account'], $case['op']), "{$this->map[$case['op']]} granted.");
|
Chris@0
|
110 }
|
Chris@0
|
111 else {
|
Chris@0
|
112 $this->assertFalse($node_revision_access->checkAccess($revision, $case['account'], $case['op']), "{$this->map[$case['op']]} not granted.");
|
Chris@0
|
113 }
|
Chris@0
|
114 }
|
Chris@0
|
115 }
|
Chris@0
|
116
|
Chris@0
|
117 // Test that access is FALSE for a node administrator with an invalid $node
|
Chris@0
|
118 // or $op parameters.
|
Chris@0
|
119 $admin_account = $accounts['admin'];
|
Chris@0
|
120 $this->assertFalse($node_revision_access->checkAccess($revision, $admin_account, 'invalid-op'), 'NodeRevisionAccessCheck() returns FALSE with an invalid op.');
|
Chris@0
|
121 }
|
Chris@0
|
122
|
Chris@0
|
123 /**
|
Chris@0
|
124 * Tests revision access permissions for a specific content type.
|
Chris@0
|
125 */
|
Chris@0
|
126 public function testNodeRevisionAccessPerType() {
|
Chris@0
|
127 // Create three users, one with each revision permission.
|
Chris@0
|
128 foreach ($this->typeMap as $op => $permission) {
|
Chris@0
|
129 // Create the user.
|
Chris@0
|
130 $account = $this->drupalCreateUser(
|
Chris@0
|
131 [
|
Chris@0
|
132 'access content',
|
Chris@0
|
133 'edit any page content',
|
Chris@0
|
134 'delete any page content',
|
Chris@0
|
135 $permission,
|
Chris@0
|
136 ]
|
Chris@0
|
137 );
|
Chris@0
|
138 $account->op = $op;
|
Chris@0
|
139 $accounts[] = $account;
|
Chris@0
|
140 }
|
Chris@0
|
141
|
Chris@0
|
142 $parameters = [
|
Chris@0
|
143 'op' => array_keys($this->typeMap),
|
Chris@0
|
144 'account' => $accounts,
|
Chris@0
|
145 ];
|
Chris@0
|
146
|
Chris@0
|
147 // Test that the accounts have access to the corresponding page revision
|
Chris@0
|
148 // permissions.
|
Chris@0
|
149 $revision = $this->nodeRevisions['page'][1];
|
Chris@0
|
150
|
Chris@0
|
151 $permutations = $this->generatePermutations($parameters);
|
Chris@0
|
152 $node_revision_access = \Drupal::service('access_check.node.revision');
|
Chris@0
|
153 foreach ($permutations as $case) {
|
Chris@0
|
154 // Skip this test if there are no revisions for the node.
|
Chris@0
|
155 if (!($revision->isDefaultRevision() && (db_query('SELECT COUNT(vid) FROM {node_field_revision} WHERE nid = :nid', [':nid' => $revision->id()])->fetchField() == 1 || $case['op'] == 'update' || $case['op'] == 'delete'))) {
|
Chris@17
|
156 if (!empty($case['account']->is_admin) || $case['account']->hasPermission($this->typeMap[$case['op']])) {
|
Chris@0
|
157 $this->assertTrue($node_revision_access->checkAccess($revision, $case['account'], $case['op']), "{$this->typeMap[$case['op']]} granted.");
|
Chris@0
|
158 }
|
Chris@0
|
159 else {
|
Chris@0
|
160 $this->assertFalse($node_revision_access->checkAccess($revision, $case['account'], $case['op']), "{$this->typeMap[$case['op']]} not granted.");
|
Chris@0
|
161 }
|
Chris@0
|
162 }
|
Chris@0
|
163 }
|
Chris@0
|
164
|
Chris@0
|
165 // Test that the accounts have no access to the article revisions.
|
Chris@0
|
166 $revision = $this->nodeRevisions['article'][1];
|
Chris@0
|
167
|
Chris@0
|
168 foreach ($permutations as $case) {
|
Chris@0
|
169 $this->assertFalse($node_revision_access->checkAccess($revision, $case['account'], $case['op']), "{$this->typeMap[$case['op']]} did not grant revision permission for articles.");
|
Chris@0
|
170 }
|
Chris@0
|
171 }
|
Chris@0
|
172
|
Chris@0
|
173 }
|