Commit 4b298c30 authored by Kristiaan Van den Eynde's avatar Kristiaan Van den Eynde
Browse files

Issue #3285014 by kristiaanvandeneynde: Make sure only the requested scope can...

Issue #3285014 by kristiaanvandeneynde: Make sure only the requested scope can be returned by a calculator
parent 8e46a38f
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -12,9 +12,9 @@ interface CalculatedPermissionsInterface extends CacheableDependencyInterface {
  /**
   * Retrieves a single calculated permission item from a given scope.
   *
   * @param $scope
   * @param string $scope
   *   The scope name to retrieve the item for.
   * @param $identifier
   * @param string|int $identifier
   *   The scope identifier to retrieve the item for.
   *
   * @return \Drupal\flexible_permissions\CalculatedPermissionsItemInterface|false
@@ -30,6 +30,14 @@ interface CalculatedPermissionsInterface extends CacheableDependencyInterface {
   */
  public function getItems();

  /**
   * Retrieves all of the scopes that have items for them.
   *
   * @return string[]
   *   The scope names that are in use.
   */
  public function getScopes();

  /**
   * Retrieves all of the calculated permission items for the given scope.
   *
+9 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\flexible_permissions;

/**
 * An exception thrown when permissions are returned for the wrong scope.
 */
class CalculatedPermissionsScopeException extends \Exception {
}
+7 −0
Original line number Diff line number Diff line
@@ -36,6 +36,13 @@ trait CalculatedPermissionsTrait {
    return $items;
  }

  /**
   * {@inheritdoc}
   */
  public function getScopes() {
    return array_keys($this->items);
  }

  /**
   * {@inheritdoc}
   */
+11 −1
Original line number Diff line number Diff line
@@ -134,7 +134,17 @@ class ChainPermissionCalculator implements ChainPermissionCalculatorInterface {
    else {
      $calculated_permissions = new RefinableCalculatedPermissions();
      foreach ($this->getCalculators() as $calculator) {
        $calculated_permissions = $calculated_permissions->merge($calculator->calculatePermissions($account, $scope));
        $calculator_permissions = $calculator->calculatePermissions($account, $scope);
        $calculator_scopes = $calculator_permissions->getScopes();

        // Validate that only the requested scope was returned. An empty result
        // is allowed, however, as it might be that the calculator had nothing
        // to say for this scope.
        if (!empty($calculator_scopes) && (count($calculator_scopes) > 1 || reset($calculator_scopes) !== $scope)) {
          throw new CalculatedPermissionsScopeException(sprintf('The calculator "%s" returned permissions for scopes other than "%s".', get_class($calculator), $scope));
        }

        $calculated_permissions = $calculated_permissions->merge($calculator_permissions);
      }

      // Apply a cache tag to easily flush the calculated permissions.
+2 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ class CalculatedPermissionsTest extends UnitTestCase {
   * @covers ::__construct
   * @covers ::getItem
   * @covers ::getItems
   * @covers ::getScopes
   * @covers ::getItemsByScope
   */
  public function testConstructor() {
@@ -37,6 +38,7 @@ class CalculatedPermissionsTest extends UnitTestCase {
    $this->assertSame($item_a, $calculated_permissions->getItem('scope_a', 'foo'), 'Managed to retrieve the calculated permissions item by scope and identifier.');
    $this->assertFalse($calculated_permissions->getItem('scope_a', '404-id-not-found'), 'Requesting a non-existent identifier fails correctly.');
    $this->assertSame([$item_a, $item_b], $calculated_permissions->getItems(), 'Successfully retrieved all items regardless of scope.');
    $this->assertSame(['scope_a', 'scope_b'], $calculated_permissions->getScopes(), 'Successfully retrieved all scopes.');
    $this->assertSame([$item_a], $calculated_permissions->getItemsByScope('scope_a'), 'Successfully retrieved all items by scope.');

    $this->assertSame(['24'], $calculated_permissions->getCacheTags(), 'Successfully inherited all cache tags.');
Loading