access_policy-1.0.x-dev/tests/src/Functional/AccessRulesEntityPermissionsTest.php
tests/src/Functional/AccessRulesEntityPermissionsTest.php
<?php namespace Drupal\Tests\access_policy\Functional; use Drupal\access_policy\Entity\AccessPolicy; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; use Drupal\taxonomy\Entity\Vocabulary; use Drupal\Tests\taxonomy\Traits\TaxonomyTestTrait; /** * Ensures that access rule validation works. * * @group access_policy */ class AccessRulesEntityPermissionsTest extends AccessPolicyTestBase { use TaxonomyTestTrait; /** * The tags vocabulary. * * @var \Drupal\Core\Entity\EntityInterface */ protected $vocabulary; /** * Modules to enable. * * @var array */ protected static $modules = [ 'access_policy', 'access_policy_test', 'filter', 'node', 'taxonomy', 'field', 'user', 'datetime', ]; /** * {@inheritdoc} */ protected $defaultTheme = 'stark'; /** * {@inheritdoc} */ public function setUp(): void { parent::setup(); // Create a tags vocabulary. $this->vocabulary = Vocabulary::create([ 'name' => 'tags', 'vid' => 'tags', ]); $this->vocabulary->save(); // @todo move this to config install. $field_storage = FieldStorageConfig::create([ 'field_name' => 'field_tags', 'entity_type' => 'node', 'type' => 'entity_reference', 'cardinality' => -1, 'settings' => [ 'target_type' => 'taxonomy_term', ], ]); $field_storage->save(); $field = FieldConfig::create([ 'field_storage' => $field_storage, 'field_name' => 'field_tags', 'bundle' => 'page', 'translatable' => FALSE, 'settings' => [ 'handler_settings' => [ 'target_bundles' => ['tags' => 'tags'], ], ], ]); $field->save(); $field_storage = FieldStorageConfig::create([ 'field_name' => 'field_tags', 'entity_type' => 'user', 'type' => 'entity_reference', 'cardinality' => -1, 'settings' => [ 'target_type' => 'taxonomy_term', ], ]); $field_storage->save(); $field = FieldConfig::create([ 'field_storage' => $field_storage, 'field_name' => 'field_tags', 'bundle' => 'user', 'translatable' => FALSE, 'settings' => [ 'handler_settings' => [ 'target_bundles' => ['tags' => 'tags'], ], ], ]); $field->save(); $policy = AccessPolicy::create([ 'id' => 'tags', 'label' => 'Tags policy', 'target_entity_type_id' => 'node', ]); $policy->save(); \Drupal::service('router.builder')->rebuildIfNeeded(); } /** * Tests view permissions restricted by access policy with access rules. */ public function testViewEntityWithAccessRules() { $term_1 = $this->createTerm($this->vocabulary, [ 'title' => 'Term 1', ]); $access_policy = $this->entityTypeManager->getStorage('access_policy')->load('tags'); $handler = $this->accessRuleManager->getHandler('node', 'match_field_tags'); $handler->setSettings([ 'operator' => 'in', 'value' => [ 'field' => 'field_tags', ], ]); $access_policy->addHandler('access_rule', $handler); $access_policy->save(); // Create a node with a value for field_text. This will be validated by // the access rule plugin. $node = $this->drupalCreateNode([ 'type' => 'page', 'status' => 1, 'field_tags' => [ $term_1, ], 'access_policy' => ['tags'], ]); // Attempt to view the content that has matching text with the user. If the // text matches then they should be allowed. $web_user_valid = $this->drupalCreateUser([ 'access content', 'access administration pages', 'access content overview', 'administer nodes', 'view tags content', ]); $web_user_valid->set('field_tags', [$term_1]); $web_user_valid->save(); $this->drupalLogin($web_user_valid); $this->drupalGet('node/' . $node->id()); $this->assertSession()->statusCodeEquals(200); $this->drupalGet('admin/content'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->pageTextContainsOnce($node->label()); $this->drupalLogout(); // Create a user without any value for field_text. They should not be able // to see the node. $web_user_invalid = $this->drupalCreateUser([ 'access content', 'access administration pages', 'access content overview', 'administer nodes', 'view tags content', ]); $this->drupalLogin($web_user_invalid); $this->entityTypeManager->getStorage('node')->resetCache(); $this->drupalGet('node/' . $node->id()); $this->assertSession()->statusCodeEquals(403); $this->drupalGet('admin/content'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->pageTextNotContains($node->label()); } /** * Tests view permissions with multiple access rules using AND operator. */ public function testViewEntityWithMultipleAndAccessRules() { $policy = AccessPolicy::create([ 'id' => 'test_policy_with_and_rules', 'label' => 'Test policy with multiple AND rules', 'access_rule_operator' => 'AND', 'target_entity_type_id' => 'node', ]); $policy->save(); $handler = $this->accessRuleManager->getHandler('node', 'match_field_tags'); $handler->setSettings([ 'operator' => 'in', 'value' => [ 'field' => 'field_tags', ], ]); $policy->addHandler('access_rule', $handler); $policy->addHandler('access_rule', $this->accessRuleManager->getHandler('node', 'is_own')); $policy->save(); $term_1 = $this->createTerm($this->vocabulary, [ 'title' => 'Term 1', ]); // Create a user with the right permissions and matching text. $web_user = $this->drupalCreateUser([ 'access content', 'access administration pages', 'access content overview', 'view test_policy_with_and_rules content', ]); $web_user->set('field_tags', [ $term_1, ]); $web_user->save(); $this->drupalLogin($web_user); // Attempt to view the content that has matching text with the user. If the // text matches AND the content is published then they should be allowed. $node = $this->drupalCreateNode([ 'type' => 'page', 'uid' => $web_user->id(), 'status' => 1, 'field_tags' => [ $term_1, ], 'access_policy' => ['test_policy_with_and_rules'], ]); $this->drupalGet('node/' . $node->id()); $this->assertSession()->statusCodeEquals(200); // Create a node with a different uid and matching value for field_text. // this should fail validation. $diff_author = $this->createUser(); $node_diff_owner = $this->drupalCreateNode([ 'type' => 'page', 'status' => 1, 'uid' => $diff_author->id(), 'field_tags' => [ $term_1, ], 'access_policy' => ['test_policy_with_and_rules'], ]); $this->drupalGet('node/' . $node_diff_owner->id()); $this->assertSession()->statusCodeEquals(403); $this->drupalGet('admin/content'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->pageTextContainsOnce($node->label()); $this->assertSession()->pageTextNotContains($node_diff_owner->label()); } /** * Tests view permissions with multiple access rules using OR operator. */ public function testViewEntityWithMultipleOrAccessRules() { $policy = AccessPolicy::create([ 'id' => 'test_policy_with_or_rules', 'label' => 'Test policy with OR rules', 'access_rule_operator' => 'OR', 'target_entity_type_id' => 'node', ]); $policy->addHandler('access_rule', $this->accessRuleManager->getHandler('node', 'is_own')); $handler = $this->accessRuleManager->getHandler('node', 'match_field_tags'); $handler->setSettings([ 'operator' => 'in', 'value' => [ 'field' => 'field_tags', ], ]); $policy->addHandler('access_rule', $handler); $policy->addHandler('access_rule', $this->accessRuleManager->getHandler('node', 'is_own')); $policy->save(); $term_1 = $this->createTerm($this->vocabulary, [ 'title' => 'Term 1', ]); $term_2 = $this->createTerm($this->vocabulary, [ 'title' => 'Term 1', ]); // Create a user with the right permissions and matching text. $web_user = $this->drupalCreateUser([ 'access content', 'access administration pages', 'access content overview', 'administer nodes', 'view test_policy_with_or_rules content', ]); $web_user->set('field_tags', [ $term_1, ]); $web_user->save(); $this->drupalLogin($web_user); // Attempt to view the content that has matching text with the user. If the // text matches OR the content is published then they should be allowed. $node = $this->drupalCreateNode([ 'type' => 'page', 'uid' => $web_user->id(), 'status' => 1, 'field_tags' => [ $term_1, ], 'access_policy' => ['test_policy_with_or_rules'], ]); $this->drupalGet('node/' . $node->id()); $this->assertSession()->statusCodeEquals(200); // Create a node with a different uid and matching value for field_text. // this should pass validation because one of them is true. $node_diff_owner = $this->drupalCreateNode([ 'type' => 'page', 'status' => 1, 'uid' => 100, 'field_tags' => [ $term_1, ], 'access_policy' => ['test_policy_with_or_rules'], ]); $this->drupalGet('node/' . $node_diff_owner->id()); $this->assertSession()->statusCodeEquals(200); // Create a node with a different uid and different value for field_tags. // This should not pass validation because none of them are true. $node_no_match = $this->drupalCreateNode([ 'type' => 'page', 'status' => 1, 'uid' => 100, 'field_tags' => [ $term_2, ], 'access_policy' => ['test_policy_with_or_rules'], ]); $this->drupalGet('node/' . $node_no_match->id()); $this->assertSession()->statusCodeEquals(403); $this->drupalGet('admin/content'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->pageTextContainsOnce($node->label()); $this->assertSession()->pageTextContainsOnce($node_diff_owner->label()); $this->assertSession()->pageTextNotContains($node_no_match->label()); } /** * Tests bypassed access rules. */ public function testViewEntityWithBypassedAccessRules() { $policy = $this->entityTypeManager->getStorage('access_policy')->load('tags'); $handler = $this->accessRuleManager->getHandler('node', 'match_field_tags'); $handler->setSettings([ 'operator' => 'in', 'value' => [ 'field' => 'field_tags', ], ]); $policy->addHandler('access_rule', $handler); $term_1 = $this->createTerm($this->vocabulary, [ 'title' => 'Term 1', ]); $term_2 = $this->createTerm($this->vocabulary, [ 'title' => 'Term 1', ]); // Create a node with a value for field_text. This will be validated by // the access rule plugin. $node = $this->drupalCreateNode([ 'type' => 'page', 'status' => 1, 'field_tags' => [ $term_1, ], 'access_policy' => ['tags'], ]); // Create a user without any value for field_text but they have the bypass // permission. They should be able to see the node. $web_user_invalid = $this->drupalCreateUser([ 'access content', 'access administration pages', 'access content overview', 'administer nodes', 'view tags content', 'bypass tags access rules', ]); $web_user_invalid->set('field_tags', [ $term_2, ]); $web_user_invalid->save(); $this->drupalLogin($web_user_invalid); $this->drupalGet('node/' . $node->id()); $this->assertSession()->statusCodeEquals(200); $this->drupalGet('admin/content'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->pageTextContainsOnce($node->label()); } }