Verified Commit 420765cf authored by godotislate's avatar godotislate
Browse files

fix: #3285176 Warning message links to "available updates" even if user does...

fix: #3285176 Warning message links to "available updates" even if user does not have permission for that page

By: benjifisher
By: dww
By: smustgrave
By: feyp
By: larowlan
By: ravi.shankar
By: acbramley
By: godotislate
By: aaronmchale
By: andregp
By: rkoller
By: shaal
By: simohell
By: worldlinemine
(cherry picked from commit f5b6b5ef)
parent 667a2f53
Loading
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -201,7 +201,7 @@ public function mail($key, &$message, $params): void {
    $language = \Drupal::languageManager()->getLanguage($langcode);
    $message['subject'] .= $this->t('New release(s) available for @site_name', ['@site_name' => \Drupal::config('system.site')->get('name')], ['langcode' => $langcode]);
    foreach ($params as $msg_type => $msg_reason) {
      $message['body'][] = _update_message_text($msg_type, $msg_reason, $langcode);
      $message['body'][] = _update_message_text($msg_type, $msg_reason, $langcode, TRUE);
    }
    $message['body'][] = $this->t('See the available updates page for more information:',
      [],
+11 −10
Original line number Diff line number Diff line
@@ -115,9 +115,6 @@ protected function requirementCheck($project, $type): array {
    if ($status != UpdateManagerInterface::CURRENT) {
      $requirement['reason'] = $status;
      $requirement['severity'] = RequirementSeverity::Error;
      // When updates are available, append the available updates link to the
      // message from _update_message_text(), and format the two translated
      // strings together in a single paragraph.
      $requirement['description'][] = ['#markup' => _update_message_text($type, $status)];
      if (!in_array($status, [
        UpdateFetcherInterface::UNKNOWN,
@@ -125,15 +122,19 @@ protected function requirementCheck($project, $type): array {
        UpdateFetcherInterface::NOT_FETCHED,
        UpdateFetcherInterface::FETCH_PENDING,
      ])) {
        $url = Url::fromRoute('update.status');
        // When updates are available, if the current user has access to the
        // available updates report, append the available updates link to the
        // message from _update_message_text(), and format the two translated
        // strings together in a single paragraph.
        if ($url->access()) {
          $requirement['description'][] = [
            '#prefix' => ' ',
          '#markup' => $this->t('See the <a href=":available_updates">available updates</a> page for more information.', [
            ':available_updates' => Url::fromRoute('update.status')
              ->toString(),
          ]),
            '#markup' => $this->t('See the <a href=":available_updates">available updates</a> page for more information.', [':available_updates' => $url->toString()]),
          ];
        }
      }
    }
    switch ($status) {
      case UpdateManagerInterface::NOT_SECURE:
        $requirement_label = $this->t('Not secure!');
+47 −0
Original line number Diff line number Diff line
@@ -115,6 +115,53 @@ public function testBrokenThenFixedUpdates(): void {
    $this->assertSession()->pageTextContains('There is a security update available for your version of Drupal.');
  }

  /**
   * Tests the available link appears to users with the right permissions.
   */
  public function testAvailableUpdateLink(): void {
    // Test that a user with the correct permissions is shown the available
    // updates link.
    $this->drupalLogin($this->drupalCreateUser([
      'administer site configuration',
      'view update notifications',
      'administer themes',
      'access administration pages',
    ]));

    $this->setProjectInstalledVersion('8.0.0');
    // Instead of using refreshUpdateStatus(), set these manually.
    $this->config('update.settings')
      ->set('fetch.url', Url::fromRoute('update_test.update_test')
        ->setAbsolute()
        ->toString())
      ->save();
    // Use update XML that has no information to simulate a broken response from
    // the update server.
    $this->config('update_test.settings')
      ->set('xml_map', ['drupal' => 'broken'])
      ->save();

    // This will retrieve broken updates.
    $this->cronRun();

    $this->drupalGet('admin/appearance');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->linkExists('available updates');

    // Test that a user without the correct permissions is not shown the
    // available updates link.
    $this->drupalLogin($this->drupalCreateUser([
      'view update notifications',
      'administer themes',
      'access administration pages',
    ]));

    $this->drupalGet('admin/appearance');
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->linkNotExists('available updates');
    $this->assertSession()->pageTextContains('available updates');
  }

  /**
   * Tests when a dev release does not have a date.
   */
+22 −3
Original line number Diff line number Diff line
@@ -167,11 +167,16 @@ function update_fetch_data_finished($success, $results): void {
 *   Integer constant specifying why message is generated.
 * @param string $langcode
 *   (optional) A language code to use. Defaults to NULL.
 * @param bool $is_email
 *   (optional) Controls if this function is used for generating mail. If TRUE,
 *   URLs will be absolute and will be included without access checks. If FALSE,
 *   links will be relative and will only be included if the current user can
 *   access them. Defaults to FALSE.
 *
 * @return \Drupal\Core\StringTranslation\TranslatableMarkup
 *   The properly translated error message for the given key.
 */
function _update_message_text($msg_type, $msg_reason, $langcode = NULL) {
function _update_message_text($msg_type, $msg_reason, $langcode = NULL, bool $is_email = FALSE) {
  $text = '';
  switch ($msg_reason) {
    case UpdateManagerInterface::NOT_SECURE:
@@ -214,11 +219,25 @@ function _update_message_text($msg_type, $msg_reason, $langcode = NULL) {
    case UpdateFetcherInterface::NOT_CHECKED:
    case UpdateFetcherInterface::NOT_FETCHED:
    case UpdateFetcherInterface::FETCH_PENDING:
      $url = Url::fromRoute('update.status', [], [
        'absolute' => $is_email,
        'language' => $langcode,
      ]);
      if ($msg_type == 'core') {
        $text = t('There was a problem checking <a href=":update-report">available updates</a> for Drupal.', [':update-report' => Url::fromRoute('update.status')->toString()], ['langcode' => $langcode]);
        if ($url->access() || $is_email) {
          return t('There was a problem checking <a href=":update-report">available updates</a> for Drupal.', [
            ':update-report' => $url->toString(),
          ], ['langcode' => $langcode]);
        }
        return t('There was a problem checking available updates for Drupal.', [], ['langcode' => $langcode]);
      }
      else {
        $text = t('There was a problem checking <a href=":update-report">available updates</a> for your modules or themes.', [':update-report' => Url::fromRoute('update.status')->toString()], ['langcode' => $langcode]);
        if ($url->access() || $is_email) {
          return t('There was a problem checking <a href=":update-report">available updates</a> for your modules or themes.', [
            ':update-report' => $url->toString(),
          ], ['langcode' => $langcode]);
        }
        return t('There was a problem checking available updates for Drupal.', [], ['langcode' => $langcode]);
      }
      break;
  }