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

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

namespace Drupal\Tests\access_policy\Functional;

use Drupal\access_policy\Entity\AccessPolicy;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;

/**
 * Tests the creation and deletion of access policy entities.
 *
 * @group access_policy
 */
class AccessPolicyCreationTest extends AccessPolicyTestBase {

  /**
   * Modules to enable.
   *
   * @var array
   */
  protected static $modules = [
    'access_policy',
    'access_policy_test',
    'taxonomy',
    'filter',
    'node',
    'block_content',
    'comment',
    'datetime',
    'options',
  ];

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

  /**
   * Tests creating and deleting a new access policy with rules and bundles.
   */
  public function testCreateAndDeleteAccessPolicyWithRules() {
    $settings = $this->entityTypeSettings->load('node');
    $settings->set('selection_strategy', 'manual');
    $settings->save();

    $rid = $this->drupalCreateRole([
      'access administration pages',
      'administer access policy entities',
    ]);
    $web_user = $this->drupalCreateUser();
    $web_user->addRole($rid);
    $web_user->save();

    $this->drupalLogin($web_user);

    $this->drupalGet('admin/people/access-policies');
    $this->assertSession()->statusCodeEquals(200);

    $this->drupalGet('admin/people/access-policies/add');

    $this->assertSession()->optionExists('target_entity_type_id', 'node');
    $this->assertSession()->optionExists('target_entity_type_id', 'taxonomy_term');
    $this->assertSession()->optionExists('target_entity_type_id', 'block_content');
    $this->assertSession()->optionNotExists('target_entity_type_id', 'comment');

    $edit = [
      'label' => 'Foo',
      'id' => 'foo',
    ];
    $this->submitForm($edit, 'Save');

    // Add a rule to the policy (cancel)
    $this->drupalGet('/admin/people/access-policies/foo/handler/access_rule/add');
    $this->assertSession()->statusCodeEquals(200);
    $edit = [
      'access_rules[node:title]' => TRUE,
    ];
    $this->submitForm($edit, 'Add and configure');
    // Go to access rule configuration form and press cancel. Make sure it
    // does not save anything.
    $this->submitForm([], 'Cancel');
    $this->drupalGet('/admin/people/access-policies/foo');
    $this->assertSession()->pageTextNotContains('Title (= )');

    // Add a rule to the policy (submit).
    $this->drupalGet('/admin/people/access-policies/foo/handler/access_rule/add');
    $this->assertSession()->statusCodeEquals(200);
    $edit = [
      'access_rules[node:title]' => TRUE,
    ];
    $this->submitForm($edit, 'Add and configure');
    $this->assertSession()->fieldValueEquals('query', TRUE);
    $this->assertSession()->fieldValueEquals('admin_label', '');
    $this->submitForm([], 'Save');

    $this->drupalGet('/admin/people/access-policies/foo');
    $this->assertSession()->pageTextContains('Title (= )');

    // Change settings of title access rule.
    $this->drupalGet('/admin/people/access-policies/foo/handler/access_rule/title');
    $this->assertSession()->statusCodeEquals(200);
    $edit = [
      'operator' => '=',
      'value' => 'Foo bar',
      'query' => FALSE,
    ];
    $this->submitForm($edit, 'Save');

    $this->drupalGet('/admin/people/access-policies/foo');
    $this->assertSession()->pageTextContains('Configure Foo access policy');
    $this->assertSession()->pageTextContains('Title (= Foo bar)');

    $this->drupalGet('/admin/people/access-policies/foo/handler/access_rule/title');
    $this->assertSession()->fieldValueEquals('operator', '=');
    $this->assertSession()->fieldValueEquals('value', 'Foo bar');
    $this->assertSession()->fieldValueEquals('query', FALSE);

    // Change the admin label.
    $edit = [
      'admin_label' => 'Title field overridden.',
    ];
    $this->submitForm($edit, 'Save');
    $this->drupalGet('/admin/people/access-policies/foo');
    $this->assertSession()->pageTextContains('Title field overridden.');

    // Delete the is_own access rule.
    $this->drupalGet('/admin/people/access-policies/foo/handler/access_rule/title/remove');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->pageTextContains('Are you sure you want to remove this?');
    $this->submitForm([], 'Remove');
    $this->drupalGet('/admin/people/access-policies/foo');
    $this->assertSession()->pageTextNotContains('Authored by current user (modified)');

    // Change the other fields in the policy.
    $edit = [
      'label' => 'Bar',
      'description' => 'Lorem ipsum dolor.',
      'access_rule_operator' => 'OR',
    ];
    $this->submitForm($edit, 'Save');

    $this->clickLink('Configure');

    $this->assertSession()->fieldValueEquals('label', 'Bar');
    $this->assertSession()->fieldValueEquals('description', 'Lorem ipsum dolor.');
    $this->assertSession()->fieldValueEquals('access_rule_operator', 'OR');

    $this->clickLink('Delete');
    $this->assertSession()->pageTextContains('Are you sure you want to delete Bar?');
    $this->submitForm([], 'Delete');
    $this->assertSession()->pageTextContains('Deleted Bar Access Policy');

    $policy = $this->entityTypeManager->getStorage('access_policy')->load('foo');
    $this->assertEmpty($policy, 'The policy should have been deleted.');
  }

  /**
   * Tests setting creating a new access policy.
   */
  public function testDoNotPermitPolicyDeletionWhenUsed() {
    AccessPolicy::create([
      'id' => 'test_policy',
      'label' => 'Test policy',
      'access_rules' => [],
      'target_entity_type_id' => 'node',
    ])->save();

    $this->drupalCreateNode([
      'type' => 'page',
      'access_policy' => ['test_policy'],
    ]);

    $web_user = $this->drupalCreateUser([
      'access administration pages',
      'administer access policy entities',
    ]);
    $this->drupalLogin($web_user);

    $this->drupalGet('admin/people/access-policies/test_policy/delete');

    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->pageTextContains('Are you sure you want to delete Test policy?');
    $this->assertSession()->pageTextContains('The access policy Test policy is being used, and cannot be deleted.');
    $this->assertSession()->linkNotExists('Delete');
  }

  /**
   * Tests updating the access policy operations.
   */
  public function testUpdateAccessPolicyOperations() {

    $rid = $this->drupalCreateRole([
      'access administration pages',
      'administer access policy entities',
    ]);

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

    $this->drupalGet('admin/people/access-policies');
    $this->assertSession()->statusCodeEquals(200);

    $this->drupalGet('admin/people/access-policies/add');

    $edit = [
      'label' => 'Foo',
      'id' => 'foo',
    ];
    $this->submitForm($edit, 'Save');

    // Add a rule to the policy and override its default operations.
    $this->drupalGet('/admin/people/access-policies/foo/handler/access_rule/add');
    $this->assertSession()->statusCodeEquals(200);
    $edit = [
      'access_rules[node:title]' => TRUE,
    ];
    $this->submitForm($edit, 'Add and configure');
    $this->submitForm([], 'Save');

    // Disable the default access rule operations and use 'view' and 'edit'.
    // For some reason it needs to be done through the API. it doesn't work
    // through the interface during the test.
    $policy = $this->entityTypeManager->getStorage('access_policy')->load('foo');
    $handlers = $policy->getHandlers('access_rule');
    $handlers['title']['settings']['operations'] = ['view', 'edit'];
    $policy->setHandlers('access_rule', $handlers);
    $policy->save();

    // Add the new permissions to the role. They should be generated after
    // creating the new policy.
    $role = $this->entityTypeManager->getStorage('user_role')->load($rid);
    $role->grantPermission('view foo content');
    $role->grantPermission('delete foo content');
    $role->grantPermission('edit foo content');
    $role->grantPermission('view all foo content revisions');
    $role->grantPermission('view any foo unpublished content');
    $role->grantPermission('assign foo access policy');
    $role->save();

    // Confirm that manage access is checked and disabled.
    $this->drupalGet('admin/people/access-policies/foo/operations');
    $this->assertSession()->checkboxChecked('operations[manage_access][permission]');
    $this->assertSession()->fieldDisabled('operations[manage_access][permission]');

    // Disable the permissions. It should automatically remove the permissions
    // from the roles.
    $edit = [
      'operations[view][permission]' => 0,
      'operations[view_unpublished][permission]' => 0,
      'operations[view_all_revisions][permission]' => 0,
      'operations[edit][permission]' => 0,
      'operations[delete][permission]' => 0,
      'operations[manage_access][permission]' => 0,
    ];
    $this->submitForm($edit, 'Save operations');
    $this->entityTypeManager->getStorage('user_role')->resetCache();
    $role = $this->entityTypeManager->getStorage('user_role')->load($rid);
    $expected = [
      'access administration pages',
      'administer access policy entities',
      // It should not be possible to remove this because it is not owned by
      // the manage_access operation.
      'assign foo access policy',
    ];
    $this->assertEquals($expected, $role->getPermissions());

    // Disable the view access rule, it should remove the view operation
    // override.
    $this->drupalGet('admin/people/access-policies/foo/operations');
    $edit = [
      'operations[view][access_rules]' => 0,
    ];
    $this->submitForm($edit, 'Save operations');

    $this->entityTypeManager->getStorage('access_policy')->resetCache();
    $policy = $this->entityTypeManager->getStorage('access_policy')->load('foo');
    $handler = $policy->getHandler('access_rule', 'title');
    $this->assertEquals(['edit'], $handler['settings']['operations'], 'The view operation should be removed.');

    // Disable all the access rules, it should hide the access rules form and
    // remove all the access rules.
    $this->drupalGet('admin/people/access-policies/foo/operations');
    $edit = [
      'operations[view][access_rules]' => 0,
      'operations[view_unpublished][access_rules]' => 0,
      'operations[view_all_revisions][access_rules]' => 0,
      'operations[edit][access_rules]' => 0,
      'operations[delete][access_rules]' => 0,
      'operations[manage_access][access_rules]' => 0,
    ];
    $this->submitForm($edit, 'Save operations');

    $this->assertSession()->linkNotExists('Add Rule');
    $this->assertSession()->linkNotExists('Validation operator');

    $this->entityTypeManager->getStorage('access_policy')->resetCache();
    $policy = $this->entityTypeManager->getStorage('access_policy')->load('foo');
    $handlers = $policy->getHandlers('access_rule');
    $this->assertEmpty($handlers, 'The access rules should have been removed.');

    // Disable the columns, it should hide them on the form.
    $this->drupalGet('admin/people/access-policies/foo');
    $session = $this->assertSession();
    $session->elementExists('xpath', "//th[text() = 'View unpublished']");
    $session->elementExists('xpath', "//th[text() = 'View']");
    $session->elementExists('xpath', "//th[text() = 'View all revisions']");
    $session->elementExists('xpath', "//th[text() = 'Edit']");
    $session->elementExists('xpath', "//th[text() = 'Delete']");

    $this->drupalGet('admin/people/access-policies/foo/operations');
    $edit = [
      'operations[view][show_column]' => 0,
      'operations[view_unpublished][show_column]' => 0,
      'operations[view_all_revisions][show_column]' => 0,
      'operations[edit][show_column]' => 0,
      'operations[delete][show_column]' => 0,
      'operations[manage_access][show_column]' => 0,
    ];
    $this->submitForm($edit, 'Save operations');
    $this->drupalGet('admin/people/access-policies/foo');
    $session->elementNotExists('xpath', "//th[text() = 'View unpublished']");
    $session->elementNotExists('xpath', "//th[text() = 'View']");
    $session->elementNotExists('xpath', "//th[text() = 'View all revisions']");
    $session->elementNotExists('xpath', "//th[text() = 'Edit']");
    $session->elementNotExists('xpath', "//th[text() = 'Delete']");
  }

  /**
   * Tests creating and viewing an access policy with broken access rules.
   */
  public function testCreatePolicyWithBrokenRule() {
    // This is an access policy with the old access rule data and a missing
    // plugin. Without a valid plugin it is effectively broken.
    AccessPolicy::create([
      'id' => 'broken_rules',
      'label' => 'Access policy with broken rules.',
      'access_rules' => [
        'field_value:node:field_text' => [
          'plugin_id' => 'field_value:node:field_text',
          'settings' => [
            'target' => 'value',
            'value' => 'My text',
            'operator' => '=',
            'query' => TRUE,
            'empty_behavior' => 'deny',
          ],
        ],
      ],
      'target_entity_type_id' => 'node',
    ])->save();

    // This is an access policy with correct access rule data. This acts as a
    // control to compare against the broken_rules policy.
    $policy = AccessPolicy::create([
      'id' => 'working_rules',
      'label' => 'Access policy with working rules.',
      'target_entity_type_id' => 'node',
    ]);
    $access_rule = $this->accessRuleManager->getHandler('node', 'field_text', [
      'value' => 'My text',
      'operator' => '=',
      'query' => TRUE,
      'empty_behavior' => 'deny',
    ]);

    $policy->addHandler('access_rule', $access_rule);
    $policy->save();

    $rid = $this->drupalCreateRole([
      'access administration pages',
      'access content overview',
      'administer access policy entities',
      'view broken_rules content',
    ]);
    $web_user = $this->drupalCreateUser();
    $web_user->addRole($rid);
    $web_user->save();

    $this->drupalLogin($web_user);

    // Because the user does not have an entity reference this normally
    // would return 403, but because it's broken it should return 200.
    $node_broken = $this->drupalCreateNode([
      'title' => 'Node (broken)',
      'type' => 'page',
      'status' => 1,
      'access_policy' => ['broken_rules'],
    ]);
    $node_working = $this->drupalCreateNode([
      'title' => 'Node (working)',
      'type' => 'page',
      'status' => 1,
      'field_text' => 'My text',
      'access_policy' => ['working_rules'],
    ]);

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

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

    $this->drupalGet('admin/content');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->pageTextContainsOnce('Node (broken)');
    $this->assertSession()->pageTextNotContains('Node (working)');

    // Configure the policy.
    $this->drupalGet('admin/people/access-policies/broken_rules');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->pageTextContainsOnce('Broken/missing handler');

    // Configure the broken access rule.
    $this->clickLink('Configure');
    $this->assertSession()->pageTextContains('The handler for this access rule is broken or missing.');

    // Delete the broken access rule.
    $this->drupalGet('/admin/people/access-policies/broken_rules/handler/access_rule/field_value:node:field_text/remove');
    $this->submitForm([], 'Remove');
    $this->drupalGet('/admin/people/access-policies/broken_rules');
    $this->assertSession()->pageTextNotContains('Broken/missing handler');

    // Add a rule to the policy. It should show the broken handler.
    $this->drupalGet('/admin/people/access-policies/broken_rules/handler/access_rule/add');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->pageTextContains('Broken/missing handler');
  }

  /**
   * Tests creating and viewing an access policy invalid access rule data.
   */
  public function testCreatePolicyWithInvalidAccessRuleData() {
    // This is an access policy with the old access rule data. However, this has
    // a valid plugin id, therefore it should still work but show a warning.
    AccessPolicy::create([
      'id' => 'invalid_rules',
      'label' => 'Access policy with invalid rule data.',
      'access_rules' => [
        'field_text' => [
          'plugin_id' => 'entity_field_string',
          'settings' => [
            'target' => 'value',
            'value' => 'My text',
            'operator' => '=',
            'query' => TRUE,
            'empty_behavior' => 'deny',
            'admin_label' => '',
          ],
        ],
      ],
      'target_entity_type_id' => 'node',
    ])->save();

    // This is an access policy with valid access rule data. This acts as a
    // control to compare against the invalid_rules policy.
    $policy = AccessPolicy::create([
      'id' => 'valid_rules',
      'label' => 'Access policy with valid rule data.',
      'target_entity_type_id' => 'node',
    ]);
    $access_rule = $this->accessRuleManager->getHandler('node', 'field_text', [
      'value' => 'My text',
      'operator' => '=',
      'query' => TRUE,
      'empty_behavior' => 'deny',
    ]);

    $policy->addHandler('access_rule', $access_rule);
    $policy->save();

    $rid = $this->drupalCreateRole([
      'access administration pages',
      'access content overview',
      'administer access policy entities',
      'view invalid_rules content',
      'view valid_rules content',
    ]);
    $web_user = $this->drupalCreateUser();
    $web_user->addRole($rid);
    $web_user->save();

    $this->drupalLogin($web_user);

    $node_invalid = $this->drupalCreateNode([
      'title' => 'Node (invalid)',
      'type' => 'page',
      'status' => 1,
      'field_text' => 'Not matching text',
      'access_policy' => ['invalid_rules'],
    ]);
    $node_valid = $this->drupalCreateNode([
      'title' => 'Node (valid)',
      'type' => 'page',
      'status' => 1,
      'field_text' => 'Not matching text',
      'access_policy' => ['valid_rules'],
    ]);

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

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

    $this->drupalGet('admin/content');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->pageTextNotContains('Node (invalid)');
    $this->assertSession()->pageTextNotContains('Node (valid)');

    // Configure the policy.
    $this->drupalGet('admin/people/access-policies/invalid_rules');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->pageTextContainsOnce('Warning: invalid data detected');

    // It should be possible to configure it.
    $this->clickLink('Configure');
    $this->assertSession()->fieldExists('operations[view]');
    $this->assertSession()->fieldExists('admin_label');

    // Delete the invalid access rule.
    $this->drupalGet('/admin/people/access-policies/invalid_rules/handler/access_rule/field_text/remove');
    $this->submitForm([], 'Remove');
    $this->drupalGet('/admin/people/access-policies/invalid_rules');
    $this->assertSession()->pageTextNotContains('Warning: invalid data detected');
  }

  /**
   * Confirm that immutable operator access rules do not show the operator.
   */
  public function testCreateAccessRuleWithImmutableOperator() {
    $field_storage = FieldStorageConfig::create([
      'field_name' => 'field_user',
      'entity_type' => 'node',
      'type' => 'entity_reference',
      'cardinality' => -1,
      'settings' => [
        'target_type' => 'user',
      ],
    ]);
    $field_storage->save();

    $field = FieldConfig::create([
      'field_storage' => $field_storage,
      'field_name' => 'field_user',
      'bundle' => 'page',
      'translatable' => FALSE,
    ]);
    $field->save();

    $policy = AccessPolicy::create([
      'id' => 'basic_policy',
      'label' => 'Basic policy',
      'target_entity_type_id' => 'node',
    ]);
    $policy->save();

    $access_rule = $this->accessRuleManager->getHandler('node', 'field_user_user_reference');
    $policy->addHandler('access_rule', $access_rule);
    $policy->save();

    $rid = $this->drupalCreateRole([
      'access administration pages',
      'access content overview',
      'administer access policy entities',
    ]);
    $web_user = $this->drupalCreateUser();
    $web_user->addRole($rid);
    $web_user->save();

    $this->drupalLogin($web_user);

    $this->drupalGet('/admin/people/access-policies/basic_policy');
    $this->assertSession()->pageTextContains('field_user field has reference to current user');
    $this->clickLink('Configure');

    // Confirm that the operator field is not shown.
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->fieldNotExists('operator');
  }

  /**
   * Tests the field access permission setting on selection rules.
   */
  public function testCreateSelectionRuleWithFieldAccessPermission() {
    $policy = AccessPolicy::create([
      'id' => 'basic_policy',
      'label' => 'Basic policy',
      'target_entity_type_id' => 'node',
      'weight' => -10,
    ]);
    $policy->save();

    $selection_rule = $this->selectionRuleManager->getHandler('node', 'field_text');
    $selection_rule->setSettings([
      'operator' => 'not empty',
    ]);
    $policy->addHandler('selection_rule', $selection_rule);
    $policy->save();

    $rid = $this->drupalCreateRole([
      'access content',
      'access administration pages',
      'access content overview',
      'edit any page content',
      'create page content',
      'administer access policy entities',
      'assign basic_policy access policy',
      'view basic_policy content',
      'edit basic_policy content',
    ]);
    $admin_user = $this->drupalCreateUser();
    $admin_user->addRole($rid);
    $admin_user->save();

    $this->drupalLogin($admin_user);

    $this->drupalGet('/admin/people/access-policies/basic_policy/handler/selection_rule/field_text');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->pageTextContains('Field access');
    $this->assertSession()->fieldExists('field_access[type]');

    $edit = [
      'field_access[type]' => 'permission',
      'field_access[permission]' => 'assign basic_policy access policy',
    ];
    $this->submitForm($edit, 'Save');

    // Make sure it saved properly.
    $this->drupalGet('/admin/people/access-policies/basic_policy/selection');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->pageTextContains('Text (not empty)');

    $policy = $this->entityTypeManager->getStorage('access_policy')->load($policy->id());
    $rules = $policy->getHandlers('selection_rule');
    $rule_settings = $rules['field_text']['settings'];
    $this->assertEquals('permission', $rule_settings['field_access']['type']);
    $this->assertEquals('assign basic_policy access policy', $rule_settings['field_access']['permission']);

    // Assign the access policy to a node and edit it. Make sure that the field
    // is hidden.
    $node = $this->drupalCreateNode([
      'title' => 'Node',
      'type' => 'page',
      'status' => 1,
    ]);
    // Edit the node, confirm that they can see the field.
    $this->drupalGet('node/' . $node->id() . '/edit');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->fieldExists('field_text[0][value]');

    // Create a new node. They should be able to see the field.
    $this->drupalGet('node/add/page');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->fieldExists('field_text[0][value]');

    // This user can't assign the basic policy, therefore should not be able
    // to see the field.
    $web_user = $this->drupalCreateUser([
      'access content',
      'access administration pages',
      'access content overview',
      'edit any page content',
      'create page content',
    ]);

    $this->drupalLogin($web_user);

    // Edit the node, confirm that they can't see the field.
    $this->drupalGet('node/' . $node->id() . '/edit');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->fieldNotExists('field_text[0][value]');

    // Create a new node. They should not be able to see the field.
    $this->drupalGet('node/add/page');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->fieldNotExists('field_text[0][value]');

    // Create a new node that is assigned the Basic policy. Make sure that
    // It doesn't change the policy if another user without permission to
    // assign that policy edits it.
    $this->drupalLogin($admin_user);
    $node_2 = $this->drupalCreateNode([
      'title' => 'Node 2',
      'type' => 'page',
      'status' => 1,
      'field_text' => 'Foo bar',
    ]);
    $node_2 = $this->drupalGetNodeByTitle($node_2->label());
    $policy = $this->contentAccessPolicyManager->getAccessPolicy($node_2);
    $policy = reset($policy);
    $this->assertEquals('basic_policy', $policy->id());

    // This user can edit Basic policy content node but can't assign the Basic
    // policy. Make sure that it doesn't reset the policy.
    $web_user = $this->drupalCreateUser([
      'access content',
      'access administration pages',
      'access content overview',
      'edit any page content',
      'create page content',
      'edit basic_policy content',
    ]);
    $this->drupalLogin($web_user);

    $this->drupalGet('node/' . $node_2->id() . '/edit');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->fieldNotExists('field_text[0][value]');

    // Save the node, make sure that it doesn't change the policy.
    $edit = [
      'title[0][value]' => 'Node 2',
    ];
    $this->submitForm($edit, 'Save');

    $this->entityTypeManager->getStorage('node')->resetCache();
    $node = $this->drupalGetNodeByTitle('Node 2');
    $policy = $this->contentAccessPolicyManager->getAccessPolicy($node);
    $policy = reset($policy);
    $this->assertEquals('basic_policy', $policy->id(), 'This policy is incorrect');
  }

  /**
   * Tests viewing user profile with field observed by access rule.
   *
   * This tests multiple field types because some access rules use argument
   * settings to determine which field to observe.
   */
  public function testCreateAccessRuleUserFieldPermissions() {

    // Create a list field for user and node.
    FieldStorageConfig::create([
      'field_name' => 'field_list_string',
      'entity_type' => 'node',
      'type' => 'list_string',
      'cardinality' => 1,
      'settings' => [
        'allowed_values' => [
          'foo' => 'Foo',
          'bar' => 'Bar',
        ],
      ],
    ])->save();

    FieldConfig::create([
      'field_name' => 'field_list_string',
      'entity_type' => 'node',
      'label' => 'Test options list field',
      'bundle' => 'page',
    ])->save();

    FieldStorageConfig::create([
      'field_name' => 'field_list_string',
      'entity_type' => 'user',
      'type' => 'list_string',
      'cardinality' => 1,
      'settings' => [
        'allowed_values' => [
          'foo' => 'Foo',
          'bar' => 'Bar',
        ],
      ],
    ])->save();

    FieldConfig::create([
      'field_name' => 'field_list_string',
      'entity_type' => 'user',
      'label' => 'Test options list field',
      'bundle' => 'user',
    ])->save();

    FieldStorageConfig::create([
      'field_name' => 'field_boolean',
      'entity_type' => 'user',
      'type' => 'boolean',
    ])->save();

    FieldConfig::create([
      'field_name' => 'field_boolean',
      'entity_type' => 'user',
      'bundle' => 'user',
      'label' => "boolean",
      'required' => TRUE,
      'settings' => [
        'on_label' => 'On',
        'off_label' => 'Off',
      ],
    ])->save();

    // Add the new field to the edit form.
    EntityFormDisplay::create([
      'targetEntityType' => 'user',
      'bundle' => 'user',
      'mode' => 'default',
      'status' => TRUE,
    ])
      ->setComponent('field_boolean', [
        'type' => 'boolean_checkbox',
      ])
      ->setComponent('field_list_string', [
        'type' => 'options_select',
      ])
      ->save();

    $policy = AccessPolicy::create([
      'id' => 'basic_policy',
      'label' => 'Basic policy',
      'target_entity_type_id' => 'node',
    ]);
    $policy->save();

    $access_rule = $this->accessRuleManager->getHandler('user', 'field_boolean');
    $policy->addHandler('access_rule', $access_rule);

    $access_rule = $this->accessRuleManager->getHandler('node', 'match_field_list_string');
    $access_rule->setSettings([
      'operator' => 'in',
      'value' => ['field' => 'field_list_string'],
    ]);
    $policy->addHandler('access_rule', $access_rule);
    $policy->save();

    $web_user = $this->drupalCreateUser([
      'access administration pages',
      'access content overview',
      'administer access policy entities',
    ]);

    $this->drupalLogin($web_user);

    $this->drupalGet('/user/' . $web_user->id() . '/edit');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->fieldNotExists('field_list_string');
    $this->assertSession()->fieldNotExists('field_boolean');

    // Create a new user with the edit user information permission.
    $web_user = $this->drupalCreateUser([
      'access administration pages',
      'access content overview',
      'administer access policy entities',
      'edit basic_policy user information',
    ]);

    $this->drupalLogin($web_user);

    $this->drupalGet('/user/' . $web_user->id() . '/edit');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->fieldExists('field_list_string');
    $this->assertSession()->fieldNotExists('field_boolean');
  }

  /**
   * Tests filtering the allowed values in list fields.
   *
   * This tests filtering on list fields when the "Filer allowed values"
   * checkbox is checked. This only filters results for list text fields
   * that are being compared with user fields.
   */
  public function testFilterListFieldAllowedValues() {

    // Create a list field for user and node.
    FieldStorageConfig::create([
      'field_name' => 'field_list_string',
      'entity_type' => 'node',
      'type' => 'list_string',
      'cardinality' => 1,
      'settings' => [
        'allowed_values' => [
          'foo' => 'Foo',
          'bar' => 'Bar',
        ],
      ],
    ])->save();

    FieldConfig::create([
      'field_name' => 'field_list_string',
      'entity_type' => 'node',
      'label' => 'Test options list field',
      'bundle' => 'page',
    ])->save();

    FieldStorageConfig::create([
      'field_name' => 'field_list_string',
      'entity_type' => 'user',
      'type' => 'list_string',
      'cardinality' => 1,
      'settings' => [
        'allowed_values' => [
          'foo' => 'Foo',
          'bar' => 'Bar',
        ],
      ],
    ])->save();

    FieldConfig::create([
      'field_name' => 'field_list_string',
      'entity_type' => 'user',
      'label' => 'Test options list field',
      'bundle' => 'user',
    ])->save();

    $display = EntityFormDisplay::load('node.page.default');
    $display->setComponent('field_list_string', [
      'type' => 'options_select',
    ]);
    $display->save();

    $policy = AccessPolicy::create([
      'id' => 'basic_policy',
      'label' => 'Basic policy',
      'target_entity_type_id' => 'node',
    ]);
    $policy->save();

    $access_rule = $this->accessRuleManager->getHandler('node', 'match_field_list_string');
    $access_rule->setSettings([
      'operator' => 'in',
      'value' => ['field' => 'field_list_string'],
    ]);
    $policy->addHandler('access_rule', $access_rule);
    $policy->save();

    $permissions = [
      'access content',
      'access administration pages',
      'access content overview',
      'edit any page content',
      'create page content',
    ];
    $web_user = $this->drupalCreateUser(array_merge($permissions, [
      'administer access policy entities',
    ]));

    $web_user->set('field_list_string', ['bar']);
    $web_user->save();

    $this->drupalLogin($web_user);

    // Edit the access rule, confirm that the setting is visible.
    $this->drupalGet('/admin/people/access-policies/basic_policy/handler/access_rule/match_field_list_string');
    $this->assertSession()->fieldExists('filter_allowed_values');
    $this->assertSession()->checkboxNotChecked('filter_allowed_values');
    $submit = [
      'filter_allowed_values' => 1,
    ];
    $this->submitForm($submit, 'Save');
    $this->drupalGet('/admin/people/access-policies/basic_policy/handler/access_rule/match_field_list_string');
    $this->assertSession()->checkboxChecked('filter_allowed_values');

    $node = $this->drupalCreateNode([
      'title' => 'Node 1',
      'field_list_string' => 'bar',
    ]);

    // Log in as a user who doesn't have any values assigned to them. They
    // should not be able to choose an option.
    $web_user_2 = $this->drupalCreateUser($permissions);
    $this->drupalLogin($web_user_2);

    // Confirm that a new node does not show "bar".
    $this->drupalGet('/node/add/page');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->fieldExists('field_list_string');
    $this->assertSession()->fieldEnabled('field_list_string');
    $this->assertSession()->optionNotExists('field_list_string', 'foo');
    $this->assertSession()->optionNotExists('field_list_string', 'bar');

    // Log in as the other web user with a different list string value.
    $web_user_3 = $this->drupalCreateUser($permissions);
    $web_user_3->set('field_list_string', ['foo']);
    $web_user_3->save();

    $this->drupalLogin($web_user_3);

    $this->drupalGet('/node/add/page');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->fieldExists('field_list_string');
    $this->assertSession()->fieldEnabled('field_list_string');
    $this->assertSession()->optionExists('field_list_string', 'foo');
    $this->assertSession()->optionNotExists('field_list_string', 'bar');

    // Edit the existing node, confirm that the value is still there and that
    // the field is disabled.
    $this->drupalGet('node/' . $node->id() . '/edit');
    $this->assertSession()->fieldExists('field_list_string');
    $this->assertSession()->fieldDisabled('field_list_string');
    $this->assertSession()->fieldValueEquals('field_list_string', 'bar');

    // Log in as a user with bypass access rules permission and doesn't have any
    // values assigned for field_list_string. The field should still be enabled.
    $admin_user = $this->drupalCreateUser(array_merge($permissions, [
      'bypass basic_policy access rules',
    ]));

    $this->drupalLogin($admin_user);
    $this->drupalGet('node/' . $node->id() . '/edit');
    $this->assertSession()->fieldExists('field_list_string');
    $this->assertSession()->fieldEnabled('field_list_string');
    $this->assertSession()->fieldValueEquals('field_list_string', 'bar');

  }

}

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

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