View source
<?php
use Drupal\Core\Url;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Session\AccountInterface;
use Drupal\User\UserInterface;
use Drupal\User\RoleInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemList;
use Drupal\Core\Database\Query\AlterableInterface;
function _administerusersbyrole_build_perm_string($role_id, $op = 'edit') {
$perm = "{$op} users with role {$role_id}";
return $perm;
}
function administerusersbyrole_user_role_access(RoleInterface $role, $operation, AccountInterface $account) {
if ($operation == 'view') {
return AccessResult::allowedIfHasPermission($account, 'access users overview');
}
return AccessResult::neutral();
}
function administerusersbyrole_user_access(UserInterface $user, $operation, AccountInterface $account) {
if (!$user
->isNew() && $user
->id() <= 1) {
return AccessResult::neutral();
}
if ($user
->isBlocked() && $operation == 'view') {
return administerusersbyrole_user_access($user, 'update', $account);
}
$convert = array(
'delete' => 'cancel',
'update' => 'edit',
);
if (!isset($convert[$operation])) {
return AccessResult::neutral();
}
$roles = $user
->getRoles();
foreach ($roles as $rid) {
if ($rid == AccountInterface::AUTHENTICATED_ROLE && count($roles) > 1) {
continue;
}
if (!$account
->hasPermission(_administerusersbyrole_build_perm_string($rid, $convert[$operation]))) {
return AccessResult::neutral();
}
}
return AccessResult::allowed()
->cachePerPermissions()
->addCacheableDependency($user);
}
function administerusersbyrole_entity_create_access(AccountInterface $account, array $context, $entity_bundle) {
if ($context['entity_type_id'] != 'user') {
return AccessResult::neutral();
}
return AccessResult::allowedIfHasPermission($account, 'create users');
}
function administerusersbyrole_entity_field_access($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemList $items = NULL) {
if ($field_definition
->getTargetEntityTypeId() != 'user') {
return AccessResult::neutral();
}
$fields = array(
'name',
'status',
'mail',
);
if ($operation == 'view') {
array_push($fields, 'roles', 'access');
}
if (!in_array($field_definition
->getName(), $fields)) {
return AccessResult::neutral();
}
if (is_null($items)) {
if ($operation == 'view') {
return AccessResult::allowedIfHasPermission($account, 'access users overview');
}
return AccessResult::neutral();
}
return administerusersbyrole_user_access($items
->getEntity(), 'update', $account);
}
function administerusersbyrole_validation_constraint_alter(array &$definitions) {
$definitions['UserMailRequired']['class'] = '\\Drupal\\administerusersbyrole\\Constraint\\OverrideUserMailRequired';
}
function administerusersbyrole_query_administerusersbyrole_edit_access_alter(AlterableInterface $query) {
$account = \Drupal::currentUser();
if (!$account
->hasPermission('administer users')) {
$query
->condition('users_field_data.uid', 1, '<>');
$roles = user_roles(TRUE);
foreach ($roles as $rid => $role) {
if (!$account
->hasPermission(_administerusersbyrole_build_perm_string($rid, 'edit'))) {
$exclude[$rid] = $rid;
}
}
if (isset($exclude[RoleInterface::AUTHENTICATED_ID])) {
$query
->Join('user__roles', 'ur', 'ur.entity_id=users_field_data.uid');
unset($exclude[RoleInterface::AUTHENTICATED_ID]);
}
if (!empty($exclude)) {
$subquery = \Drupal::database()
->select('user__roles', 'ur2');
$subquery
->fields('ur2', array(
'entity_id',
));
$subquery
->condition('ur2.roles_target_id', $exclude, 'IN');
$query
->condition('users_field_data.uid', $subquery, 'NOT IN');
}
}
}
function administerusersbyrole_form_user_form_alter(&$form, &$form_state) {
$user = $form_state
->getFormObject()
->getEntity();
$account = Drupal::currentUser();
if (!$user
->getEmail() && $account
->hasPermission('allow empty user mail')) {
$form['account']['mail']['#required'] = FALSE;
}
}
function administerusersbyrole_form_user_cancel_form_alter(&$form, &$form_state) {
$user = $form_state
->getFormObject()
->getEntity();
$account = Drupal::currentUser();
if (administerusersbyrole_user_access($user, 'delete', $account)
->isAllowed()) {
$form['user_cancel_method']['user_cancel_delete']['#access'] = TRUE;
}
}
function administerusersbyrole_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.administerusersbyrole':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('Administer Users by Role allows site builders to set up fine-grained permissions for allowing "sub-admin" users to edit and delete other users - more specific than Drupal Core\'s all-or-nothing \'administer users\' permission. It also provides and enforces a \'create users\' permission') . '</p>';
$output .= '<h3>' . t('Core permissions') . '</h3>';
$output .= '<dl>';
$output .= '<dt>' . t('Administer users') . '</dt>';
$output .= '<dd>' . t('<em>Do not</em> set this for sub-admins. This permission bypasses all of the permissions in "Administer Users by Role".') . '</dd>';
$output .= '<dt>' . t('View user profiles') . '</dt>';
$output .= '<dd>' . t('Your sub-admins should probably have this permission. (Most things work without it, but for example with a View showing users, the user name will only become a link if this permission is set.)') . '</dd>';
$output .= '<dt>' . t('Select method for cancelling account') . '</dt>';
$output .= '<dd>' . t('If you set this for sub-admins, then the sub-admin can choose a cancellation method when cancelling an account. If not, then the sum-admin will always use the default cancellation method.') . '</dd>';
$output .= '</dl>';
$output .= '<h3>' . t('New permissions') . '</h3>';
$output .= '<dl>';
$output .= '<dt>' . t('Access the users overview page') . '</dt>';
$output .= '<dd>' . t('Grants access to <a href=":people">manage users page</a>. Only users that can be edited are shown.', [
':people' => \Drupal::url('entity.user.collection'),
]) . '</dd>';
$output .= '<dt>' . t('Create new users') . '</dt>';
$output .= '<dd>' . t('Grants access to <a href=":create">create users</a>.', [
':create' => \Drupal::url('user.admin_create'),
]) . '</dd>';
$output .= '<dt>' . t('Allow empty user mail when managing users') . '</dt>';
$output .= '<dd>' . t('Create and manage users that have no email address.') . '</dd>';
$output .= '<dt>' . t('Edit users with no custom roles') . '</dt>';
$output .= '<dd>' . t('Allows editing of any authenticated user that has no custom roles set.') . '</dd>';
$output .= '<dt>' . t('Edit users with role XXX') . '</dt>';
$output .= '<dd>' . t('Allows editing of any authenticated user with the specified role. To edit a user with multiple roles, the sub-admin must have permission to edit ALL of those roles. (\'Edit users with no custom roles\' is NOT needed.)') . '</dd>';
$output .= '</dl>';
$output .= '<p>' . t('The permission for cancel work exactly the same as those for edit.') . '</p>';
return $output;
}
}