Problem/Motivation

Following on from http://drupal.org/node/1945390#comment-7247250 with further detail in http://drupal.org/node/1945390#comment-7215306, we ideally want user_access to be an injectable service.

Proposed resolution

Convert user_access into a service that can be injected wherever needed.

Remaining tasks

  • Experimental conversion
  • Initial sanity check
  • Finalize conversion
  • Convert all instances in code to use the new service, including test conversion
  • Reviews (tests should be covered by existing tests using the new service)
  • Documentation updates

User interface changes

None

API changes

All instances of user_access would be changed to the new service.

#1945390: Convert book_admin_edit to a new-style FormInterface implementation

Follow-ups

#2045361: Mark user_access as deprecated
#2048171: [meta] Replace user_access() calls with $account->hasPermission() wherever possible.

CommentFileSizeAuthor
#88 user_access-1966334-88.patch13.25 KBdawehner
#88 interdiff.txt2.02 KBdawehner
#86 drupal-1966334-86.patch13.22 KBParisLiakos
#80 drupal-1966334-80.patch14.93 KBParisLiakos
#80 interdiff.txt871 bytesParisLiakos
#77 drupal-1966334-77.patch14.92 KBParisLiakos
#77 interdiff.txt3.76 KBParisLiakos
#71 drupal-1966334-71.patch15.42 KBdawehner
#71 interdiff.txt4.07 KBdawehner
#69 drupal-1966334-69.patch13.89 KBdawehner
#69 interdiff.txt3.12 KBdawehner
#65 user_access-1966334-65.patch13.7 KBdawehner
#64 1966334-64.patch7.68 KBfubhy
#62 1966334-62.patch8.87 KBfubhy
#57 1966334-57.patch7.04 KBfubhy
#57 interdiff.txt3.88 KBfubhy
#54 1966334-54.patch7.03 KBfubhy
#46 interdiff.txt1.3 KBdawehner
#46 drupal-1966334-46.patch21.63 KBdawehner
#45 user_access-1966334-45.patch20.33 KBdawehner
#43 1966334-43.patch15.7 KBfubhy
#40 1966334-40.patch18.96 KBfubhy
#38 1966334-38.patch18.85 KBfubhy
#36 1966334-36.patch14.33 KBfubhy
#33 drupal-1966334-33.patch18.91 KBdawehner
#29 interdiff.txt1.39 KBAlan Evans
#29 drupal-user-access-service-1966334-29.patch16.61 KBAlan Evans
#27 drupal-user-access-service-1966334-27.patch15.39 KBAlan Evans
#27 interdiff.txt7.46 KBAlan Evans
#24 drupal-user-access-service-1966334-24.patch13.91 KBAlan Evans
#22 drupal-user-access-service-1966334-22.patch13.92 KBAlan Evans
#20 drupal-user-access-service-1966334-20.patch12.56 KBAlan Evans
#14 drupal-user-access-service-1966334-14.patch11.56 KBAlan Evans
#12 drupal-user-access-service-1966334-12.patch11.55 KBAlan Evans
#9 drupal-user-access-service-1966334-9.patch9.12 KBAlan Evans
#5 drupal-user-access-service-1966334-5.patch7.79 KBAlan Evans
#3 drupal-user-access-service-1966334-3.patch7.82 KBAlan Evans
#1 drupal-user-access-service-1966334-1.patch6.5 KBAlan Evans
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Alan Evans’s picture

Status: Active » Needs review
Issue tags: +WSCCI, +WSCCI-conversion
FileSize
6.5 KB

Initial stab at converting user_access into a service - I'd like to get some early feedback or sanity checking on this if possible before working on it further. Would be good to get an idea if the direction is reasonable before starting on converting all calls and tests.

Status: Needs review » Needs work

The last submitted patch, drupal-user-access-service-1966334-1.patch, failed testing.

Alan Evans’s picture

Status: Needs work » Needs review
FileSize
7.82 KB

... of course it's usually helpful to add all the right files to the patch ... trying again ...

Status: Needs review » Needs work

The last submitted patch, drupal-user-access-service-1966334-3.patch, failed testing.

Alan Evans’s picture

Status: Needs work » Needs review
FileSize
7.79 KB

Not sure what's going on with the tests (all green locally, and impact should be limited) ... rerolled with a whitespace fix

Status: Needs review » Needs work

The last submitted patch, drupal-user-access-service-1966334-5.patch, failed testing.

Alan Evans’s picture

puzzling results ...

Alan Evans’s picture

Status: Needs work » Needs review
Alan Evans’s picture

Silly me ... turns out that any test that alters permissions and then checks with user_access does need converting already, because the drupal_static key changed (and user_access() still uses the old key)

Crell’s picture

Status: Needs review » Needs work
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.php
@@ -29,6 +31,12 @@ public static function getInfo() {
+    $this->access = drupal_container()->get('user.access');

This should be \Drupal::service('user.access') now.

+++ b/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.php
@@ -23,7 +24,7 @@ public static function getInfo() {
+    $this->access = drupal_container()->get('user.access');

Ibid.

+++ b/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.php
@@ -56,9 +57,9 @@ function testUserPermissionChanges() {
+    drupal_static_reset('Drupal\user\UserAccess::check');

This is right out, because drupal_static() should never be used inside an object.

+++ b/core/modules/user/lib/Drupal/user/UserAccess.php
@@ -0,0 +1,44 @@
+  public function check($string, $account = NULL) {
+    global $user;
+
+    if (!isset($account)) {
+      $account = $user;
+    }

The default-to-global logic is flawed to begin with. Let's just make $account required. From a service perspective, that's what we want as it makes the object idempotent.

+++ b/core/modules/user/lib/Drupal/user/UserAccess.php
@@ -0,0 +1,44 @@
+    // To reduce the number of SQL queries, we cache the user's permissions
+    // in a static variable.
+    // Use the advanced drupal_static() pattern, since this is called very often.
+    static $drupal_static_fast;
+    if (!isset($drupal_static_fast)) {
+      $drupal_static_fast['perm'] = &drupal_static('Drupal\user\UserAccess::check');

drupal_static() is completely unnecessary inside an object. That's what protected object properties are for.

+++ b/core/modules/user/lib/Drupal/user/UserAccess.php
@@ -0,0 +1,44 @@
+      $role_permissions = user_role_permissions($account->roles);

Blargh. Can we turn that function into a service, too? Or, put it on some existing service? Or, something?

Actually, looking at the function, it should just be a method on this service, and then this service depends on the DB connection. Done. Then we can deprecate both functions.

Alan Evans’s picture

Many thanks for the review, Crell. Will work on a revision shortly.

Alan Evans’s picture

Status: Needs work » Needs review
FileSize
11.55 KB

Attaching a messy progress patch with a few test fails for now ... will work on this more ...

Alan Evans’s picture

Status: Needs review » Needs work
Alan Evans’s picture

Status: Needs work » Needs review
FileSize
11.56 KB

And as it turns out, if you add a new method, it actually helps if you call it instead of the old func..

Alan Evans’s picture

Status: Needs review » Needs work
dawehner’s picture

+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.phpundefined
@@ -21,6 +21,8 @@ class CommentLinksTest extends CommentTestBase {
+  protected $access;

Needs docs.

+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.phpundefined
@@ -29,6 +31,12 @@ public static function getInfo() {
+    $this->access = \Drupal::service('user.access');

+++ b/core/modules/user/lib/Drupal/user/RoleStorageController.phpundefined
@@ -36,8 +36,8 @@ public function resetCache(array $ids = NULL) {
+    \Drupal::service('user.access')->resetCache();
+    \Drupal::service('user.access')->resetRoleCache();

Afaik we should use $this->container->get('user.access')

+++ b/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.phpundefined
@@ -10,6 +10,7 @@
+  protected $access;

@@ -23,7 +24,7 @@ public static function getInfo() {
+    $this->access = \Drupal::service('user.access');

Maybe accessService would describe better what this class is about.

+++ b/core/modules/user/lib/Drupal/user/UserAccess.phpundefined
@@ -0,0 +1,122 @@
+  /**
+   * Implements \Drupal\Core\ControllerInterface::create().
+   */

Should be {@inheritdoc} now.

+++ b/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.phpundefined
--- /dev/null
+++ b/core/modules/user/lib/Drupal/user/UserAccess.phpundefined

+++ b/core/modules/user/user.services.ymlundefined
@@ -13,3 +13,6 @@ services:
+  user.access:
+    class: Drupal\user\UserAccess
+    arguments: ['@database']

I'm wondering whether this should be something provided by user module or whether this is a central core service.

+++ b/core/modules/user/lib/Drupal/user/UserAccess.phpundefined
@@ -0,0 +1,122 @@
+  public function resetCache() {
+    // @todo -rename to permisisonCache to distinguish from roles cache
+    $this->perm = array();
+  }

I guess it would make sense to have a method which resets both at the same time. What about just ->reset()?

+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.phpundefined
@@ -21,6 +21,8 @@ class CommentLinksTest extends CommentTestBase {
+  protected $access;

Needs docs.

+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.phpundefined
@@ -29,6 +31,12 @@ public static function getInfo() {
+    $this->access = \Drupal::service('user.access');

+++ b/core/modules/user/lib/Drupal/user/RoleStorageController.phpundefined
@@ -36,8 +36,8 @@ public function resetCache(array $ids = NULL) {
+    \Drupal::service('user.access')->resetCache();
+    \Drupal::service('user.access')->resetRoleCache();

Afaik we should use $this->container->get('user.access')

+++ b/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.phpundefined
@@ -10,6 +10,7 @@
+  protected $access;

@@ -23,7 +24,7 @@ public static function getInfo() {
+    $this->access = \Drupal::service('user.access');

Maybe accessService would describe better what this class is about.

+++ b/core/modules/user/lib/Drupal/user/UserAccess.phpundefined
@@ -0,0 +1,122 @@
+  /**
+   * Implements \Drupal\Core\ControllerInterface::create().
+   */

Should be {@inheritdoc} now.

Alan Evans’s picture

Sorry, I wasn't looking for a review on this just yet, just a testbot run (hence the "needs work" status).

Thanks for reviewing though - I can still use your comments as a TODO list for cleanup.

There's one task remaining before I start looking at the cleanup (making $account required and checking what breaks), then once both of those are done there would be a lot of conversion left to do.

dawehner’s picture

I just hope you try to keep user_access() in this issue (which calls the service then) and people can start and use the service in new code.

Alan Evans’s picture

ugh ... sorry, got swamped with work and thought this issue was more blocked than it actually was: I was trying to get the suggestion from #18 into place with no luck at all. Turns out that a full drush cache clear is often not enough to rebuild everything - I had to reinstall my test drupal install to get this working.

Back on course now hopefully, and should have a new patch soon.

Alan Evans’s picture

Status: Needs work » Needs review
FileSize
12.56 KB

Attaching a version mainly for the test bot again, just to check that the now-implemented last outstanding suggestion from #10 doesn't have unexpected side effects ($account is now a required argument).

I've also incorporated the suggestion in #18 so user_access remains as a wrapper around the service. The optionality of $account is retained in the procedural wrapper then, but removed in the service.

There are a number of cleanups still to do and outstanding issues from #16. I'm on the fence though about whether this should be a core service: user.module is always required anyway so moving this to a core service is mainly going to come down to a question of where people would prefer it. I'm leaning toward leaving it where it is for the moment, as I think that's where most people would expect to find it. It vaguely seems to "belong" in the user module namespace, but I acknowledge that's entirely subjective.

I'd agree incidentally that both caches seem to consistently need a reset at the same time, so would make sense to combine those.

Not attaching interdiffs until I've got to a point where I'm more or less happy with the basis: I haven't kept local history tidy enough to do that yet.

Alan Evans’s picture

Status: Needs review » Needs work
Alan Evans’s picture

Status: Needs work » Needs review
FileSize
13.92 KB

OK, I'm reasonably happy with this one. I've incorporated all previous review suggestions I think, with the exception of moving the service into a core service - I've left that in the user.module space unless there are strong opinions for making it a core service.

As mentioned previously, I've taken the suggestion of leaving user_access as a still-functional wrapper that can be used. That way we can have a follow-up task to convert all other instances of user_access to use the new service (assuming it gets in of course ...). It's probably not a huge job, but I'd want further opinions on the current patch before converting everything.

Status: Needs review » Needs work

The last submitted patch, drupal-user-access-service-1966334-22.patch, failed testing.

Alan Evans’s picture

Status: Needs work » Needs review
FileSize
13.91 KB

Reverting the RoleStorageController change as $this->container doesn't seem to be set - broke tests.

Crell’s picture

+++ b/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.php
@@ -10,6 +10,13 @@
+  /**
+   * A UserAccess service object used for checking permissions within this test.
+   *
+   * @var \Drupal\user\UserAccess
+   */
+  protected $accessService;
   protected $admin_user;
   protected $rid;

At least a line break between the properties here. I won't ask you to document the other two since they're unrelated to this patch, but if you want to while you're in there no one will object. :-) (Also, $adminUser, not $admin_user, for object properties.)

+++ b/core/modules/user/lib/Drupal/user/UserAccess.php
@@ -0,0 +1,138 @@
+class UserAccess implements ControllerInterface {

This class is a pure service, not a controller. It should not be using ControllerInterface. It should just register with the container as service directly via user.services.yml.

We also need an interface defined for user access checking that this class can implement. That way someone else can swap it out with a MongoDB-based one, or whatever.

This also suggests that the service should also be responsible for collecting and saving user/role data, or at least some service should be. That way you can swap out the entire user permission system. Hm... Not sure if that's scope creep or not.

+++ b/core/modules/user/lib/Drupal/user/UserAccess.php
@@ -0,0 +1,138 @@
+      $result = db_query("SELECT rid, permission FROM {role_permission} WHERE rid IN (:fetch)", array(':fetch' => $fetch));

This should be using the injected DB connection.

Alan Evans’s picture

This should be using the injected DB connection.

Well that's just embarrassing ... that was after all the whole point of injecting it. Oh well, I need to be more careful.

Alan Evans’s picture

  • Added space + docs to UserPermissionTest properties
  • Removed controller implementation - somehow had it in my head that I needed the create method and therefore controller also
  • Added interface for the class
  • Corrected the db query

Needless to say, I'm not overly keen to add to the scope of this, but I'll have a think about what would need adding to the new interface+class here to support what you were suggesting.

Alan Evans’s picture

So I think what you'd be suggesting is, aside from the 2 functions that are already included in this UserAccess class (user_role_permissions and user_access), the following would also need inclusion:

  • user_role_names
  • user_roles
  • user_role_load
  • user_permission_get_modules
  • user_role_change_permissions
  • user_role_grant_permissions
  • user_role_revoke_permissions

Maybe not user_role_load necessarily, which is based on the entity system and has its own swapability built in. However, if the other role functions are included, it only seems to make sense to include it also.

Alan Evans’s picture

Converted user_role_permissions to just be a wrapper.

Crell’s picture

+++ b/core/modules/user/lib/Drupal/user/UserAccessInterface.php
@@ -0,0 +1,46 @@
+  public function check($string, $account);

I'm not sure check() is the best name here. It's not really self-descriptive. hasPermission()? Which would then, I think, want to take ($account, $permission), not ($string, $account), so that it naturally reads $account hasPermission $permission.

+++ b/core/modules/user/lib/Drupal/user/UserAccessInterface.php
@@ -0,0 +1,46 @@
+   * @param $roles
+   *   An array whose keys are the role IDs of interest, such as $user->roles.

Specify $param array $roles for completeness.

+++ b/core/modules/user/lib/Drupal/user/UserAccessInterface.php
@@ -0,0 +1,46 @@
+  public function userRolePermissions($roles);

This should be type hinted to an array.

We should probably also inject this service into at least one of the other services that us currently calling user_access(). Probably the PermissionAccessCheck class is a good candidate. We don't need to all of them, but at least one to prove that it works. :-)

I'm still torn about converting the entire function set. It makes sense, but I worry about scope creep. Of course, with the other functions still hard coded to the database the swappability here doesn't buy us all that much.

Crell’s picture

Status: Needs review » Needs work

Actually, bejeebus in IRC just pointed me at this issue, which is going to have a radical impact on anything going on here: #1872876: Turn role permission assignments into configuration.. :-(

So, yeah, we should wait for that to go in, and then revisit this issue to move all of the functions into a service.

fubhy’s picture

Actually, bejeebus in IRC just pointed me at this issue, which is going to have a radical impact on anything going on here: #1872876: Turn role permission assignments into configuration.. :-(

So, yeah, we should wait for that to go in, and then revisit this issue to move all of the functions into a service.

I asked whether we can commit #1872876: Turn role permission assignments into configuration. without the last part of cleaning up stale permissions on module uninstallation for now so we can proceed with this patch. If it's a "nay" we should proceed with this. Should be much faster to get this to a clean state than the other patch due to the dependency on #1199946: Disabled modules are broken beyond repair so the "disable" functionality needs to be removed that it would imply in that case. It's not that much work to re-roll the patch over at #1872876: Turn role permission assignments into configuration. anyways.

dawehner’s picture

Title: Convert user_access to an injectable service » Extend the router provider interface so that Views can override routes
Component: user system » routing system
Assigned: Alan Evans » Unassigned
Category: task » bug
Priority: Normal » Critical
Status: Needs work » Needs review
Issue tags: -WSCCI-conversion +VDC
FileSize
18.91 KB

Here is a rerole, which injects the user access service into the permission access checker.

Sadly the tests did not passed due to the following issue: #2015721: Adding a role to a user throws a php error

dawehner’s picture

Title: Extend the router provider interface so that Views can override routes » Convert user_access to an injectable service
Component: routing system » user system
Category: bug » task
Priority: Critical » Normal
Issue tags: -VDC +WSCCI-conversion

Oh I think this was dreditor.

Status: Needs review » Needs work

The last submitted patch, drupal-1966334-33.patch, failed testing.

fubhy’s picture

Status: Needs work » Needs review
FileSize
14.33 KB

Fixing the fails and integrating with AccountInterface from #1825332: Introduce an AccountInterface to represent the current user.

Wonder if we should move this to Drupal\Core now that we got that AccountInterface? Has to be role agnostic then too though.

Status: Needs review » Needs work

The last submitted patch, 1966334-36.patch, failed testing.

fubhy’s picture

Status: Needs work » Needs review
FileSize
18.85 KB

Whoops, forgot a file.

dawehner’s picture

+++ b/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.phpundefined
@@ -24,48 +43,47 @@ public static function getInfo() {
+    \Drupal::service('user.access')->reset();
...
+    \Drupal::service('user.access')->reset();

Should/could we also call $this->container->get('user.access')->reset()?

Potential follow ups:

  • Convert parts of UserPermissionTest to a proper unit test
  • Add a Drupal::userAccess() or similar method
  • Move diverse things from user to core
fubhy’s picture

FileSize
18.96 KB

Should/could we also call $this->container->get('user.access')->reset()?

Of course! Missed that. Thanks

Potential follow ups:

Convert parts of UserPermissionTest to a proper unit test
Add a Drupal::userAccess() or similar method
Move diverse things from user to core

Agreed. (2) and (3) are consequentially the same though :)

dawehner’s picture

+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.phpundefined
@@ -31,6 +38,12 @@ public static function getInfo() {
+  function setUp() {

Should have an @inheritdoc

+++ b/core/modules/user/lib/Drupal/user/Access/PermissionAccessCheck.phpundefined
@@ -17,6 +18,23 @@
+  protected $userAccess;

+++ b/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.phpundefined
@@ -10,7 +10,26 @@
+  protected $accessService;

We should make that consistent.

+++ b/core/modules/user/lib/Drupal/user/RoleStorageController.phpundefined
@@ -36,8 +36,7 @@ public function resetCache(array $ids = NULL) {
+    \Drupal::service('user.access')->reset();

Entity controller can have services injected now.

+++ b/core/modules/user/lib/Drupal/user/UserAccessInterface.phpundefined
@@ -0,0 +1,51 @@
+   * Determines the permissions for one or more roles.
...
+  public function userRolePermissions(array $roles);

So we agreed that there should be a follow up for this as well.

Status: Needs review » Needs work

The last submitted patch, 1966334-40.patch, failed testing.

fubhy’s picture

Status: Needs work » Needs review
FileSize
15.7 KB

So we agreed that there should be a follow up for this as well.

Okay, moved it out again. I like the idea of having a single service for managing all this stuff in one place as #28 suggests but yeah, that's scope creep.

Anyways there's still something wrong in the upgrade pass. Don't have time to look at those fails now.

Status: Needs review » Needs work

The last submitted patch, 1966334-43.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
20.33 KB

Point one: Think about patches if they get smaller :) (UserAccess and UserAccessInterface got lost)

For example "BASIC MINIMAL PROFILE UPGRADE, FREE ACCESS" will fail.

dawehner’s picture

FileSize
21.63 KB
1.3 KB

Mh, this fixes some bits but still has small upgrade path fails. You can't create a User object as somehow the container is not ready yet.

Status: Needs review » Needs work

The last submitted patch, drupal-1966334-46.patch, failed testing.

dawehner’s picture

Berdir has the point that there should be a method on the account interface (hasPermission) instead of having a separate service.

Berdir’s picture

The reason for doing it as a method is that it's easier to use (we could still have a proxy method, sure), but mostly that after permissions are also stored in the role config entity, this comes down to the following pseudo-code:

function hasPermission($permission) {
  foreach ($roles as $role) {
    if ($role->hasPermission($permission)) {
      return TRUE;
    }
  }
  return FALSE;
}

Maybe with a bit caching and stuff, but no database queries involved anymore. Why make a service of this?

Combine it with passing the current user into the access checks as discussed yesterday, the permission and role checks become really simple and nice (apart form the +/, stuff).

Crell’s picture

I agree. Let's just make this a method on the User class and be done with it. No service needed.

Crell’s picture

Title: Convert user_access to an injectable service » Convert user_access to User::hasPermission()

Retitling.

fubhy’s picture

Assigned: Unassigned » fubhy

Yeah.. agreed

Berdir’s picture

Note that there are still a few places where global user is not yet an AccountInterface, e.g. UpgradePathTestBase. #2017207: [meta] Complete conversion of users to Entity Field API has fixes for that.

fubhy’s picture

Status: Needs work » Needs review
FileSize
7.03 KB

Just playing around a bit... I think we can drop the static user access cache. Even more so once #1872876: Turn role permission assignments into configuration. lands which moves permissions onto the role entity.

I am not sure if we should do more here.. The rest should probably happen in #1872876: Turn role permission assignments into configuration..

One thing that bothers me is that addRole(), etc. currently use $rid instead of a full $role object. We might want to change that.

fubhy’s picture

Assigned: fubhy » Unassigned

Status: Needs review » Needs work

The last submitted patch, 1966334-54.patch, failed testing.

fubhy’s picture

Status: Needs work » Needs review
FileSize
3.88 KB
7.04 KB

Forgot a return statement.

Status: Needs review » Needs work

The last submitted patch, 1966334-57.patch, failed testing.

dawehner’s picture

I'm sorry but it feels really wrong to have the same code twice.

Berdir’s picture

We have two quite different classes that implement the same interface, they have to have similar implementations, but it will change more I think. I'm adding a few additional methods to that interface in the issue references in #53, they will have "duplicate "/similar implementations there as well.

I expect they will not be that similar in the end, If we go with msonnabaums idea, we might e.g. add something like a UserOneSession class, that subclasses UserSession and just returns TRUE in hasPermission(). We'll see.

Berdir’s picture

Wow, we have 23 upgrade path tests now ;)

As mentioned before, if you merge in the changes to UpgradePathTestBase from #2017207: [meta] Complete conversion of users to Entity Field API, you should have a green patch.

fubhy’s picture

Status: Needs work » Needs review
FileSize
8.87 KB

As mentioned before, if you merge in the changes to UpgradePathTestBase from #2017207: Complete conversion of users to Entity Field API, you should have a green patch.

Checking if that is true!

fubhy’s picture

Issue tags: +needs profiling

Okay, @berdir and I agreed that we should do some profiling despite the fact that we both also concluded that it probably won't make much of a performance difference as we are really just doing the static caching to cut on function calls (slightly). So if anyone want's to do that today, go ahead... Otherwise I'll get back to it tomorrow.

fubhy’s picture

FileSize
7.68 KB
dawehner’s picture

Here is a unit test for both User and UserSession.

Status: Needs review » Needs work
Issue tags: -WSCCI, -needs profiling, -WSCCI-conversion

The last submitted patch, user_access-1966334-65.patch, failed testing.

fubhy’s picture

Status: Needs work » Needs review

#65: user_access-1966334-65.patch queued for re-testing.

Status: Needs review » Needs work
Issue tags: +WSCCI, +needs profiling, +WSCCI-conversion

The last submitted patch, user_access-1966334-65.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
3.12 KB
13.89 KB

So, there is a problem for phpunit/autoloading if you use the simpletest UI, so let's setup stuff different.

Status: Needs review » Needs work
Issue tags: -WSCCI-conversion

The last submitted patch, drupal-1966334-69.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
4.07 KB
15.42 KB

So never assume that simple code always work.

Status: Needs review » Needs work
Issue tags: -WSCCI, -needs profiling

The last submitted patch, drupal-1966334-71.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review

#71: drupal-1966334-71.patch queued for re-testing.

Status: Needs review » Needs work
Issue tags: +WSCCI, +needs profiling

The last submitted patch, drupal-1966334-71.patch, failed testing.

dawehner’s picture

Issue tags: +PHPUnit

Adding tag

dawehner’s picture

The problem with the current patch seems somehow that the global $user is not the one which is logged in the test.

ParisLiakos’s picture

Status: Needs work » Needs review
FileSize
3.76 KB
14.92 KB

this should be green

ParisLiakos’s picture

Issue tags: +PHPUnit Blocker

tag

dawehner’s picture

This was certainly a good fix.

+++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.phpundefined
@@ -144,15 +145,12 @@ protected function setUp() {
+    // Load rolest.

Maybe something like "// Load roles of the user."?

ParisLiakos’s picture

FileSize
871 bytes
14.93 KB

yes:)

Status: Needs review » Needs work
Issue tags: -PHPUnit, -WSCCI, -needs profiling, -PHPUnit Blocker

The last submitted patch, drupal-1966334-80.patch, failed testing.

ParisLiakos’s picture

Status: Needs work » Needs review
Issue tags: +PHPUnit, +WSCCI, +needs profiling, +PHPUnit Blocker

#80: drupal-1966334-80.patch queued for re-testing.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Thank you!

fubhy’s picture

Very good. Thanks. RTBC +1

YesCT’s picture

Issue tags: +RTBC July 1

This issue was RTBC and passing tests on July 1, the beginning of API freeze.

ParisLiakos’s picture

FileSize
13.22 KB

reroll after adding methods to AccountInterface got in

note: size difference is due to exact same changes in UpgradePathTestBase happened there:)

Status: Reviewed & tested by the community » Needs work

The last submitted patch, drupal-1966334-86.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
2.02 KB
13.25 KB

OMG this patch has an error level of over 9000!

fubhy’s picture

Of course, this is sparta! If we blow up tests, we always reach the 9000. Easy. SPARTA!

ParisLiakos’s picture

Issue tags: -needs profiling

Overall Diff Summary

Run #51dc95f06eeea Run #51dc958dcd69b Diff Diff%
Number of Function Calls 56,913 56,961 48 0.1%
Incl. MemUse (bytes) 11,246,168 11,247,168 1,000 0.0%
Incl. PeakMemUse (bytes) 11,294,288 11,295,288 1,000 0.0%

which is because user_access is a wrapper now, and it is called 48 times:P

ParisLiakos’s picture

Status: Needs review » Reviewed & tested by the community

re-rtbcing, i totally missed load -> loadMultiple changed thanks dawehner:)

Dries’s picture

Status: Reviewed & tested by the community » Needs work

Committed to 8.x. Two follow-ups:

1) Can we mark user_access as deprecated?

2) Can you explain what profiling you have done? This patch removes some caching. It does not look to be material due to caching at different levels but it would be good to understand what kind of profiling you did.

Thanks!

xjm’s picture

Status: Needs work » Fixed
Issue tags: +Needs followup

Switching for a followup :)

dawehner’s picture

Here is the follow up: #2045361: Mark user_access as deprecated

@fubhy, please speak about the caching.

xjm’s picture

Thanks @dawehner!

fubhy’s picture

This patch removes some caching. It does not look to be material due to caching at different levels but it would be good to understand what kind of profiling you did.

Exactly.. So while we removed the direct static caching in user_access() we are still using the values from the $role entities (which are already in memory) and the role assignments of the user entity (also in memory). Instead of directly returning the cached values from user_access() we now go to through both, user entity and role entity, to determine access:

$user->hasPermission() -> $role->hasPermission() (for all roles of a user)

This makes the whole system much more solid and decoupled as it's only bound to the static entity caching instead of multiple, custom caching layers (which you would have to be aware of in order to do proper cache invalidation upon write / delete operations, e.g. when deleting a role). Now, when you remove a user role assignment, or add a new role to the user, or add a new permission to a role, it is automatically reflected in the next $user->hasPermission() check without the need of any cache invalidation (entity system takes care of that).

The only thing that we add are some (very few) additional function calls which obviously doesn't affect performance much.

EDIT: As to the question "what kind of profiling was done" we would have to ask @ParisLiakos.

Hey King Leonidas? Can you give us some detail on the profiling you did?

fubhy’s picture

Issue tags: -Needs followup

Untagging

ParisLiakos’s picture

Hey King Leonidas? Can you give us some detail on the profiling you did?

I believe you are talking to me:p

it was against the D8 HEAD (at the time) front page. First run was before the patch second run after patch..the only change was 48 more function calls which completely make sense since user_access is now a wrapper..when we have converted everything to call hasPermission() directly there will be no performance difference..that 1kb of ram i didnt even bother to check more

xjm’s picture

Well, what @effulgentsia pointed out is that the real thing to profile would be a site with a lot of roles, and with individual users with lots of roles. I seriously doubt there would actually be a negative impact from the patch, and overall the removal of the cache can only be a good thing, I think, as @fubhy explains in #96.

xjm’s picture

Issue summary: View changes

experimental conversion done

fubhy’s picture

Crell’s picture

Title: Convert user_access to User::hasPermission() » Change Notice: Convert user_access to User::hasPermission()
Priority: Normal » Critical
Status: Fixed » Active
Issue tags: +Needs change record
dawehner’s picture

Status: Active » Needs review
jibran’s picture

Title: Change Notice: Convert user_access to User::hasPermission() » Convert user_access to User::hasPermission()
Priority: Critical » Normal
Status: Needs review » Fixed
Issue tags: -Needs change record

Fixed some formatting issues, change notice looks good to me. Thanks @dawehner.

agentrickard’s picture

Status: Fixed » Needs work
Issue tags: +Needs change record

Sample code in the change notice needs to account for cases where you want to check access for a user other than the one making the request.

tim.plunkett’s picture

Status: Needs work » Fixed
Issue tags: -Needs change record

Updated

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

Anonymous’s picture

Issue summary: View changes

Updated issue summary.