Problem/Motivation

The webform overview is accessible with the access webform overview permission. But the filter and the bulk operations on that overview are only available with the administer webform permission. The downside of that is, it grants far too many permissions to a user who only wants to filter webforms on the overview or needs to get access to archive, etc.

Proposed resolution

Introduce a new permission administer webform overview which can be granted to roles that should not have full admin permission but need access to those filters and bulk operations.

Issue fork webform-3487530

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

jurgenhaas created an issue. See original summary.

jurgenhaas’s picture

Status: Active » Needs review
jrockowitz’s picture

Status: Needs review » Needs work

This enhancement makes sense, we just need to add a little test coverage to \Drupal\Tests\webform\Functional\WebformListBuilderTest

jrockowitz’s picture

Status: Needs work » Reviewed & tested by the community

If tests pass this can be RTBC

jrockowitz’s picture

Status: Reviewed & tested by the community » Fixed

Now that this issue is closed, please review the contribution record.

As a contributor, attribute any organization helped you, or if you volunteered your own time.

Maintainers, please credit people who helped resolve this issue.

glynster’s picture

On a project the update failed for us

/**
 * Issue #3487530 : New permission for filter and bulk action on overview page.
 */
function webform_update_8648() {
  /** @var \Drupal\user\RoleInterface $roles */
  $roles = \Drupal::entityTypeManager()->getStorage('role')->loadMultiple();
  foreach ($roles as $role) {
    if ($role->hasPermission('administer webform')) {
      $role->grantPermission('administer webform overview');
      $role->save();
    }
  }
}

Error:

DEBUG [c7736e0e] 
 DEBUG [c7736e0e]        // Do you wish to run the specified pending updates?: yes.                     
 DEBUG [c7736e0e] 
 DEBUG [c7736e0e]       >  [notice] Update started: webform_update_8648
 DEBUG [c7736e0e]       >  [error]  The "role" entity type does not exist. 
 DEBUG [c7736e0e]       >  [error]  Update failed: webform_update_8648 
 DEBUG [c7736e0e]        [error]  Update aborted by: webform_update_8648 
 DEBUG [c7736e0e]        [error]  Finished performing updates. 

The only way we could resolve it was to update to

function webform_update_8648() {
  if (!\Drupal::entityTypeManager()->hasDefinition('role')) {
    \Drupal::logger('webform')->warning('Skipping webform_update_8648: role entity type not registered.');
    return;
  }

  $roles = \Drupal::entityTypeManager()->getStorage('role')->loadMultiple();
  foreach ($roles as $role) {
    if ($role->hasPermission('administer webform')) {
      $role->grantPermission('administer webform overview');
      $role->save();
    }
  }
}

This could be an isolated issue as several other projects did not have this issue.

  • 03af8298 committed on 6.3.x
    [#3487530] feat: New permission for filter and bulk action on overview...
jrockowitz’s picture

@glynster Thank you for posting something so quickly. I hadn't tested the update which contained a very dumb mistake.

I committed the fix. @see https://git.drupalcode.org/project/webform/-/commit/03af82986c566e137426...

  • 03af8298 committed on 6.x
    [#3487530] feat: New permission for filter and bulk action on overview...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

dimilias’s picture

I do not want to reopen the issue but just log something here just if somebody else runs across it.
This update broke our update path because it is using the API to update a role entity before config sync.

In our case, we had a rest plugin that we installed in the website and later removed it. At the same time, we updated webform.
One of our roles, which has the admin flag set to true, but no permissions assigned (because it gets all permissions) was attempted to be updated.
Now, I understand this might be quite an edge case, but since we removed the rest configuration, and along we removed the plugin as well, but because this is trying to update the role before configuration update (we are using drush deploy), Drupal started gathering all permissions and threw a PluginNotFoundException.

For anyone that might run across this, you may either use an update hook to remove the configuration prior to the update or you can commit a patch to first check for the role being admin or having no permissions.

Examples for both:

// In your mymodule.install file.
/**
 * Implements hook_update_N
 */
function mymodule_8000(): void {
  $config_to_delete = 'rest.resource.discussion_comment'; // Set your own configuration that is causing the issue.
  $config_to_delete = \Drupal::configFactory()->getEditable($config_to_delete);
  $config_to_delete->delete();
}

// In your mymodule.module file.
// Because the webform update might still run first depending on your dependency chain, you can set dependencies on it.
/**
 * Implements hook_update_dependencies().
 */
function mymodule_update_dependencies(): array {
  $dependencies['webform']['8648'] = [
    'mymodule' => '8000',
  ];
  return $dependencies;
}

Or, submitting a patch (not very optimal at this point unless you provide a different update entirely):

function webform_update_8648() {
  /** @var \Drupal\user\RoleInterface $roles */
  $roles = \Drupal::entityTypeManager()->getStorage('user_role')->loadMultiple();
  foreach ($roles as $role) {
-    if ($role->hasPermission('administer webform')) {
+   // You may use one of the following:
+   // if (!$role->isAdmin() && $role->hasPermission('administer webform')) {
+   // or
+   // if (in_array('administer webform', $role->getPermissions()) // Because ::hasPermission will return TRUE for the admin role but ::getPermissions will still be empty.
      $role->grantPermission('administer webform overview');
      $role->save();
    }
  }
}

The later solution is not preferred because 1, our case was very specific to admin roles, and 2, someone for some reason might still appoint (by mistake) permissions to that role too.

dpi’s picture

Same as @dimilias, trying to do an all in one D10.5->D11.2 upgrade with 6.3.0-beta7 in the mix.

Im getting:

> [notice] Update started: webform_update_8648
> [error] SQLSTATE[42S22]: Column not found: 1054 Unknown column 'alias' in 'where clause': SELECT "router"."name" AS "name", "router"."route" AS "route"
> FROM
> "router" "router"
> WHERE "alias" IS NULL; Array
> (
> )
>
> [error] Update failed: webform_update_8648

Like various other update paths in the same file, I think we need to update webform_update_8648 to also use configFactory's listAll and getEditable instead of by entity API's.

dpi’s picture

Pushed MR811 with proposed change.

dpi’s picture