diff --git a/core/modules/update/css/update.admin.theme.css b/core/modules/update/css/update.admin.theme.css index abf0a88243..27da7735a7 100644 --- a/core/modules/update/css/update.admin.theme.css +++ b/core/modules/update/css/update.admin.theme.css @@ -8,10 +8,12 @@ font-size: 110%; } .project-update__status { + text-align: right; /* LTR */ float: right; /* LTR */ font-size: 110%; } [dir="rtl"] .project-update__status { + text-align: left; float: left; } .project-update__status--not-supported { @@ -32,12 +34,22 @@ padding-left: 0; padding-right: 0.5em; } +.project-update__status-icon img { + vertical-align: top; +} .project-update__details { padding: 1em 1em 0.25em 1em; } .project-update__version { - padding: 1em 0; + border-top: 1px solid #bfbfbf; + padding: 0.5em 0; +} +.project-update__version:last-child { + padding-bottom: 0; +} +.project-update__version--installed { + border-top: none; } .project-update__version-date { white-space: nowrap; @@ -51,12 +63,10 @@ } .project-update__version-links { text-align: right; /* LTR */ - padding-right: 1em; /* LTR */ list-style-type: none; } [dir="rtl"] .project-update__version-links { text-align: left; - padding-left: 1em; } .project-update__version--recommended-strong .project-update__version-title { font-weight: bold; diff --git a/core/modules/update/src/Tests/UpdateContribTest.php b/core/modules/update/src/Tests/UpdateContribTest.php index 81f7117a3a..83b0cbe56c 100644 --- a/core/modules/update/src/Tests/UpdateContribTest.php +++ b/core/modules/update/src/Tests/UpdateContribTest.php @@ -84,6 +84,8 @@ public function testUpdateContribBasic() { $this->assertRaw('

' . t('Modules') . '

'); $this->assertNoText(t('Update available')); $this->assertRaw($project_link, 'Link to aaa_update_test project appears.'); + // Check for security advisory coverage information. + $this->assertText(t('AAA is not covered!')); // Since aaa_update_test is installed the fact it is hidden and in the // Testing package means it should not appear. @@ -176,8 +178,8 @@ public function testUpdateContribOrder() { // Instead of just searching for 'BBB Update test' or something, we want // to use the full markup that starts the project entry itself, so that // we're really testing that the project listings are in the right order. - $bbb_project_link = '
BBB Update test'; - $ccc_project_link = '
CCC Update test'; + $bbb_project_link = '
BBB Update test'; + $ccc_project_link = '
CCC Update test'; $this->assertTrue(strpos($this->getRawContent(), $bbb_project_link) < strpos($this->getRawContent(), $ccc_project_link), "'BBB Update test' project is listed before the 'CCC Update test' project"); } @@ -375,7 +377,7 @@ public function testUpdateBrokenFetchURL() { // The other two should be listed as projects. $this->assertRaw(\Drupal::l(t('AAA Update test'), Url::fromUri('http://example.com/project/aaa_update_test')), 'Link to aaa_update_test project appears.'); $this->assertNoRaw(\Drupal::l(t('BBB Update test'), Url::fromUri('http://example.com/project/bbb_update_test')), 'Link to bbb_update_test project does not appear.'); - $this->assertRaw(\Drupal::l(t('CCC Update test'), Url::fromUri('http://example.com/project/ccc_update_test')), 'Link to bbb_update_test project appears.'); + $this->assertRaw(\Drupal::l(t('CCC Update test'), Url::fromUri('http://example.com/project/ccc_update_test')), 'Link to ccc_update_test project appears.'); } /** diff --git a/core/modules/update/src/UpdateProcessor.php b/core/modules/update/src/UpdateProcessor.php index 25dfc7a004..9115357274 100644 --- a/core/modules/update/src/UpdateProcessor.php +++ b/core/modules/update/src/UpdateProcessor.php @@ -231,6 +231,9 @@ protected function parseXml($raw_xml) { foreach ($release->children() as $k => $v) { $data['releases'][$version][$k] = (string) $v; } + if ($release->security['covered']) { + $data['releases'][$version]['security_covered'] = TRUE; + } $data['releases'][$version]['terms'] = []; if ($release->terms) { foreach ($release->terms->children() as $term) { diff --git a/core/modules/update/templates/update-project-status.html.twig b/core/modules/update/templates/update-project-status.html.twig index 4cc9a19e8b..402bb77600 100644 --- a/core/modules/update/templates/update-project-status.html.twig +++ b/core/modules/update/templates/update-project-status.html.twig @@ -47,24 +47,14 @@
-
+
{%- if url -%} {{ title }} {%- else -%} {{ title }} {%- endif %} - {{ existing_version }} - {% if install_type == 'dev' and datestamp %} - ({{ datestamp }}) - {% endif %}
-{% if versions %} - {% for version in versions %} - {{ version }} - {% endfor %} -{% endif %} - {% set extra_classes = [ project.status == constant('UPDATE_NOT_SECURE') ? 'project-not-secure', @@ -104,3 +94,9 @@ {% endtrans %} {% endif %}
+ +{% if versions %} + {% for version in versions %} + {{ version }} + {% endfor %} +{% endif %} diff --git a/core/modules/update/templates/update-report.html.twig b/core/modules/update/templates/update-report.html.twig index ae121cc3b4..25ccc45238 100644 --- a/core/modules/update/templates/update-report.html.twig +++ b/core/modules/update/templates/update-report.html.twig @@ -19,7 +19,7 @@ {% for project_type in project_types %}

{{ project_type.label }}

- {{ project_type.table }} + {{ project_type.content }} {% else %}

{{ no_updates_message }}

{% endfor %} diff --git a/core/modules/update/templates/update-version.html.twig b/core/modules/update/templates/update-version.html.twig index c21c4f0ba4..25dbcce4c0 100644 --- a/core/modules/update/templates/update-version.html.twig +++ b/core/modules/update/templates/update-version.html.twig @@ -17,20 +17,24 @@ #}
-
{{ title }}
-
+
{{ title }}
+
{{ version.version }} ({{ version.date|date('Y-M-d') }}) + {% if version.security_covered %} + {% trans %} + Covered by Drupal’s security advisory policy + {% endtrans %} + {% endif %}
- + {% if attributes.class != 'project-update__version--installed' %} +
+ +
+ {% endif %}
diff --git a/core/modules/update/tests/modules/update_test/aaa_update_test.1_0.xml b/core/modules/update/tests/modules/update_test/aaa_update_test.1_0.xml index 82362fe846..9405cb3e38 100644 --- a/core/modules/update/tests/modules/update_test/aaa_update_test.1_0.xml +++ b/core/modules/update/tests/modules/update_test/aaa_update_test.1_0.xml @@ -29,6 +29,7 @@ Release typeNew features Release typeBug fixes + AAA is not covered! diff --git a/core/modules/update/tests/modules/update_test/bbb_update_test.1_0.xml b/core/modules/update/tests/modules/update_test/bbb_update_test.1_0.xml index 8d705b5f96..2142c04efa 100644 --- a/core/modules/update/tests/modules/update_test/bbb_update_test.1_0.xml +++ b/core/modules/update/tests/modules/update_test/bbb_update_test.1_0.xml @@ -16,11 +16,11 @@ bbb_update_test 8.x-1.0 8.x-1.0 - DRUPAL-7--1-0 + 8.x-1.0 1 0 published - http://example.com/bbb_update_test-7-x-1-0-release + http://example.com/bbb_update_test-8-x-1-0-release http://example.com/bbb_update_test-8.x-1.0.tar.gz 1250424521 b966255555d9c9b86d480ca08cfaa98e @@ -29,6 +29,26 @@ Release typeNew features Release typeBug fixes + + + + bbb_update_test 8.x-1.0-beta1 + 8.x-1.0-beta1 + 8.x-1.0-beta1 + 1 + 0 + beta1 + published + http://example.com/bbb_update_test-8-x-1-0-beta1 + http://example.com/bbb_update_test-8.x-1.0-beta1.tar.gz + 1250424521 + 7da7b18ce17cef2122f5cbca1bfe626a + 1073751331 + + Release typeNew features + Release typeBug fixes + + Not covered! diff --git a/core/modules/update/tests/modules/update_test/ccc_update_test.1_0.xml b/core/modules/update/tests/modules/update_test/ccc_update_test.1_0.xml index 82764c2c33..35e1f5f4ca 100644 --- a/core/modules/update/tests/modules/update_test/ccc_update_test.1_0.xml +++ b/core/modules/update/tests/modules/update_test/ccc_update_test.1_0.xml @@ -29,6 +29,7 @@ Release typeNew features Release typeBug fixes + diff --git a/core/modules/update/update.compare.inc b/core/modules/update/update.compare.inc index 2ba5fdce75..c8be5c325c 100644 --- a/core/modules/update/update.compare.inc +++ b/core/modules/update/update.compare.inc @@ -177,6 +177,10 @@ function update_calculate_project_update_status(&$project_data, $available) { } } + // For dev releases, existing_version looks like '8.4.0-dev', while + // updates.drupal.org provides '8.4.x-dev'. + $project_data['version_normalized'] = preg_replace('/0-dev$/', 'x-dev', $project_data['existing_version']); + // If the project status is marked as something bad, there's nothing else // to consider. if (isset($available['project_status'])) { diff --git a/core/modules/update/update.install b/core/modules/update/update.install index c616412ac4..da2ec2a484 100644 --- a/core/modules/update/update.install +++ b/core/modules/update/update.install @@ -5,6 +5,8 @@ * Install, update, and uninstall functions for the Update Manager module. */ +use Drupal\Core\Site\Settings; +use Drupal\Core\Link; use Drupal\Core\Url; /** @@ -33,8 +35,29 @@ function update_requirements($phase) { if ($available = update_get_available(FALSE)) { module_load_include('inc', 'update', 'update.compare'); $data = update_calculate_project_data($available); - // First, populate the requirements for core: + + if (Settings::get('update_warn_drupalorg_security', TRUE)) { + // Check if all projects have security advisory coverage. + $requirements['update_covered'] = [ + 'title' => t('Drupal.org security advisory coverage'), + 'value' => t('Currently installed modules and themes from Drupal.org receive coverage.'), + 'description' => t('Learn more about Drupal.org security advisory coverage.'), + ]; + foreach ($data as $project) { + // 'security_covered' boolean makes a positive assertion of coverage. + // 'security' string confirms there is no coverage. Check both so + // non-www.drupal.org projects are not false positives. + if (isset($project['releases'][$project['version_normalized']]) && empty($project['releases'][$project['version_normalized']]['security_covered']) && !empty($project['releases'][$project['version_normalized']]['security'])) { + $requirements['update_covered']['value'] = Link::createFromRoute(t('Modules and themes without security advisory coverage found'), 'update.status'); + $requirements['update_covered']['severity'] = REQUIREMENT_WARNING; + break; + } + } + } + + // Populate the requirements for core: $requirements['update_core'] = _update_requirement_check($data['drupal'], 'core'); + // We don't want to check drupal a second time. unset($data['drupal']); if (!empty($data)) { diff --git a/core/modules/update/update.report.inc b/core/modules/update/update.report.inc index 7b14a05852..8bd2d192ac 100644 --- a/core/modules/update/update.report.inc +++ b/core/modules/update/update.report.inc @@ -6,6 +6,7 @@ */ use Drupal\Component\Utility\Unicode; +use Drupal\Core\Site\Settings; use Drupal\Core\Template\Attribute; use Drupal\Core\Url; @@ -39,45 +40,18 @@ function template_preprocess_update_report(&$variables) { $variables['no_updates_message'] = _update_no_data(); } - $rows = []; - + $projects = []; foreach ($data as $project) { - $project_status = [ - '#theme' => 'update_project_status', - '#project' => $project, + // Add the project status and details. + $projects[$project['project_type']][Unicode::strtolower(!empty($project['title']) ? $project['title'] : $project['name'])] = [ + '#theme' => 'admin_block', + '#block' => [ + 'content' => [ + '#theme' => 'update_project_status', + '#project' => $project, + ], + ], ]; - - // Build project rows. - if (!isset($rows[$project['project_type']])) { - $rows[$project['project_type']] = [ - '#type' => 'table', - '#attributes' => ['class' => ['update']], - ]; - } - $row_key = !empty($project['title']) ? Unicode::strtolower($project['title']) : Unicode::strtolower($project['name']); - - // Add the project status row and details. - $rows[$project['project_type']][$row_key]['status'] = $project_status; - - // Add project status class attribute to the table row. - switch ($project['status']) { - case UPDATE_CURRENT: - $rows[$project['project_type']][$row_key]['#attributes'] = ['class' => ['color-success']]; - break; - case UPDATE_UNKNOWN: - case UPDATE_FETCH_PENDING: - case UPDATE_NOT_FETCHED: - case UPDATE_NOT_SECURE: - case UPDATE_REVOKED: - case UPDATE_NOT_SUPPORTED: - $rows[$project['project_type']][$row_key]['#attributes'] = ['class' => ['color-error']]; - break; - case UPDATE_NOT_CHECKED: - case UPDATE_NOT_CURRENT: - default: - $rows[$project['project_type']][$row_key]['#attributes'] = ['class' => ['color-warning']]; - break; - } } $project_types = [ @@ -90,11 +64,11 @@ function template_preprocess_update_report(&$variables) { $variables['project_types'] = []; foreach ($project_types as $type_name => $type_label) { - if (!empty($rows[$type_name])) { - ksort($rows[$type_name]); + if (!empty($projects[$type_name])) { + ksort($projects[$type_name]); $variables['project_types'][] = [ 'label' => $type_label, - 'table' => $rows[$type_name], + 'content' => $projects[$type_name], ]; } } @@ -127,6 +101,14 @@ function template_preprocess_update_project_status(&$variables) { $versions_inner = []; $security_class = []; $version_class = []; + if (isset($project['releases'][$project['version_normalized']])) { + $versions_inner[] = [ + '#theme' => 'update_version', + '#version' => $project['releases'][$project['version_normalized']], + '#title' => t('Installed version:'), + '#attributes' => ['class' => ['project-update__version--installed']], + ]; + } if (isset($project['recommended'])) { if ($project['status'] != UPDATE_CURRENT || $project['existing_version'] !== $project['recommended']) { diff --git a/core/themes/stable/css/update/update.admin.theme.css b/core/themes/stable/css/update/update.admin.theme.css index abf0a88243..27da7735a7 100644 --- a/core/themes/stable/css/update/update.admin.theme.css +++ b/core/themes/stable/css/update/update.admin.theme.css @@ -8,10 +8,12 @@ font-size: 110%; } .project-update__status { + text-align: right; /* LTR */ float: right; /* LTR */ font-size: 110%; } [dir="rtl"] .project-update__status { + text-align: left; float: left; } .project-update__status--not-supported { @@ -32,12 +34,22 @@ padding-left: 0; padding-right: 0.5em; } +.project-update__status-icon img { + vertical-align: top; +} .project-update__details { padding: 1em 1em 0.25em 1em; } .project-update__version { - padding: 1em 0; + border-top: 1px solid #bfbfbf; + padding: 0.5em 0; +} +.project-update__version:last-child { + padding-bottom: 0; +} +.project-update__version--installed { + border-top: none; } .project-update__version-date { white-space: nowrap; @@ -51,12 +63,10 @@ } .project-update__version-links { text-align: right; /* LTR */ - padding-right: 1em; /* LTR */ list-style-type: none; } [dir="rtl"] .project-update__version-links { text-align: left; - padding-left: 1em; } .project-update__version--recommended-strong .project-update__version-title { font-weight: bold; diff --git a/core/themes/stable/templates/admin/update-project-status.html.twig b/core/themes/stable/templates/admin/update-project-status.html.twig index 5a6d2ecea7..780d8557c2 100644 --- a/core/themes/stable/templates/admin/update-project-status.html.twig +++ b/core/themes/stable/templates/admin/update-project-status.html.twig @@ -45,24 +45,14 @@
-
+
{%- if url -%} {{ title }} {%- else -%} {{ title }} {%- endif %} - {{ existing_version }} - {% if install_type == 'dev' and datestamp %} - ({{ datestamp }}) - {% endif %}
-{% if versions %} - {% for version in versions %} - {{ version }} - {% endfor %} -{% endif %} - {% set extra_classes = [ project.status == constant('UPDATE_NOT_SECURE') ? 'project-not-secure', @@ -102,3 +92,9 @@ {% endtrans %} {% endif %}
+ +{% if versions %} + {% for version in versions %} + {{ version }} + {% endfor %} +{% endif %} diff --git a/core/themes/stable/templates/admin/update-report.html.twig b/core/themes/stable/templates/admin/update-report.html.twig index 9efebc06ae..648d31ea98 100644 --- a/core/themes/stable/templates/admin/update-report.html.twig +++ b/core/themes/stable/templates/admin/update-report.html.twig @@ -17,7 +17,7 @@ {% for project_type in project_types %}

{{ project_type.label }}

- {{ project_type.table }} + {{ project_type.content }} {% else %}

{{ no_updates_message }}

{% endfor %} diff --git a/core/themes/stable/templates/admin/update-version.html.twig b/core/themes/stable/templates/admin/update-version.html.twig index 6c23584a68..aa5ed5802b 100644 --- a/core/themes/stable/templates/admin/update-version.html.twig +++ b/core/themes/stable/templates/admin/update-version.html.twig @@ -15,20 +15,24 @@ #}
-
{{ title }}
-
+
{{ title }}
+
{{ version.version }} ({{ version.date|date('Y-M-d') }}) + {% if version.security_covered %} + {% trans %} + Covered by Drupal’s security advisory policy + {% endtrans %} + {% endif %}
- + {% if attributes.class != 'project-update__version--installed' %} +
+ +
+ {% endif %}
diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php index 1720d11e43..6cdd2421cf 100644 --- a/sites/default/default.settings.php +++ b/sites/default/default.settings.php @@ -736,6 +736,19 @@ */ /** + * Hide Drupal.org security advisory policy warnings. + * + * By default, Update Manager module warns about modules and themes from + * Drupal.org that are not covered by Drupal.org’s security advisory policy. + * + * Security issues in non-covered projects are reported to the public issue + * queue and will not receive coordinated security announcements. + * + * @see https://www.drupal.org/security-advisory-policy + */ +# $settings['update_warn_drupalorg_security'] = FALSE; + +/** * The default list of directories that will be ignored by Drupal's file API. * * By default ignore node_modules and bower_components folders to avoid issues