diff core/modules/user/tests/src/Unit/UserAccessControlHandlerTest.php @ 0:4c8ae668cc8c

Initial import (non-working)
author Chris Cannam
date Wed, 29 Nov 2017 16:09:58 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/modules/user/tests/src/Unit/UserAccessControlHandlerTest.php	Wed Nov 29 16:09:58 2017 +0000
@@ -0,0 +1,418 @@
+<?php
+
+namespace Drupal\Tests\user\Unit;
+
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Cache\Context\CacheContextsManager;
+use Drupal\Core\DependencyInjection\Container;
+use Drupal\Tests\UnitTestCase;
+use Drupal\user\UserAccessControlHandler;
+
+/**
+ * Tests the user access controller.
+ *
+ * @group Drupal
+ * @group User
+ *
+ * @coversDefaultClass \Drupal\user\UserAccessControlHandler
+ */
+class UserAccessControlHandlerTest extends UnitTestCase {
+
+  /**
+   * The user access controller to test.
+   *
+   * @var \Drupal\user\UserAccessControlHandler
+   */
+  protected $accessControlHandler;
+
+  /**
+   * The mock user account with view access.
+   *
+   * @var \Drupal\Core\Session\AccountInterface
+   */
+  protected $viewer;
+
+  /**
+   * The mock user account that is able to change their own account name.
+   *
+   * @var \Drupal\Core\Session\AccountInterface
+   */
+  protected $owner;
+
+  /**
+   * The mock administrative test user.
+   *
+   * @var \Drupal\Core\Session\AccountInterface
+   */
+  protected $admin;
+
+  /**
+   * The mocked test field items.
+   *
+   * @var \Drupal\Core\Field\FieldItemList
+   */
+  protected $items;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $cache_contexts_manager = $this->prophesize(CacheContextsManager::class);
+    $cache_contexts_manager->assertValidTokens()->willReturn(TRUE);
+    $cache_contexts_manager->reveal();
+    $container = new Container();
+    $container->set('cache_contexts_manager', $cache_contexts_manager);
+    \Drupal::setContainer($container);
+
+    $this->viewer = $this->getMock('\Drupal\Core\Session\AccountInterface');
+    $this->viewer
+      ->expects($this->any())
+      ->method('hasPermission')
+      ->will($this->returnValue(FALSE));
+    $this->viewer
+      ->expects($this->any())
+      ->method('id')
+      ->will($this->returnValue(1));
+
+    $this->owner = $this->getMock('\Drupal\Core\Session\AccountInterface');
+    $this->owner
+      ->expects($this->any())
+      ->method('hasPermission')
+      ->will($this->returnValueMap([
+        ['administer users', FALSE],
+        ['change own username', TRUE],
+      ]));
+
+    $this->owner
+      ->expects($this->any())
+      ->method('id')
+      ->will($this->returnValue(2));
+
+    $this->admin = $this->getMock('\Drupal\Core\Session\AccountInterface');
+    $this->admin
+      ->expects($this->any())
+      ->method('hasPermission')
+      ->will($this->returnValue(TRUE));
+
+    $entity_type = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+
+    $this->accessControlHandler = new UserAccessControlHandler($entity_type);
+    $module_handler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
+    $module_handler->expects($this->any())
+      ->method('getImplementations')
+      ->will($this->returnValue([]));
+    $this->accessControlHandler->setModuleHandler($module_handler);
+
+    $this->items = $this->getMockBuilder('Drupal\Core\Field\FieldItemList')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $this->items
+      ->expects($this->any())
+      ->method('defaultAccess')
+      ->will($this->returnValue(AccessResult::allowed()));
+  }
+
+  /**
+   * Asserts correct field access grants for a field.
+   */
+  public function assertFieldAccess($field, $viewer, $target, $view, $edit) {
+    $field_definition = $this->getMock('Drupal\Core\Field\FieldDefinitionInterface');
+    $field_definition->expects($this->any())
+      ->method('getName')
+      ->will($this->returnValue($field));
+
+    $this->items
+      ->expects($this->any())
+      ->method('getEntity')
+      ->will($this->returnValue($this->{$target}));
+
+    foreach (['view' => $view, 'edit' => $edit] as $operation => $result) {
+      $result_text = !isset($result) ? 'null' : ($result ? 'true' : 'false');
+      $message = "User '$field' field access returns '$result_text' with operation '$operation' for '$viewer' accessing '$target'";
+      $this->assertSame($result, $this->accessControlHandler->fieldAccess($operation, $field_definition, $this->{$viewer}, $this->items), $message);
+    }
+  }
+
+  /**
+   * Ensures user name access is working properly.
+   *
+   * @dataProvider userNameProvider
+   */
+  public function testUserNameAccess($viewer, $target, $view, $edit) {
+    $this->assertFieldAccess('name', $viewer, $target, $view, $edit);
+  }
+
+  /**
+   * Provides test data for testUserNameAccess().
+   */
+  public function userNameProvider() {
+    $name_access = [
+      // The viewer user is allowed to see user names on all accounts.
+      [
+        'viewer' => 'viewer',
+        'target' => 'viewer',
+        'view' => TRUE,
+        'edit' => FALSE,
+      ],
+      [
+        'viewer' => 'owner',
+        'target' => 'viewer',
+        'view' => TRUE,
+        'edit' => FALSE,
+      ],
+      [
+        'viewer' => 'viewer',
+        'target' => 'owner',
+        'view' => TRUE,
+        'edit' => FALSE,
+      ],
+      // The owner user is allowed to change its own user name.
+      [
+        'viewer' => 'owner',
+        'target' => 'owner',
+        'view' => TRUE,
+        'edit' => TRUE,
+      ],
+      // The users-administrator user has full access.
+      [
+        'viewer' => 'admin',
+        'target' => 'owner',
+        'view' => TRUE,
+        'edit' => TRUE,
+      ],
+    ];
+    return $name_access;
+  }
+
+  /**
+   * Tests that private user settings cannot be viewed by other users.
+   *
+   * @dataProvider hiddenUserSettingsProvider
+   */
+  public function testHiddenUserSettings($field, $viewer, $target, $view, $edit) {
+    $this->assertFieldAccess($field, $viewer, $target, $view, $edit);
+  }
+
+  /**
+   * Provides test data for testHiddenUserSettings().
+   */
+  public function hiddenUserSettingsProvider() {
+    $access_info = [];
+
+    $fields = [
+      'preferred_langcode',
+      'preferred_admin_langcode',
+      'timezone',
+      'mail',
+    ];
+
+    foreach ($fields as $field) {
+      $access_info[] = [
+        'field' => $field,
+        'viewer' => 'viewer',
+        'target' => 'viewer',
+        'view' => TRUE,
+        'edit' => TRUE,
+      ];
+      $access_info[] = [
+        'field' => $field,
+        'viewer' => 'viewer',
+        'target' => 'owner',
+        'view' => FALSE,
+        // Anyone with edit access to the user can also edit these fields. In
+        // reality edit access will already be checked on entity level and the
+        // user without view access will typically not be able to edit.
+        'edit' => TRUE,
+      ];
+      $access_info[] = [
+        'field' => $field,
+        'viewer' => 'owner',
+        'target' => 'owner',
+        'view' => TRUE,
+        'edit' => TRUE,
+      ];
+      $access_info[] = [
+        'field' => $field,
+        'viewer' => 'admin',
+        'target' => 'owner',
+        'view' => TRUE,
+        'edit' => TRUE,
+      ];
+    }
+
+    return $access_info;
+  }
+
+  /**
+   * Tests that private user settings cannot be viewed by other users.
+   *
+   * @dataProvider adminFieldAccessProvider
+   */
+  public function testAdminFieldAccess($field, $viewer, $target, $view, $edit) {
+    $this->assertFieldAccess($field, $viewer, $target, $view, $edit);
+  }
+
+  /**
+   * Provides test data for testAdminFieldAccess().
+   */
+  public function adminFieldAccessProvider() {
+    $access_info = [];
+
+    $fields = [
+      'roles',
+      'status',
+      'access',
+      'login',
+      'init',
+    ];
+
+    foreach ($fields as $field) {
+      $access_info[] = [
+        'field' => $field,
+        'viewer' => 'viewer',
+        'target' => 'viewer',
+        'view' => FALSE,
+        'edit' => FALSE,
+      ];
+      $access_info[] = [
+        'field' => $field,
+        'viewer' => 'viewer',
+        'target' => 'owner',
+        'view' => FALSE,
+        'edit' => FALSE,
+      ];
+      $access_info[] = [
+        'field' => $field,
+        'viewer' => 'admin',
+        'target' => 'owner',
+        'view' => TRUE,
+        'edit' => TRUE,
+      ];
+    }
+
+    return $access_info;
+  }
+
+  /**
+   * Tests that passwords cannot be viewed, just edited.
+   *
+   * @dataProvider passwordAccessProvider
+   */
+  public function testPasswordAccess($viewer, $target, $view, $edit) {
+    $this->assertFieldAccess('pass', $viewer, $target, $view, $edit);
+  }
+
+  /**
+   * Provides test data for passwordAccessProvider().
+   */
+  public function passwordAccessProvider() {
+    $pass_access = [
+      [
+        'viewer' => 'viewer',
+        'target' => 'viewer',
+        'view' => FALSE,
+        'edit' => TRUE,
+      ],
+      [
+        'viewer' => 'viewer',
+        'target' => 'owner',
+        'view' => FALSE,
+        // Anyone with edit access to the user can also edit these fields. In
+        // reality edit access will already be checked on entity level and the
+        // user without view access will typically not be able to edit.
+        'edit' => TRUE,
+      ],
+      [
+        'viewer' => 'owner',
+        'target' => 'viewer',
+        'view' => FALSE,
+        'edit' => TRUE,
+      ],
+      [
+        'viewer' => 'admin',
+        'target' => 'owner',
+        'view' => FALSE,
+        'edit' => TRUE,
+      ],
+    ];
+    return $pass_access;
+  }
+
+  /**
+   * Tests the user created field access.
+   *
+   * @dataProvider createdAccessProvider
+   */
+  public function testCreatedAccess($viewer, $target, $view, $edit) {
+    $this->assertFieldAccess('created', $viewer, $target, $view, $edit);
+  }
+
+  /**
+   * Provides test data for testCreatedAccess().
+   */
+  public function createdAccessProvider() {
+    $created_access = [
+      [
+        'viewer' => 'viewer',
+        'target' => 'viewer',
+        'view' => TRUE,
+        'edit' => FALSE,
+      ],
+      [
+        'viewer' => 'owner',
+        'target' => 'viewer',
+        'view' => TRUE,
+        'edit' => FALSE,
+      ],
+      [
+        'viewer' => 'admin',
+        'target' => 'owner',
+        'view' => TRUE,
+        'edit' => TRUE,
+      ],
+    ];
+    return $created_access;
+  }
+
+  /**
+   * Tests access to a non-existing base field.
+   *
+   * @dataProvider NonExistingFieldAccessProvider
+   */
+  public function testNonExistingFieldAccess($viewer, $target, $view, $edit) {
+    // By default everyone has access to all fields that do not have explicit
+    // access control.
+    // @see EntityAccessControlHandler::checkFieldAccess()
+    $this->assertFieldAccess('some_non_existing_field', $viewer, $target, $view, $edit);
+  }
+
+  /**
+   * Provides test data for testNonExistingFieldAccess().
+   */
+  public function NonExistingFieldAccessProvider() {
+    $created_access = [
+      [
+        'viewer' => 'viewer',
+        'target' => 'viewer',
+        'view' => TRUE,
+        'edit' => TRUE,
+      ],
+      [
+        'viewer' => 'owner',
+        'target' => 'viewer',
+        'view' => TRUE,
+        'edit' => TRUE,
+      ],
+      [
+        'viewer' => 'admin',
+        'target' => 'owner',
+        'view' => TRUE,
+        'edit' => TRUE,
+      ],
+    ];
+    return $created_access;
+  }
+
+}