Loading bulk_update_user_roles.routing.yml +1 −1 Changes for bulk_update_user_roles.routing.yml: 1 added line, 1 removed line. Original line number Diff line number Diff line Loading @@ -4,4 +4,4 @@ bulk_update_user_roles.settings: _form: '\Drupal\bulk_update_user_roles\Form\BulkUpdateUserForm' _title: 'Bulk Update User Roles' requirements: _permission: 'administer users' _permission: 'administer permissions' src/Form/BulkUpdateUserForm.php +55 −14 Changes for src/Form/BulkUpdateUserForm.php: 55 added lines, 14 removed lines. Original line number Diff line number Diff line Loading @@ -8,7 +8,8 @@ use Drupal\bulk_update_user_roles\Batch\BulkUpdateUserRoles; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\user\RoleStorageInterface; use Drupal\Core\Session\AccountInterface; use Drupal\user\RoleInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** Loading @@ -24,23 +25,23 @@ class BulkUpdateUserForm extends FormBase { protected $entityTypeManager; /** * The role storage. * The current user. * * @var \Drupal\user\RoleStorageInterface * @var \Drupal\Core\Session\AccountInterface */ protected $roleStorage; protected $currentUserAccount; /** * Constructs a new BulkUpdateUserForm. * * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager * The entity type manager. * @param \Drupal\user\RoleStorageInterface $role_storage * The role storage. * @param \Drupal\Core\Session\AccountInterface $current_user * The current user. */ public function __construct(EntityTypeManagerInterface $entity_type_manager, RoleStorageInterface $role_storage) { public function __construct(EntityTypeManagerInterface $entity_type_manager, AccountInterface $current_user) { $this->entityTypeManager = $entity_type_manager; $this->roleStorage = $role_storage; $this->currentUserAccount = $current_user; } /** Loading @@ -49,7 +50,7 @@ class BulkUpdateUserForm extends FormBase { public static function create(ContainerInterface $container): static { return new static( $container->get('entity_type.manager'), $container->get('entity_type.manager')->getStorage('user_role') $container->get('current_user') ); } Loading @@ -69,13 +70,10 @@ class BulkUpdateUserForm extends FormBase { 'remove' => $this->t('Remove roles'), ]; $roles = $this->roleStorage->loadMultiple(); $role_options = []; foreach ($roles as $role) { if (!in_array($role->id(), ['anonymous', 'authenticated'])) { foreach ($this->getAssignableRoles() as $role) { $role_options[$role->id()] = $role->label(); } } $user_storage = $this->entityTypeManager->getStorage('user'); $query = $user_storage->getQuery() Loading Loading @@ -159,11 +157,54 @@ class BulkUpdateUserForm extends FormBase { return $options; } /** * Returns the roles the current user is allowed to bulk assign/remove. * * Mirrors \Drupal\user\AccountForm, which only exposes role assignment at * all to users holding 'administer permissions'. The route already * requires that permission, but the role list is filtered again here * (and re-checked in submitForm()) so that a mis-restricted route, a * stale cached page, or a directly-crafted POST can never grant a role * the current user was not actually authorized to hand out -- an * account must not be able to assign an admin role it does not already * hold itself. User 1 is exempt from that check: as the site's * superuser it typically holds no roles at all (its permissions bypass * comes from being uid 1, not from role membership), so without this * exemption user 1 could never assign an admin role through this form. * * @return \Drupal\user\RoleInterface[] * The assignable roles, keyed by role ID. */ protected function getAssignableRoles(): array { if (!$this->currentUserAccount->hasPermission('administer permissions')) { return []; } $assignable = []; foreach ($this->entityTypeManager->getStorage('user_role')->loadMultiple() as $role) { if (in_array($role->id(), [RoleInterface::ANONYMOUS_ID, RoleInterface::AUTHENTICATED_ID], TRUE)) { continue; } if ($role->isAdmin() && (int) $this->currentUserAccount->id() !== 1 && !in_array($role->id(), $this->currentUserAccount->getRoles(), TRUE)) { continue; } $assignable[$role->id()] = $role; } return $assignable; } /** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state): void { $roles_selected = $form_state->getValue('buur_user_roles'); $assignable_role_ids = array_keys($this->getAssignableRoles()); $roles_selected = array_intersect((array) $form_state->getValue('buur_user_roles'), $assignable_role_ids); if (empty($roles_selected)) { $this->messenger()->addError($this->t('You are not authorized to assign or remove the selected role(s).')); return; } $select_all_users = $form_state->getValue('select_all_users'); $user_storage = $this->entityTypeManager->getStorage('user'); $query = $user_storage->getQuery() Loading Loading
bulk_update_user_roles.routing.yml +1 −1 Changes for bulk_update_user_roles.routing.yml: 1 added line, 1 removed line. Original line number Diff line number Diff line Loading @@ -4,4 +4,4 @@ bulk_update_user_roles.settings: _form: '\Drupal\bulk_update_user_roles\Form\BulkUpdateUserForm' _title: 'Bulk Update User Roles' requirements: _permission: 'administer users' _permission: 'administer permissions'
src/Form/BulkUpdateUserForm.php +55 −14 Changes for src/Form/BulkUpdateUserForm.php: 55 added lines, 14 removed lines. Original line number Diff line number Diff line Loading @@ -8,7 +8,8 @@ use Drupal\bulk_update_user_roles\Batch\BulkUpdateUserRoles; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\user\RoleStorageInterface; use Drupal\Core\Session\AccountInterface; use Drupal\user\RoleInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** Loading @@ -24,23 +25,23 @@ class BulkUpdateUserForm extends FormBase { protected $entityTypeManager; /** * The role storage. * The current user. * * @var \Drupal\user\RoleStorageInterface * @var \Drupal\Core\Session\AccountInterface */ protected $roleStorage; protected $currentUserAccount; /** * Constructs a new BulkUpdateUserForm. * * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager * The entity type manager. * @param \Drupal\user\RoleStorageInterface $role_storage * The role storage. * @param \Drupal\Core\Session\AccountInterface $current_user * The current user. */ public function __construct(EntityTypeManagerInterface $entity_type_manager, RoleStorageInterface $role_storage) { public function __construct(EntityTypeManagerInterface $entity_type_manager, AccountInterface $current_user) { $this->entityTypeManager = $entity_type_manager; $this->roleStorage = $role_storage; $this->currentUserAccount = $current_user; } /** Loading @@ -49,7 +50,7 @@ class BulkUpdateUserForm extends FormBase { public static function create(ContainerInterface $container): static { return new static( $container->get('entity_type.manager'), $container->get('entity_type.manager')->getStorage('user_role') $container->get('current_user') ); } Loading @@ -69,13 +70,10 @@ class BulkUpdateUserForm extends FormBase { 'remove' => $this->t('Remove roles'), ]; $roles = $this->roleStorage->loadMultiple(); $role_options = []; foreach ($roles as $role) { if (!in_array($role->id(), ['anonymous', 'authenticated'])) { foreach ($this->getAssignableRoles() as $role) { $role_options[$role->id()] = $role->label(); } } $user_storage = $this->entityTypeManager->getStorage('user'); $query = $user_storage->getQuery() Loading Loading @@ -159,11 +157,54 @@ class BulkUpdateUserForm extends FormBase { return $options; } /** * Returns the roles the current user is allowed to bulk assign/remove. * * Mirrors \Drupal\user\AccountForm, which only exposes role assignment at * all to users holding 'administer permissions'. The route already * requires that permission, but the role list is filtered again here * (and re-checked in submitForm()) so that a mis-restricted route, a * stale cached page, or a directly-crafted POST can never grant a role * the current user was not actually authorized to hand out -- an * account must not be able to assign an admin role it does not already * hold itself. User 1 is exempt from that check: as the site's * superuser it typically holds no roles at all (its permissions bypass * comes from being uid 1, not from role membership), so without this * exemption user 1 could never assign an admin role through this form. * * @return \Drupal\user\RoleInterface[] * The assignable roles, keyed by role ID. */ protected function getAssignableRoles(): array { if (!$this->currentUserAccount->hasPermission('administer permissions')) { return []; } $assignable = []; foreach ($this->entityTypeManager->getStorage('user_role')->loadMultiple() as $role) { if (in_array($role->id(), [RoleInterface::ANONYMOUS_ID, RoleInterface::AUTHENTICATED_ID], TRUE)) { continue; } if ($role->isAdmin() && (int) $this->currentUserAccount->id() !== 1 && !in_array($role->id(), $this->currentUserAccount->getRoles(), TRUE)) { continue; } $assignable[$role->id()] = $role; } return $assignable; } /** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state): void { $roles_selected = $form_state->getValue('buur_user_roles'); $assignable_role_ids = array_keys($this->getAssignableRoles()); $roles_selected = array_intersect((array) $form_state->getValue('buur_user_roles'), $assignable_role_ids); if (empty($roles_selected)) { $this->messenger()->addError($this->t('You are not authorized to assign or remove the selected role(s).')); return; } $select_all_users = $form_state->getValue('select_all_users'); $user_storage = $this->entityTypeManager->getStorage('user'); $query = $user_storage->getQuery() Loading