access_policy-1.0.x-dev/tests/src/Functional/AccessPolicyEntityListingTest.php

tests/src/Functional/AccessPolicyEntityListingTest.php
<?php

namespace Drupal\Tests\access_policy\Functional;

use Drupal\access_policy\Entity\AccessPolicy;
use Drupal\user\Entity\Role;

/**
 * Ensures that listings only display entities that a user is allowed to view.
 *
 * @group access_policy
 */
class AccessPolicyEntityListingTest extends AccessPolicyTestBase {

  /**
   * Modules to enable.
   *
   * @var array
   */
  protected static $modules = [
    'access_policy',
    'access_policy_test',
    'filter',
    'node',
    'field',
    'user',
    'datetime',
    'views',
  ];

  /**
   * {@inheritdoc}
   */
  protected $defaultTheme = 'stark';

  /**
   * {@inheritdoc}
   */
  public function setUp(): void {
    parent::setUp();

    // This is necessary to register the access rules.
    AccessPolicy::create([
      'id' => 'test_policy',
      'label' => 'Test policy',
      'access_rules' => [],
      'target_entity_type_id' => 'node',
    ])->save();
  }

  /**
   * Tests that a listing only displays entities that a user is allowed to view.
   */
  public function testContentListing() {

    $policy = AccessPolicy::create([
      'id' => 'matching_text',
      'label' => 'Matching Text Access Policy',
      'target_entity_type_id' => 'node',
    ]);
    // You should audit the rules  and see which ones are worth removing.
    $access_rule = $this->accessRuleManager->getHandler('node', 'field_text');
    $access_rule->setSettings([
      'operator' => '=',
      'value' => 'Foo',
      'empty_behavior' => 'deny',
    ]);
    $policy->addHandler('access_rule', $access_rule);
    $policy->save();

    $policy = AccessPolicy::create([
      'id' => 'basic_policy_no_rules',
      'label' => 'Test Access Policy',
      'target_entity_type_id' => 'node',
    ]);
    $policy->save();

    $admin_user = $this->drupalCreateUser([
      'access administration pages',
      'access content overview',
      'administer nodes',
      'bypass node access',
      'view matching_text content',
    ]);
    $admin_user->save();

    $this->drupalCreateNode([
      'title' => 'First',
      'type' => 'page',
      'status' => 1,
      'field_text' => 'Foo',
      'access_policy' => ['matching_text'],
    ]);

    $this->drupalCreateNode([
      'title' => 'Second',
      'type' => 'page',
      'status' => 1,
      'field_text' => 'Restricted',
      'access_policy' => ['matching_text'],
    ]);

    $this->drupalCreateNode([
      'title' => 'Third',
      'type' => 'page',
      'status' => 1,
      'access_policy' => ['matching_text'],
    ]);

    $this->drupalCreateNode([
      'title' => 'Fourth',
      'type' => 'page',
      'status' => 1,
      'access_policy' => ['basic_policy_no_rules'],
    ]);

    $this->drupalLogin($admin_user);

    // Verify that only the content that the user can access is listed.
    $this->drupalGet('admin/content');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->pageTextContains('First');
    $this->assertSession()->pageTextNotContains('Second');
    $this->assertSession()->pageTextNotContains('Third');
    $this->assertSession()->pageTextNotContains('Fourth');
  }

  /**
   * Tests that a policy is not applied to a query when disabled.
   */
  public function testContentListingWithPolicyQueryDisabled() {
    $policy = AccessPolicy::create([
      'id' => 'policy_with_query_disabled',
      'label' => 'Test Access Policy with query disabled.',
      'query' => FALSE,
      'target_entity_type_id' => 'node',
    ]);
    // You should audit the rules  and see which ones are worth removing.
    $access_rule = $this->accessRuleManager->getHandler('node', 'field_text');
    $access_rule->setSettings([
      'operator' => '=',
      'value' => 'Foo',
      'empty_behavior' => 'deny',
    ]);
    $policy->addHandler('access_rule', $access_rule);
    $policy->save();

    $node_1 = $this->drupalCreateNode([
      'title' => 'Different text (visible)',
      'type' => 'page',
      'status' => 1,
      'field_text' => 'Bar',
      'access_policy' => ['policy_with_query_disabled'],
    ]);

    $node_2 = $this->drupalCreateNode([
      'title' => 'Matching text (visible)',
      'type' => 'page',
      'status' => 1,
      'field_text' => 'Foo',
      'access_policy' => ['policy_with_query_disabled'],
    ]);

    $rid = $this->createRole([
      'access administration pages',
      'access content overview',
      'administer nodes',
    ]);
    $role = Role::load($rid);

    $user = $this->drupalCreateUser();
    $user->addRole($rid);
    $user->save();

    $this->drupalLogin($user);

    // Verify that all the content is visible on listing pages even if the
    // user doesn't have the permission to view content with that access policy.
    $this->drupalGet('node/' . $node_1->id());
    $this->assertSession()->statusCodeEquals(403);

    $this->drupalGet('node/' . $node_2->id());
    $this->assertSession()->statusCodeEquals(403);

    $this->drupalGet('admin/content');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->pageTextContains('Matching text (visible)');
    $this->assertSession()->pageTextContains('Different text (visible)');

    // Verify that all the content is visible on listing pages even if some
    // rules wouldn't usually pass when viewed directly.
    $this->grantPermissions($role, [
      'view policy_with_query_disabled content',
    ]);

    $this->drupalGet('node/' . $node_1->id());
    $this->assertSession()->statusCodeEquals(403);

    $this->drupalGet('node/' . $node_2->id());
    $this->assertSession()->statusCodeEquals(200);

    $this->drupalGet('admin/content');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->pageTextContains('Matching text (visible)');
    $this->assertSession()->pageTextContains('Different text (visible)');
  }

  /**
   * Tests content listing with multiple AND access rules.
   *
   * Tests that a listing only displays entities that a user is allowed to view
   * when that policy has multiple rules using AND.
   */
  public function testContentListingWithMultipleAndRules() {
    $policy = AccessPolicy::create([
      'id' => 'test_policy_with_and_rules',
      'label' => 'Test Access Policy with AND rules',
      'target_entity_type_id' => 'node',
    ]);
    $access_rule = $this->accessRuleManager->getHandler('node', 'field_text');
    $access_rule->setSettings([
      'operator' => '=',
      'value' => 'Foo',
    ]);
    $policy->addHandler('access_rule', $access_rule);
    $policy->addHandler('access_rule', $this->accessRuleManager->getHandler('node', 'is_own'));
    $policy->save();

    $admin_user = $this->drupalCreateUser([
      'access administration pages',
      'access content overview',
      'administer nodes',
      'bypass node access',
      'view test_policy_with_and_rules content',
    ]);

    $this->drupalCreateNode([
      'title' => 'Matching text (visible)',
      'type' => 'page',
      'status' => 1,
      'uid' => $admin_user->id(),
      'field_text' => 'Foo',
      'access_policy' => ['test_policy_with_and_rules'],
    ]);

    $this->drupalCreateNode([
      'title' => 'Different owner (hidden)',
      'type' => 'page',
      'status' => 1,
      'uid' => 100,
      'field_text' => 'Foo',
      'access_policy' => ['test_policy_with_and_rules'],
    ]);

    $this->drupalCreateNode([
      'title' => 'Different text and owner (hidden)',
      'type' => 'page',
      'status' => 1,
      'uid' => 100,
      'field_text' => 'Bar',
      'access_policy' => ['test_policy_with_and_rules'],
    ]);

    $this->drupalLogin($admin_user);

    // Verify that only the content that the user can access is listed.
    $this->drupalGet('admin/content');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->pageTextContains('Matching text (visible)');
    $this->assertSession()->pageTextNotContains('Different owner (hidden)');
    $this->assertSession()->pageTextNotContains('Different text and owner (hidden)');
  }

  /**
   * Tests content listing with multiple OR access rules.
   *
   * Tests that a listing only displays entities that a user is allowed to view
   * when that policy has multiple rules using OR.
   */
  public function testContentListingWithMultipleOrRules() {
    $policy = AccessPolicy::create([
      'id' => 'test_policy_with_or_rules',
      'label' => 'Test Access Policy with OR rules',
      'access_rule_operator' => 'OR',
      'target_entity_type_id' => 'node',
    ]);
    $access_rule = $this->accessRuleManager->getHandler('node', 'field_text');
    $access_rule->setSettings([
      'operator' => '=',
      'value' => 'Foo',
    ]);
    $policy->addHandler('access_rule', $access_rule);
    $policy->addHandler('access_rule', $this->accessRuleManager->getHandler('node', 'is_own'));
    $policy->save();

    $admin_user = $this->drupalCreateUser([
      'access administration pages',
      'access content overview',
      'administer nodes',
      'bypass node access',
      'view test_policy_with_or_rules content',
    ]);
    $admin_user->save();

    $this->drupalCreateNode([
      'title' => 'Matching text and owner (visible)',
      'type' => 'page',
      'status' => 1,
      'uid' => $admin_user->id(),
      'field_text' => 'Foo',
      'access_policy' => ['test_policy_with_or_rules'],
    ]);

    $this->drupalCreateNode([
      'title' => 'Different text (visible)',
      'type' => 'page',
      'status' => 1,
      'uid' => $admin_user->id(),
      'field_text' => 'Bar',
      'access_policy' => ['test_policy_with_or_rules'],
    ]);

    $this->drupalCreateNode([
      'title' => 'Different owner (visible)',
      'type' => 'page',
      'status' => 1,
      'uid' => 100,
      'field_text' => 'Foo',
      'access_policy' => ['test_policy_with_or_rules'],
    ]);

    $this->drupalCreateNode([
      'title' => 'Different text and owner (hidden)',
      'type' => 'page',
      'status' => 1,
      'uid' => 100,
      'field_text' => 'Bar',
      'access_policy' => ['test_policy_with_or_rules'],
    ]);

    $this->drupalLogin($admin_user);

    // Verify that only the content that the user can access is listed.
    $this->drupalGet('admin/content');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->pageTextContains('Matching text and owner (visible)');
    $this->assertSession()->pageTextContains('Different text (visible)');
    $this->assertSession()->pageTextContains('Different owner (visible)');
    $this->assertSession()->pageTextNotContains('Different text and owner (hidden)');
  }

  /**
   * Tests that a listing displays entities with Access Rules a user can bypass.
   */
  public function testContentListingWithBypassAccessRulesEnabled() {
    $policy = AccessPolicy::create([
      'id' => 'matching_text',
      'label' => 'Matching Text Access Policy',
      'target_entity_type_id' => 'node',
    ]);
    $access_rule = $this->accessRuleManager->getHandler('node', 'field_text');
    $access_rule->setSettings([
      'operator' => '=',
      'value' => 'Foo',
    ]);
    $policy->addHandler('access_rule', $access_rule);
    $policy->save();

    $admin_user = $this->drupalCreateUser([
      'access administration pages',
      'access content overview',
      'administer nodes',
      'bypass node access',
      'view matching_text content',
      'bypass matching_text access rules',
    ]);
    $admin_user->set('field_text', 'Matching text');
    $admin_user->save();

    $this->drupalCreateNode([
      'title' => 'First',
      'type' => 'page',
      'status' => 1,
      'field_text' => 'Foo',
      'access_policy' => ['matching_text'],
    ]);

    $this->drupalCreateNode([
      'title' => 'Second',
      'type' => 'page',
      'status' => 1,
      'field_text' => 'Bar',
      'access_policy' => ['matching_text'],
    ]);

    $this->drupalLogin($admin_user);

    // Verify that content for which a user can bypass Access Rules is listed.
    $this->drupalGet('admin/content');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->pageTextContains('First');
    $this->assertSession()->pageTextContains('Second');
  }

  /**
   * Tests that an access rule without a query doesn't break the query.
   */
  public function testContentListingWithAccessRulesQueryMissing() {
    $policy = AccessPolicy::create([
      'id' => 'rules_with_no_query',
      'label' => 'Test Access Policy with no query rules',
      'target_entity_type_id' => 'node',
    ]);
    $policy->addHandler('access_rule', $this->accessRuleManager->getHandler('node', 'access_rule_test'));
    $policy->save();

    $admin_user = $this->drupalCreateUser([
      'access administration pages',
      'access content overview',
      'administer nodes',
      'bypass node access',
      'view rules_with_no_query content',
    ]);
    $admin_user->set('field_text', 'Does not match');
    $admin_user->save();

    $this->drupalCreateNode([
      'title' => 'First',
      'type' => 'page',
      'status' => 1,
      'field_text' => 'First',
      'access_policy' => ['rules_with_no_query'],
    ]);

    $this->drupalCreateNode([
      'title' => 'Second',
      'type' => 'page',
      'status' => 1,
      'field_text' => 'Second',
      'access_policy' => ['rules_with_no_query'],
    ]);

    $this->drupalLogin($admin_user);

    // If query is enabled for the rules then these would not be visible.
    $this->drupalGet('admin/content');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->pageTextContains('First');
    $this->assertSession()->pageTextContains('Second');
  }

  /**
   * Tests that a listing displays entities when Access Rule query disabled.
   */
  public function testContentListingWithAccessRulesQueryDisabled() {
    $policy = AccessPolicy::create([
      'id' => 'rules_with_disabled_query',
      'label' => 'Test Access Policy with disabled rules',
      'target_entity_type_id' => 'node',
    ]);
    $access_rule = $this->accessRuleManager->getHandler('node', 'field_text');
    $access_rule->setSettings([
      'operator' => '=',
      'value' => 'Does not match',
      'query' => FALSE,
    ]);
    $policy->addHandler('access_rule', $access_rule);
    $policy->save();

    $this->drupalCreateNode([
      'title' => 'First',
      'type' => 'page',
      'status' => 1,
      'field_text' => 'Foo',
      'access_policy' => ['rules_with_disabled_query'],
    ]);

    $this->drupalCreateNode([
      'title' => 'Second',
      'type' => 'page',
      'status' => 1,
      'field_text' => 'Bar',
      'access_policy' => ['rules_with_disabled_query'],
    ]);

    $admin_user = $this->drupalCreateUser([
      'access administration pages',
      'access content overview',
      'administer nodes',
      'bypass node access',
      'view rules_with_disabled_query content',
    ]);
    $this->drupalLogin($admin_user);

    // These are only visible because query is disabled, otherwise they would
    // be hidden.
    $this->drupalGet('admin/content');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->pageTextContains('First');
    $this->assertSession()->pageTextContains('Second');
  }

  /**
   * Test content listing for entities with multiple policies.
   */
  public function testContentListingWithMultiplePolicies() {
    AccessPolicy::create([
      'id' => 'policy_1',
      'label' => 'Policy 1',
      'target_entity_type_id' => 'node',
      'selection_set' => ['restricted'],
    ])->save();

    AccessPolicy::create([
      'id' => 'policy_2',
      'label' => 'Policy 2',
      'target_entity_type_id' => 'node',
      'selection_set' => ['restricted'],
    ])->save();

    $admin_user = $this->drupalCreateUser([
      'access administration pages',
      'access content overview',
      'administer nodes',
      'bypass node access',
      'view policy_1 content',
      'view policy_2 content',
    ]);
    $admin_user->save();

    $this->drupalCreateNode([
      'title' => 'First',
      'type' => 'page',
      'status' => 1,
      'access_policy' => ['policy_1', 'policy_2'],
    ]);

    $this->drupalLogin($admin_user);

    // If query is enabled for the rules then these would not be visible.
    $this->drupalGet('admin/content');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->pageTextContainsOnce('First');
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc