diff --git a/core/modules/contact/lib/Drupal/contact/Tests/ContactPersonalTest.php b/core/modules/contact/lib/Drupal/contact/Tests/ContactPersonalTest.php index 7e1bd71..e735180 100644 --- a/core/modules/contact/lib/Drupal/contact/Tests/ContactPersonalTest.php +++ b/core/modules/contact/lib/Drupal/contact/Tests/ContactPersonalTest.php @@ -54,7 +54,7 @@ function setUp() { parent::setUp(); // Create an admin user. - $this->admin_user = $this->drupalCreateUser(array('administer contact forms', 'administer users')); + $this->admin_user = $this->drupalCreateUser(array('administer contact forms', 'administer users', 'administer account settings')); // Create some normal users with their contact forms enabled by default. \Drupal::config('contact.settings')->set('user_default_enabled', 1)->save(); diff --git a/core/modules/contact/lib/Drupal/contact/Tests/ContactSitewideTest.php b/core/modules/contact/lib/Drupal/contact/Tests/ContactSitewideTest.php index 56b902e..b524dfa 100644 --- a/core/modules/contact/lib/Drupal/contact/Tests/ContactSitewideTest.php +++ b/core/modules/contact/lib/Drupal/contact/Tests/ContactSitewideTest.php @@ -39,6 +39,7 @@ function testSiteWideContact() { 'access site-wide contact form', 'administer contact forms', 'administer users', + 'administer account settings', 'administer contact_message fields', )); $this->drupalLogin($admin_user); diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUiTestBase.php b/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUiTestBase.php index c836023..8d397f1 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUiTestBase.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/Tests/FieldUiTestBase.php @@ -26,7 +26,7 @@ function setUp() { parent::setUp(); // Create test user. - $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer node fields', 'administer node form display', 'administer node display', 'administer taxonomy', 'administer taxonomy_term fields', 'administer taxonomy_term display', 'administer users', 'administer user display', 'bypass node access')); + $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer node fields', 'administer node form display', 'administer node display', 'administer taxonomy', 'administer taxonomy_term fields', 'administer taxonomy_term display', 'administer users', 'administer account settings', 'administer user display', 'bypass node access')); $this->drupalLogin($admin_user); // Create content type, with underscores. diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UserPermissionUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UserPermissionUpgradePathTest.php new file mode 100644 index 0000000..ecb8b3a --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UserPermissionUpgradePathTest.php @@ -0,0 +1,64 @@ + 'User permission upgrade test', + 'description' => 'Upgrade tests for user permissions.', + 'group' => 'Upgrade path', + ); + } + + public function setUp() { + $this->databaseDumpFiles = array( + drupal_get_path('module', 'system') . '/tests/upgrade/drupal-7.bare.standard_all.database.php.gz', + drupal_get_path('module', 'system') . '/tests/upgrade/drupal-7.user_permission.database.php', + ); + parent::setUp(); + } + + /** + * Tests user-related permissions after a successful upgrade. + */ + public function testUserPermissionUpgrade() { + $this->assertTrue($this->performUpgrade(), 'The upgrade was completed successfully.'); + + $this->drupalGet(''); + $this->assertResponse(200); + + // Verify that we are still logged in. + $this->drupalGet('user'); + $this->clickLink(t('Edit')); + $this->assertEqual($this->getUrl(), url('user/1/edit', array('absolute' => TRUE)), 'We are still logged in as admin at the end of the upgrade.'); + + // Login as another 'administrator' role user whose uid != 1 + $this->drupalLogout(); + $user = new UserSession(array( + 'uid' => 2, + 'name' => 'user1', + 'pass_raw' => 'user1', + )); + $this->drupalLogin($user); + + // Check that user with permission 'administer users' also gets + // 'administer account settings' access. + $this->drupalGet('admin/config/people/accounts'); + $this->assertResponse(200, '"Administer account settings" page was found.'); + } + +} diff --git a/core/modules/system/tests/upgrade/drupal-7.user_permission.database.php b/core/modules/system/tests/upgrade/drupal-7.user_permission.database.php new file mode 100644 index 0000000..dc6cd5a --- /dev/null +++ b/core/modules/system/tests/upgrade/drupal-7.user_permission.database.php @@ -0,0 +1,60 @@ +fields(array( + 'uid', + 'rid', +)) +->values(array( + 'uid' => '2', + 'rid' => '3', +)) +->execute(); + +db_insert('users')->fields(array( + 'uid', + 'name', + 'pass', + 'mail', + 'theme', + 'signature', + 'signature_format', + 'created', + 'access', + 'login', + 'status', + 'timezone', + 'language', + 'picture', + 'init', + 'data', +)) +->values(array( + 'uid' => '2', + 'name' => 'user1', + 'pass' => '$S$D9JgycE33DawX/9Iv2SfAjkQEi5alDZhxycfan6dDkUKf9lH0Nfo', + 'mail' => 'user1@example.com', + 'theme' => '', + 'signature' => '', + 'signature_format' => NULL, + 'created' => '1376147347', + 'access' => '0', + 'login' => '0', + 'status' => '1', + 'timezone' => 'Europe/Berlin', + 'language' => '', + 'picture' => '0', + 'init' => 'user1@example.com', + 'data' => NULL, +)) +->execute(); diff --git a/core/modules/user/lib/Drupal/user/Tests/UserAdminTest.php b/core/modules/user/lib/Drupal/user/Tests/UserAdminTest.php index 0b61e23..077eeed 100644 --- a/core/modules/user/lib/Drupal/user/Tests/UserAdminTest.php +++ b/core/modules/user/lib/Drupal/user/Tests/UserAdminTest.php @@ -120,7 +120,7 @@ function testUserAdmin() { */ function testNotificationEmailAddress() { // Test that the Notification E-mail address field is on the config page. - $admin_user = $this->drupalCreateUser(array('administer users')); + $admin_user = $this->drupalCreateUser(array('administer users', 'administer account settings')); $this->drupalLogin($admin_user); $this->drupalGet('admin/config/people/accounts'); $this->assertRaw('id="edit-mail-notification-address"', 'Notification E-mail address field exists'); diff --git a/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.php b/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.php index 40f8d60..857f0b6 100644 --- a/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.php +++ b/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.php @@ -25,7 +25,7 @@ public static function getInfo() { function setUp() { parent::setUp(); - $this->admin_user = $this->drupalCreateUser(array('administer permissions', 'access user profiles', 'administer site configuration', 'administer modules', 'administer users')); + $this->admin_user = $this->drupalCreateUser(array('administer permissions', 'access user profiles', 'administer site configuration', 'administer modules', 'administer account settings')); // Find the new role ID. $all_rids = $this->admin_user->getRoles(); diff --git a/core/modules/user/user.install b/core/modules/user/user.install index 6d15166..2d5b03e 100644 --- a/core/modules/user/user.install +++ b/core/modules/user/user.install @@ -1012,11 +1012,31 @@ function user_update_8016() { } /** + * Grant "administer account settings" to roles with "administer users." + */ +function user_update_8017() { + $rids = db_query("SELECT rid FROM {role_permission} WHERE permission = :perm", array(':perm' => 'administer users'))->fetchCol(); + // None found. + if (empty($rids)) { + return; + } + $insert = db_insert('role_permission')->fields(array('rid', 'permission', 'module')); + foreach ($rids as $rid) { + $insert->values(array( + 'rid' => $rid, + 'permission' => 'administer account settings', + 'module' => 'user' + )); + } + $insert->execute(); +} + +/** * Migrate user roles into configuration. * * @ingroup config_upgrade */ -function user_update_8017() { +function user_update_8018() { $uuid = new Uuid(); $roles = db_select('role', 'r') @@ -1038,7 +1058,7 @@ function user_update_8017() { /** * Use the maximum allowed module name length in module name database fields. */ -function user_update_8018() { +function user_update_8019() { if (db_field_exists('role_permission', 'module')) { $spec = array( 'type' => 'varchar', @@ -1095,7 +1115,7 @@ function _user_update_map_rid($rid) { * * @ingroup config_upgrade */ -function user_update_8019() { +function user_update_8020() { $db_permissions = db_select('role_permission', 'p') ->fields('p') ->execute() @@ -1117,7 +1137,7 @@ function user_update_8019() { /** * Create the 'register' form mode. */ -function user_update_8020() { +function user_update_8021() { $uuid = new Uuid(); Drupal::config("entity.form_mode.user.register") diff --git a/core/modules/user/user.module b/core/modules/user/user.module index 75de3cc..dbc1032 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -321,24 +321,37 @@ function user_load_by_name($name) { /** * Verify the syntax of the given name. - * - * @param string $name - * The user name to validate. - * - * @return string|null - * A translated violation message if the name is invalid or NULL if the name - * is valid. - * */ function user_validate_name($name) { - $data = \Drupal::typedData()->create(array( - 'type' => 'string', - 'constraints' => array('UserName' => array()), - )); - $data->setValue($name); - $violations = $data->validate(); - if (count($violations) > 0) { - return $violations[0]->getMessage(); + if (!$name) { + return t('You must enter a username.'); + } + if (substr($name, 0, 1) == ' ') { + return t('The username cannot begin with a space.'); + } + if (substr($name, -1) == ' ') { + return t('The username cannot end with a space.'); + } + if (strpos($name, ' ') !== FALSE) { + return t('The username cannot contain multiple spaces in a row.'); + } + if (preg_match('/[^\x{80}-\x{F7} a-z0-9@_.\'-]/i', $name)) { + return t('The username contains an illegal character.'); + } + if (preg_match('/[\x{80}-\x{A0}' . // Non-printable ISO-8859-1 + NBSP + '\x{AD}' . // Soft-hyphen + '\x{2000}-\x{200F}' . // Various space characters + '\x{2028}-\x{202F}' . // Bidirectional text overrides + '\x{205F}-\x{206F}' . // Various text hinting characters + '\x{FEFF}' . // Byte order mark + '\x{FF01}-\x{FF60}' . // Full-width latin + '\x{FFF9}-\x{FFFD}' . // Replacement characters + '\x{0}-\x{1F}]/u', // NULL byte and control characters + $name)) { + return t('The username contains an illegal character.'); + } + if (drupal_strlen($name) > USERNAME_MAX_LENGTH) { + return t('The username %name is too long: it must be %max characters or less.', array('%name' => $name, '%max' => USERNAME_MAX_LENGTH)); } } @@ -466,6 +479,11 @@ function user_permission() { 'title' => t('Administer permissions'), 'restrict access' => TRUE, ), + 'administer account settings' => array( + 'title' => t('Administer account settings'), + 'description' => t('Configure site-wide settings and behavior for user accounts and registration.', array('@url' => url('admin/config/people'))), + 'restrict access' => TRUE, + ), 'administer users' => array( 'title' => t('Administer users'), 'restrict access' => TRUE, @@ -880,11 +898,15 @@ function user_menu() { // Administration pages. $items['admin/config/people'] = array( - 'title' => 'People', - 'description' => 'Configure user accounts.', - 'position' => 'left', - 'weight' => -20, - 'route_name' => 'user_admin_index', + 'title' => 'People', + 'description' => 'Configure user accounts.', + 'position' => 'left', + 'weight' => -20, + 'route_name' => 'user_admin_index', + 'page callback' => 'system_admin_menu_block_page', + 'access arguments' => array('administer account settings'), + 'file' => 'system.admin.inc', + 'file path' => drupal_get_path('module', 'system'), ); $items['admin/config/people/accounts'] = array( @@ -2099,7 +2121,7 @@ function user_library_info() { $path = drupal_get_path('module', 'user'); $libraries['drupal.user'] = array( 'title' => 'User', - 'version' => Drupal::VERSION, + 'version' => VERSION, 'js' => array( $path . '/user.js' => array(), ), @@ -2115,7 +2137,7 @@ function user_library_info() { $libraries['drupal.user.permissions'] = array( 'title' => 'User permissions', - 'version' => Drupal::VERSION, + 'version' => VERSION, 'js' => array( $path . '/user.permissions.js' => array(), ), @@ -2128,7 +2150,7 @@ function user_library_info() { $libraries['drupal.user.icons'] = array( 'title' => 'User icon styling', - 'version' => Drupal::VERSION, + 'version' => VERSION, 'css' => array( $path . '/css/user.icons.css' => array(), ), diff --git a/core/modules/user/user.routing.yml b/core/modules/user/user.routing.yml index 2e8dcb3..ba75389 100644 --- a/core/modules/user/user.routing.yml +++ b/core/modules/user/user.routing.yml @@ -38,7 +38,7 @@ user_account_settings: defaults: _form: '\Drupal\user\AccountSettingsForm' requirements: - _permission: 'administer users' + _permission: 'administer account settings' user_admin_create: pattern: '/admin/people/create'