diff -u b/core/lib/Drupal/Core/Config/ConfigInstaller.php b/core/lib/Drupal/Core/Config/ConfigInstaller.php
--- b/core/lib/Drupal/Core/Config/ConfigInstaller.php
+++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php
@@ -124,10 +124,9 @@
$collection_info = $this->configManager->getConfigCollectionInfo();
foreach ($collection_info->getCollectionNames() as $collection) {
$config_to_create = $this->getConfigToCreate($storage, $collection, $prefix, $profile_storages);
- // If we're installing a profile ensure configuration that is overriding
- // is excluded.
- // @todo Exclude simple configuration that already exists because it
- // will have been imported already.
+ // @todo If we're installing a profile we could exclude simple
+ // configuration that already exists because it will have been
+ // overridden already. Do we need to do that work?
if (!empty($config_to_create)) {
$this->createConfiguration($collection, $config_to_create);
}
@@ -260,7 +259,9 @@
if ($this->drupalInstallationAttempted()) {
// During installation profile provided configuration overrides can have
// dependencies that can not possibly be installed. Therefore, only
- // override simple configuration.
+ // override simple configuration. As this method is called before
+ // modules are installed the only way to determine if they are
+ // configuration entities is the presence of a dependencies key.
foreach ($profile_overrides as $name => $override_data) {
if (!isset($override_data['dependencies'])) {
$data[$name] = $override_data;
only in patch2:
unchanged:
--- a/core/modules/config/src/Tests/ConfigInstallProfileUnmetDependenciesTest.php
+++ b/core/modules/config/src/Tests/ConfigInstallProfileUnmetDependenciesTest.php
@@ -44,11 +44,10 @@ protected function setUp() {
}
}
- // Add a dependency that can not be met because User is installed before
- // Action.
+ // Add a dependency that can not be met.
$config_file = $dest . DIRECTORY_SEPARATOR . InstallStorage::CONFIG_INSTALL_DIRECTORY . DIRECTORY_SEPARATOR . 'system.action.user_block_user_action.yml';
$action = Yaml::decode(file_get_contents($config_file));
- $action['dependencies']['module'][] = 'action';
+ $action['dependencies']['module'][] = 'does_not_exist';
file_put_contents($config_file, Yaml::encode($action));
parent::setUp();
@@ -90,7 +89,7 @@ public function testInstalled() {
else {
$this->fail('Expected Drupal\Core\Config\UnmetDependenciesException exception thrown');
}
- $this->assertErrorLogged('Configuration objects provided by user have unmet dependencies: system.action.user_block_user_action (action)');
+ $this->assertErrorLogged('Configuration objects provided by testing_config_overrides have unmet dependencies: system.action.user_block_user_action (does_not_exist)');
}
}
only in patch2:
unchanged:
--- a/core/modules/config/tests/src/Functional/ConfigInstallProfileOverrideTest.php
+++ b/core/modules/config/tests/src/Functional/ConfigInstallProfileOverrideTest.php
@@ -8,6 +8,7 @@
use Drupal\Core\Config\FileStorage;
use Drupal\system\Entity\Action;
use Drupal\tour\Entity\Tour;
+use Drupal\user\Entity\Role;
/**
* Tests installation and removal of configuration objects in install, disable
@@ -109,6 +110,11 @@ public function testInstallProfileConfigOverwrite() {
$this->rebuildContainer();
$this->assertEqual($config_test_storage->load('override_unmet')->label(), 'Override', 'The optional config_test entity is overridden by the profile optional configuration and is installed when its dependencies are met.');
$this->assertEqual($config_test_storage->load('completely_new')->label(), 'Completely new optional configuration', 'The optional config_test entity is provided by the profile optional configuration and is installed when its dependencies are met.');
+
+ // Ensure the authenticated role has the access tour permission.
+ $role = Role::load(Role::AUTHENTICATED_ID);
+ $this->assertTrue($role->hasPermission('access tour'), 'The Authenticated role has the "access tour" permission.');
+ $this->assertEquals(['module' => ['tour']], $role->getDependencies());
}
}
only in patch2:
unchanged:
--- /dev/null
+++ b/core/modules/user/tests/src/Functional/Update/UserUpdateRoleDependenciesTest.php
@@ -0,0 +1,46 @@
+databaseDumpFiles = [
+ __DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8-rc1.bare.standard.php.gz',
+ ];
+ }
+
+ /**
+ * Tests that roles have dependencies and only existing permissions.
+ */
+ public function testRolePermissions() {
+ // Edit the role to have a non-existent permission.
+ $raw_config = $this->config('user.role.authenticated');
+ $permissions = $raw_config->get('permissions');
+ $permissions[] = 'does_not_exist';
+ $raw_config
+ ->set('permissions', $permissions)
+ ->save();
+
+ $authenticated = Role::load('authenticated');
+ $this->assertTrue($authenticated->hasPermission('does_not_exist'), 'Authenticated role has a permission that does not exist');
+ $this->assertEquals([], $authenticated->getDependencies());
+
+ $this->runUpdates();
+ $authenticated = Role::load('authenticated');
+ $this->assertFalse($authenticated->hasPermission('does_not_exist'), 'Authenticated role does not have a permission that does not exist');
+ $this->assertEquals(['config' => ['filter.format.basic_html'], 'module' => ['comment', 'contact', 'filter', 'search', 'shortcut', 'system']], $authenticated->getDependencies());
+ }
+
+}
only in patch2:
unchanged:
--- a/core/modules/user/user.post_update.php
+++ b/core/modules/user/user.post_update.php
@@ -20,3 +20,17 @@ function user_post_update_enforce_order_of_permissions() {
};
array_map($entity_save, Role::loadMultiple());
}
+
+/**
+ * Calculate role dependencies and remove non-existent permissions.
+ */
+function user_post_update_update_roles() {
+ $existing_permissions = array_keys(\Drupal::service('user.permissions')->getPermissions());
+ $entity_save = function (Role $role) use ($existing_permissions) {
+ $permissions = array_intersect($role->getPermissions(), $existing_permissions);
+ $role
+ ->set('permissions', $permissions)
+ ->save();
+ };
+ array_map($entity_save, Role::loadMultiple());
+}