Return early in EntityPermissionsForm::access if the user does not have "administer permissions"

Created on 27 February 2023, almost 2 years ago
Updated 31 August 2023, over 1 year ago

Problem/Motivation

We found a major performance issue in our D10 upgrade due to a combination of patches we were running that did not include #3315042: Remaining tasks for "edit block $type" permissions β†’

This doubled our test times (45 mins to 1h 30 mins)

In depth discussion in slack - https://drupal.slack.com/archives/C1BMUQ9U6/p1677479488859459

Proposed resolution

Since the route is only accessible if the user has both the permission defined in EntityPermissionsRouteProvider::getEntityPermissionsRoute AND if EntityPermissionsForm::access returns allowed, we can short circuit the expensive config dependency calculation by returning neutral in EntityPermissionsForm::access if the user doesn't have the permission.

Ideally we get the permission directly from the route.

πŸ“Œ Task
Status

Fixed

Version

11.0 πŸ”₯

Component
User moduleΒ  β†’

Last updated about 4 hours ago

Created by

πŸ‡¦πŸ‡ΊAustralia acbramley

Live updates comments and jobs are added and updated live.
  • Performance

    It affects performance. It is often combined with the Needs profiling tag.

Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • Issue created by @acbramley
  • @acbramley opened merge request.
  • Status changed to Needs review almost 2 years ago
  • πŸ‡¦πŸ‡ΊAustralia acbramley

    This seems to work

  • Status changed to Needs work almost 2 years ago
  • πŸ‡¦πŸ‡ΊAustralia larowlan πŸ‡¦πŸ‡ΊπŸ.au GMT+10

    Looking at \Drupal\KernelTests\Core\Config\ConfigDependencyTest::testConfigEntityUninstallComplex we have a way to test this fairly easily.

    something like this

    $comment_type = CommentType::create($values)->save();
    \Drupal::state()->set('config_test.fix_dependencies', [$comment_type->getConfigDependencyName()]);
    \Drupal::state()->set('config_test.on_dependency_removal_called', []);
    // Visit route that calls access check for comment type permissions, e.g. the comment type form with user without administer permissions.
    $called = \Drupal::state()->get('config_test.on_dependency_removal_called', []);
    $this->assertEmpty($called);
    
  • πŸ‡¨πŸ‡­Switzerland berdir Switzerland

    I still think we should consider to drop this feature (hide the permission local task dynamically if no permissions are defined) entirely. This will improve the situation for all users without administer permissions which is much better, but as such a user, you're still affected by the problem.

    IMHO, having a permissions tab with a page that says "sorry, no permissions for you" would be quite acceptable for the handful of entity types that don't come with bundle permissions by default.

  • πŸ‡¦πŸ‡ΊAustralia fenstrat Australia

    Just confirming that @acbramley's approach in the MR fixes our major performance issue.

    However I'd also strongly agree with @Berdir, dropping this permission check altogether makes a lot of sense.

  • πŸ‡¦πŸ‡ΊAustralia acbramley

    @Berdir I agree, but do you think we bother getting this in first? Seems like removing the whole thing will take some time.

    Will hold off on tests until I get confirmation on that.

  • πŸ‡¦πŸ‡ΊAustralia fenstrat Australia

    Just noting that removing it should also effectively fix πŸ› Fix access checks for bundle permissions to avoid triggering a config validation error Fixed .

  • πŸ‡¨πŸ‡­Switzerland berdir Switzerland

    See comment in the other issue. I think my suggestion to remove it changed to a pretty strong recommendation to do so based on that.

    Removing the access check would not be that complicated. We need to stop using \Drupal\user\Entity\EntityPermissionsRouteProviderWithCheck, add a deprecation message on it and add a deprecation message on \Drupal\user\Form\EntityPermissionsForm::access(). I guess some tests to adjust and dealing with an empty form then.

    But the problem you have will then still happen *on* the permission page, and this issue doesn't fix that either yet (it will only happen once and then once per menu link being checked). Maybe that could be the follow-up, to replace the getConfigEntitiesToChangeOnDependencyRemoval() call entirely with a new approach?

  • Status changed to Needs review almost 2 years ago
  • πŸ‡ΊπŸ‡ΈUnited States benjifisher Boston area

    Re #9:

    Removing the access check would not be that complicated.

    +1 to that.

    But the problem you have will then still happen *on* the permission page ...

    There is a performance problem when checking many bundles (such as block types) to see whether they have related permissions. Has anyone reported a problem when checking just one?

    When you are viewing the permissions form, you have to go through the same work in order to generate the form. If we want to avoid doing that twice, we could statically cache the result (when checking access) and then use the cached value when generating the form. I think that is out of scope for this issue, and I am not sure there is a need for it.

    I do not know a way to cache more permanently. In theory, a change to any config item could make or break a dependency chain from a permission to a bundle.

    Re #6:

    Just confirming that @acbramley's approach in the MR fixes our major performance issue.

    My understanding from the Slack thread is that the site where this was reported applied the patch from ✨ Add "edit block $type" permissions Fixed to a 10.0 site, and that applying the +1/-1 patch from the follow-up issue #3315042 was also enough to fix the performance issue.

  • πŸ‡¦πŸ‡ΊAustralia fenstrat Australia

    My understanding from the Slack thread is that the site where this was reported applied the patch from ✨ Add "edit block $type" permissions Fixed to a 10.0 site, and that applying the +1/-1 patch from the follow-up issue #3315042 was also enough to fix the performance issue.

    Yeah sorry I wasn't clear there, that is indeed the case. What I was commenting on here was when we reverted #3315042: Remaining tasks for "edit block $type" permissions β†’ , i.e. we were using EntityPermissionsRouteProviderWithCheck rather than EntityPermissionsRouteProvider, then when the approach in the MR in this issue was applied that our performance issues also went away.

  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    Part of the block reorganization we are adding more permissions for blocks so this might be impacted.

  • πŸ‡¨πŸ‡­Switzerland berdir Switzerland

    > There is a performance problem when checking many bundles (such as block types) to see whether they have related permissions. Has anyone reported a problem when checking just one?

    I think the performance aspect is one thing, but it's also that this is using config dependencies in a way that they are not made for IMHO. This function goes recursively through dependencies of dependencies and prepares them all for the situation that is being asked for: what to do if this config entity will be deleted.

    But I'm already happy if we agree on the first step, not trying to handle this in the access check and just display a message about not having any permissions and then we'll see from there.

  • Status changed to Needs work over 1 year ago
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    re-reading the comments

    But I'm already happy if we agree on the first step, not trying to handle this in the access check and just display a message about not having any permissions and then we'll see from there.

    Sounds like this is the path forward.

  • πŸ‡§πŸ‡ͺBelgium borisson_ Mechelen, πŸ‡§πŸ‡ͺ

    We already have a big performance win by applying this patch. I don't understand why this was moved back to needs work, the patch we have already accomplices most about this issue?

  • Status changed to Needs review over 1 year ago
  • πŸ‡¬πŸ‡§United Kingdom catch

    Moving back to needs review - the patch looks fine for what it is. I think we should open a separate issue to remove the permissions check altogether and just show a message in the case of no permissions - that seems fine and a lot better than (apparently) 12 second page loads.

  • πŸ‡¨πŸ‡¦Canada joseph.olstad

    @borisson_ reported in the #performance slack channel that:

    page loads that go from > 12 seconds to ~1 sec for logged in users on local with this patch.

  • Status changed to RTBC over 1 year ago
  • πŸ‡¨πŸ‡­Switzerland berdir Switzerland

    Fair enough. FWIW, users *with* that permission will still see those 12s load times and I'd have preferred to solve it for those as well, but I can live with that being a follow-up.

  • last update over 1 year ago
    29,470 pass
    • catch β†’ committed 43e4b070 on 10.1.x
      Issue #3344789 by acbramley, Berdir, fenstrat, benjifisher, borisson_:...
    • catch β†’ committed cb6824ae on 11.x
      Issue #3344789 by acbramley, Berdir, fenstrat, benjifisher, borisson_:...
  • Status changed to Fixed over 1 year ago
  • πŸ‡¬πŸ‡§United Kingdom catch

    Yeah if this hadn't already been open for six months I'd probably want to keep going here, but since it has let's stop some of the bleeding.

    Committed/pushed to 11.x and cherry-picked to 10.1.x, thanks!

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

Production build 0.71.5 2024