access_policy-1.0.x-dev/tests/src/Kernel/AccessPolicySelectionTest.php

tests/src/Kernel/AccessPolicySelectionTest.php
<?php

namespace Drupal\Tests\access_policy\Kernel;

use Drupal\access_policy\Entity\AccessPolicy;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\node\Entity\NodeType;

/**
 * Tests Access Policy selection manager.
 *
 * @group access_policy
 */
class AccessPolicySelectionTest extends AccessPolicyKernelTestBase {

  /**
   * The access policy selection service.
   *
   * @var \Drupal\access_policy\AccessPolicySelectionInterface
   */
  protected $accessPolicySelection;

  /**
   * The entity type settings service.
   *
   * @var \Drupal\access_policy\EntityTypeSettingsInterface
   */
  protected $entityTypeSettings;

  /**
   * {@inheritdoc}
   *
   * @throws \Exception
   */
  protected function setUp(): void {
    parent::setUp();

    NodeType::create(['type' => 'page', 'name' => 'Page']);
    NodeType::create(['type' => 'article', 'name' => 'Article']);

    $this->installConfig(['access_policy_test']);

    $this->entityTypeSettings = $this->container->get('access_policy.entity_type_settings');
    $this->accessPolicySelection = $this->container->get('access_policy.selection');
  }

  /**
   * Tests getting the default access policy for first available policies.
   *
   * If the default setting is set to on_create it should return the
   * first access policy that the user has access too. Prioritized by
   * weight.
   *
   * @throws \Exception
   */
  public function testGetFirstAvailableDefaultAccessPolicy() {
    // Set access policies as first accessible.
    $settings = $this->entityTypeSettings->load('node');
    $settings->set('selection_strategy', 'manual');
    $settings->set('selection_strategy_settings', [
      'allow_empty' => TRUE,
      'default_policy' => 'first_available',
      'show_operations_link' => FALSE,
    ]);
    $settings->save();

    AccessPolicy::create([
      'id' => 'policy_test_1',
      'label' => 'Policy test 1',
      'access_rules' => [],
      'target_entity_type_id' => 'node',
      'weight' => 0,
    ])->save();

    AccessPolicy::create([
      'id' => 'policy_test_2',
      'label' => 'Policy test 2',
      'access_rules' => [],
      'target_entity_type_id' => 'node',
      'weight' => -10,
    ])->save();

    $node = $this->createNode([
      'type' => 'page',
      'title' => 'Page',
    ]);
    $node->save();

    // This user doesn't have permission to any of these access policies so it
    // should not return anything.
    $user = $this->createUser();
    $default_policy = $this->accessPolicySelection->getDefaultPolicy($node, $user);
    $this->assertEquals(FALSE, $default_policy, 'This should not return an access policy');

    $this->accessPolicySelection->resetCache();
    // The user only has access to editing one access policy therefore it
    // should only return that access policy.
    $user_2 = $this->createUser([
      'assign policy_test_2 access policy',
    ]);
    $default_policy = $this->accessPolicySelection->getDefaultPolicy($node, $user_2);
    $policy = reset($default_policy);
    $this->assertEquals('policy_test_2', $policy->id(), 'Only one access policy is assigned.');

    $this->accessPolicySelection->resetCache();
    // The user has access to two access policies but it will only return the
    // one with the lowest weight (highest priority).
    $user_3 = $this->createUser([
      'assign policy_test_1 access policy',
      'assign policy_test_2 access policy',
    ]);
    $default_policy = $this->accessPolicySelection->getDefaultPolicy($node, $user_3);
    $policy = reset($default_policy);
    $this->assertEquals('policy_test_2', $policy->id(), 'policy test 2 has lower weight (higher priority) and should be returned.');
  }

  /**
   * Tests getting the default access policy when default is empty.
   *
   * If the default setting is set to empty the user should not get a default
   * policy. Even if they have permission to use it.
   *
   * @throws \Exception
   */
  public function testGetDefaultAccessPolicyWhenEmpty() {
    $settings = $this->entityTypeSettings->load('node');
    $settings->set('selection_strategy', 'manual');
    $settings->save();

    $accessPolicySelection = \Drupal::service('access_policy.selection');

    AccessPolicy::create([
      'id' => 'policy_test',
      'label' => 'Policy test',
      'access_rules' => [],
      'target_entity_type_id' => 'node',
      'weight' => 0,
    ])->save();

    $node = $this->createNode([
      'type' => 'page',
      'title' => 'Page',
    ]);
    $node->save();

    $user = $this->createUser([
      'assign policy_test access policy',
    ]);
    $default_policy = $accessPolicySelection->getDefaultPolicy($node, $user);
    $this->assertEquals(FALSE, $default_policy, 'This should not return an access policy');
  }

  /**
   * Tests getting the access policy when a selection rule is defined.
   */
  public function testGetAccessPolicyWithSelectionRule() {
    $policy_1 = AccessPolicy::create([
      'id' => 'policy_test_1',
      'label' => 'Policy test 1',
      'access_rules' => [],
      'target_entity_type_id' => 'node',
      'weight' => 0,
    ]);
    $policy_1->save();

    $policy_2 = AccessPolicy::create([
      'id' => 'policy_test_2',
      'label' => 'Policy test 2',
      'access_rules' => [],
      'target_entity_type_id' => 'node',
      'weight' => -10,
    ]);
    $policy_2->save();

    $selection_rule = $this->selectionRuleManager->getHandler('node', 'field_text');
    $policy_2->addHandler('selection_rule', $selection_rule);
    $policy_2->save();

    $user_1 = $this->createUser([
      'assign policy_test_1 access policy',
      'assign policy_test_2 access policy',
    ]);

    $this->setCurrentUser($user_1);

    // Even though policy_test_2 has lower weight it will not be selected
    // because the content does not have a value for field_text.
    $node = $this->createNode([
      'type' => 'page',
      'title' => 'Page',
    ]);

    $policy = $this->contentAccessPolicyManager->getAccessPolicy($node);
    $policy = reset($policy);
    $this->assertEquals('policy_test_1', $policy->id(), 'The access policy should be policy_test_1');

    // Because this has a value in field_text, policy_test_2 will be selected.
    $node_2 = $this->createNode([
      'type' => 'page',
      'title' => 'Page',
      'field_text' => 'This has a value.',
    ]);

    $policy = $this->contentAccessPolicyManager->getAccessPolicy($node_2);
    $policy = reset($policy);
    $this->assertEquals('policy_test_2', $policy->id(), 'The access policy should be policy_test_2');

    // Remove the field text and save the node, this should change the policy
    // to policy_test_1.
    // We need to remove the policyUpdated flag in order to properly test it
    // again. @see EntityOperations::entityPresave().
    unset($node_2->policyUpdated);
    $node_2->set('field_text', '');
    $node_2->save();
    $policy_2 = $this->contentAccessPolicyManager->getAccessPolicy($node_2);
    $policy_2 = reset($policy_2);
    $this->assertEquals('policy_test_1', $policy_2->id(), 'The access policy should be policy_test_1');

    // Article does not have the field_text field, it should be policy_test_1.
    $node_3 = $this->createNode([
      'type' => 'article',
      'title' => 'Article',
    ]);

    $policy = $this->contentAccessPolicyManager->getAccessPolicy($node_3);
    $policy = reset($policy);
    $this->assertEquals('policy_test_1', $policy->id(), 'The access policy should be policy_test_1');

    // User 2 only has access to policy_test_2 access policy. Because node_4
    // does not have text value it should remove any policy.
    $user_2 = $this->createUser([
      'assign policy_test_2 access policy',
    ]);
    $this->setCurrentUser($user_2);

    $node_4 = $this->createNode([
      'type' => 'page',
      'title' => 'Page',
      'field_text' => '',
    ]);

    $policy = $this->contentAccessPolicyManager->getAccessPolicy($node_4);
    $this->assertEmpty($policy, 'The access policy should be empty');
  }

  /**
   * Tests getting the access policy with multiple AND selection rules.
   */
  public function testGetAccessPolicyWithMultipleAndSelectionRules() {
    // Create a boolean field for this test.
    $field_storage = FieldStorageConfig::create([
      'field_name' => 'field_boolean',
      'entity_type' => 'node',
      'type' => 'boolean',
    ]);
    $field_storage->save();
    $field = FieldConfig::create([
      'field_name' => 'field_boolean',
      'entity_type' => 'node',
      'bundle' => 'page',
      'label' => "boolean",
      'required' => TRUE,
      'settings' => [
        'on_label' => 'On',
        'off_label' => 'Off',
      ],
    ]);
    $field->save();

    $policy_1 = AccessPolicy::create([
      'id' => 'policy_test_1',
      'label' => 'Policy test 1',
      'access_rules' => [],
      'target_entity_type_id' => 'node',
      'weight' => -10,
    ]);
    $policy_1->save();

    // This will only be assigned if field_text is Foo OR Bar.
    $selection_rule = $this->selectionRuleManager->getHandler('node', 'field_text');
    $selection_rule->setSettings([
      'operator' => '=',
      'value' => 'Foo',
    ]);
    $policy_1->addHandler('selection_rule', $selection_rule);

    $selection_rule = $this->selectionRuleManager->getHandler('node', 'field_boolean');
    $selection_rule->setSettings([
      'operator' => '=',
      'value' => 'true',
    ]);
    $policy_1->addHandler('selection_rule', $selection_rule);
    $policy_1->save();

    $user_1 = $this->createUser([
      'assign policy_test_1 access policy',
    ]);

    $this->setCurrentUser($user_1);

    $node = $this->createNode([
      'type' => 'page',
      'title' => 'Page',
      'field_text' => 'Foo',
      'field_boolean' => TRUE,
    ]);

    $policy = $this->contentAccessPolicyManager->getAccessPolicy($node);
    $policy = reset($policy);
    $this->assertEquals('policy_test_1', $policy->id(), 'policy_test_1 should be assigned');

    // Change the boolean value, this should remove the policy.
    // We need to remove the policyUpdated flag in order to properly test it
    // again. @see EntityOperations::entityPresave().
    unset($node->policyUpdated);
    $node->set('field_boolean', FALSE);
    $node->save();

    $policy = $this->contentAccessPolicyManager->getAccessPolicy($node);
    $this->assertEmpty($policy, 'policy_test_1 should be removed.');
  }

  /**
   * Tests getting the access policy with multiple OR selection rules.
   */
  public function testGetAccessPolicyWithMultipleOrSelectionRules() {
    $policy_1 = AccessPolicy::create([
      'id' => 'policy_test_1',
      'label' => 'Policy test 1',
      'access_rules' => [],
      'target_entity_type_id' => 'node',
      'weight' => -10,
      'selection_rule_operator' => 'OR',
    ]);
    $policy_1->save();

    // This will only be assigned if field_text is Foo OR Bar.
    $selection_rule = $this->selectionRuleManager->getHandler('node', 'field_text');
    $selection_rule->setSettings([
      'operator' => '=',
      'value' => 'Foo',
    ]);
    $policy_1->addHandler('selection_rule', $selection_rule);

    $selection_rule = $this->selectionRuleManager->getHandler('node', 'field_text');
    $selection_rule->setSettings([
      'operator' => '=',
      'value' => 'Bar',
    ]);
    $policy_1->addHandler('selection_rule', $selection_rule);
    $policy_1->save();

    $user_1 = $this->createUser([
      'assign policy_test_1 access policy',
    ]);

    $this->setCurrentUser($user_1);

    $node = $this->createNode([
      'type' => 'page',
      'title' => 'Page',
      'field_text' => 'Foo',
    ]);

    $policy = $this->contentAccessPolicyManager->getAccessPolicy($node);
    $policy = reset($policy);
    $this->assertEquals('policy_test_1', $policy->id(), 'policy_test_1 should be assigned.');

    // Remove the text value, this should remove the policy.
    // We need to remove the policyUpdated flag in order to properly test it
    // again. @see EntityOperations::entityPresave().
    unset($node->policyUpdated);
    $node->set('field_text', '');
    $node->save();

    $policy = $this->contentAccessPolicyManager->getAccessPolicy($node);
    $this->assertEmpty($policy, 'policy_test_1 should be removed.');

    // Change text to Bar, this should reassign to the policy.
    unset($node->policyUpdated);
    $node->set('field_text', 'Bar');
    $node->save();

    $policy = $this->contentAccessPolicyManager->getAccessPolicy($node);
    $policy = reset($policy);
    $this->assertEquals('policy_test_1', $policy->id(), 'policy_test_1 should be assigned.');
  }

  /**
   * Tests assigning multiple access policies with selection rules.
   */
  public function testGetMultipleAccessPoliciesWithSelectionRules() {

    $field_storage = FieldStorageConfig::create([
      'field_name' => 'field_text_2',
      'entity_type' => 'node',
      'type' => 'text',
    ]);
    $field_storage->save();
    $field = FieldConfig::create([
      'field_storage' => $field_storage,
      'bundle' => 'page',
    ]);
    $field->save();

    $policy_group_1 = AccessPolicy::create([
      'id' => 'policy_group_1',
      'label' => 'Policy group 1',
      'access_rules' => [],
      'target_entity_type_id' => 'node',
      'selection_set' => ['restricted'],
      'weight' => -10,
    ]);
    $policy_group_1->save();
    $selection_rule = $this->selectionRuleManager->getHandler('node', 'field_text');
    $selection_rule->setSettings([
      'operator' => '=',
      'value' => 'Foo',
    ]);
    $policy_group_1->addHandler('selection_rule', $selection_rule);

    // This policy is second in the list, this is to ensure that only
    // policy_group_n policies get assigned even though they have different
    // priorities.
    $basic_policy = AccessPolicy::create([
      'id' => 'basic',
      'label' => 'Basic',
      'access_rules' => [],
      'target_entity_type_id' => 'node',
      'weight' => -5,
    ]);
    $basic_policy->save();

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

    // This will only be assigned if field_text is Foo OR Bar.
    $selection_rule = $this->selectionRuleManager->getHandler('node', 'field_text_2');
    $selection_rule->setSettings([
      'operator' => '=',
      'value' => 'Bar',
    ]);
    $policy_group_2->addHandler('selection_rule', $selection_rule);

    $user_1 = $this->createUser([
      'assign policy_group_1 access policy',
      'assign policy_group_2 access policy',
      'assign basic access policy',
    ]);

    $this->setCurrentUser($user_1);

    $node = $this->createNode([
      'type' => 'page',
      'title' => 'Page',
      'field_text' => 'Foo',
      'field_text_2' => 'Foo bar',
    ]);

    $actual = [];
    $policies = $this->contentAccessPolicyManager->getAccessPolicy($node);
    foreach ($policies as $policy) {
      $actual[] = $policy->id();
    }
    $expected = [
      'policy_group_1',
      'policy_group_2',
    ];
    $this->assertSame($expected, $actual, 'Both access policies should be assigned.');
  }

}

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

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