You are here

ViewsAccess.php in Security Review 8

File

src/Checks/ViewsAccess.php
View source
<?php

namespace Drupal\security_review\Checks;

use Drupal\Core\Link;
use Drupal\security_review\Check;
use Drupal\security_review\CheckResult;
use Drupal\views\Entity\View;

/**
 * Checks for Views that do not check access.
 */
class ViewsAccess extends Check {

  /**
   * {@inheritdoc}
   */
  public function getNamespace() {
    return 'Security Review';
  }

  /**
   * {@inheritdoc}
   */
  public function getTitle() {
    return 'Views access';
  }

  /**
   * {@inheritdoc}
   */
  public function run() {

    // If views is not enabled return with INFO.
    if (!$this
      ->moduleHandler()
      ->moduleExists('views')) {
      return $this
        ->createResult(CheckResult::INFO);
    }
    $result = CheckResult::SUCCESS;
    $findings = [];
    $views = View::loadMultiple();

    /** @var View[] $views */

    // Iterate through views and their displays.
    foreach ($views as $view) {
      if ($view
        ->status()) {
        foreach ($view
          ->get('display') as $display_name => $display) {
          $access =& $display['display_options']['access'];
          if (isset($access) && $access['type'] == 'none') {

            // Access is not controlled for this display.
            $findings[$view
              ->id()][] = $display_name;
          }
        }
      }
    }
    if (!empty($findings)) {
      $result = CheckResult::FAIL;
    }
    return $this
      ->createResult($result, $findings);
  }

  /**
   * {@inheritdoc}
   */
  public function help() {
    $paragraphs = [];
    $paragraphs[] = $this
      ->t("Views can check if the user is allowed access to the content. It is recommended that all Views implement some amount of access control, at a minimum checking for the permission 'access content'.");
    return [
      '#theme' => 'check_help',
      '#title' => $this
        ->t('Views access'),
      '#paragraphs' => $paragraphs,
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function evaluate(CheckResult $result) {
    $findings = $result
      ->findings();
    if (empty($findings)) {
      return [];
    }
    $paragraphs = [];
    $paragraphs[] = $this
      ->t('The following View displays do not check access.');
    $items = [];
    foreach ($findings as $view_id => $displays) {
      $view = View::load($view_id);

      /** @var View $view */
      foreach ($displays as $display) {
        $items[] = Link::createFromRoute($view
          ->label() . ': ' . $display, 'entity.view.edit_display_form', [
          'view' => $view_id,
          'display_id' => $display,
        ]);
      }
    }
    return [
      '#theme' => 'check_evaluation',
      '#paragraphs' => $paragraphs,
      '#items' => $items,
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function evaluatePlain(CheckResult $result) {
    $findings = $result
      ->findings();
    if (empty($findings)) {
      return '';
    }
    $output = $this
      ->t('Views without access check:') . ":\n";
    foreach ($findings as $view_id => $displays) {
      $output .= "\t" . $view_id . ": " . implode(', ', $displays) . "\n";
    }
    return $output;
  }

  /**
   * {@inheritdoc}
   */
  public function getMessage($result_const) {
    switch ($result_const) {
      case CheckResult::SUCCESS:
        return $this
          ->t('Views are access controlled.');
      case CheckResult::FAIL:
        return $this
          ->t('There are Views that do not provide any access checks.');
      case CheckResult::INFO:
        return $this
          ->t('Module views is not enabled.');
      default:
        return $this
          ->t('Unexpected result.');
    }
  }

}

Classes

Namesort descending Description
ViewsAccess Checks for Views that do not check access.