RE: Is is possible to use permissionChecker in a background service?

吴 旻, modified 5 Months ago. Junior Member Posts: 57 Join Date: 5/17/17 Recent Posts

Hello everyone. I am wondering if it is possible to use permissionChecker in a background service without user login. 

 

We know that with a login user and in the thread of that user, one can call PermissionThreadLocal.getPermissionChecker() to get permissionChecker instance of that user and do checks such as permissionChecker.isGroupAdmin(long groupId). Furthermore, the permissionChecker's return is flushed as soon as a user is assgined /unassgined as a site admin.

 

However, if we create a background service and use PermissionChecker permissionChecker = PermissionCheckerFactoryUtil.create(user) , the returning permissionChecker is not flushed when the role of the user is changed. That is, if we change the role of a user to site admin, the permissionChecker.isGroupAdmin will return false until we restart the liferay server. 

 

Here is the code:

 

@Component(
    immediate = true,
    property = {
        "osgi.command.scope=liferay",
        "osgi.command.function=checkPermission"
    },
    service = PermissionCheckerTest.class
)
public class PermissionCheckerTest {
    
    private void print(String s) { System.out.println(s);}    

    public void checkPermission(long userId, long groupId) {
        
        try {
          long oldId = PrincipalThreadLocal.getUserId();    

          PrincipalThreadLocal.setName(userId);
          User user = _userLocalService.getUser(userId);
            
          PermissionCacheUtil.clearCache();
          PermissionCacheUtil.clearPrimaryKeyRoleCache();
          PermissionChecker permissionChecker = PermissionCheckerFactoryUtil.create(user);    

          PermissionChecker opc = PermissionThreadLocal.getPermissionChecker();        
          PermissionThreadLocal.setPermissionChecker(permissionChecker);

          try {
            print("User has site admin role: " + permissionChecker.isGroupAdmin(groupId));
          } finally {
            PermissionThreadLocal.setPermissionChecker(opc);
            PrincipalThreadLocal.setName(oldId);
          }
        } catch (Exception ex) {
            print(ex.getMessage());
        }
    }

    @Reference
    private UserLocalService _userLocalService;    

}

 

I think the problem is the role cache is not flushed. But how could I do it? Thank you very much.

thumbnail
Amos Fong, modified 6 Years ago. Liferay Legend Posts: 2047 Join Date: 10/7/08 Recent Posts
if we change the role of a user to site admin
Are you doing this with LocalServiceUtils or via the UI in control panel? It should clear the proper cache if you are which I think is the entityCache.

If you hit any of the clear cache buttons in control panel > server admin, does that fix the issue?
吴 旻, modified 5 Months ago. Junior Member Posts: 57 Join Date: 5/17/17 Recent Posts
Thank you for your response. We change use roles in panel UI and tried clear server cache in control panel-server admin but it didn't work.

We tracked into permissionChecker's source code and found out that the reason is
UserGroupRoleLocalService.hasUserGroupRole(userId, groupId, SITE_ADMIN, true)
does not work. It can not return true even if the userId-groupId-roleId record exists in UserGroupRole table, due to cache issue. But unfortunatelly we haven't found the method to flush that cache yet...
thumbnail
Olaf Kock, modified 6 Years ago. Liferay Legend Posts: 6441 Join Date: 9/23/08 Recent Posts
吴 旻...It can not return true even if the userId-groupId-roleId record exists in UserGroupRole table, due to cache issue. But unfortunatelly we haven't found the method to flush that cache yet...
Flushing the cache would only be good as a quick check to get to the root of the problem. It should be enough to use the controls in the Control Panel's "System Administration" section and then try again.
If it turns out to really be a cache issue, I'd look after two causes first:
  • Did anyone write to the database manually, without using the API? (If yes: Stop doing so)
  • Are you running a cluster? (if yes: Make sure that the machines are properly communicating and double check the proper cluster setup)
If it's neither of the two, it makes sense to check if there's an invalidation bug in cache handling. The probability is low though.
吴 旻, modified 5 Months ago. Junior Member Posts: 57 Join Date: 5/17/17 Recent Posts
Thank you so much for the hints. Because we are testing on a local pc without any user login, I'm afraid neither is the cause. 

1. Did anyone write to the database manually, without using the API? 

  NO

2. Are you running a cluster? 
  NO

As the source code above, we are testing permission checker via gogo-shell with some commands registerd by an osgi service. Would that cause the problem? Such as different database connection with that used by liferay-ui-called-service ?
thumbnail
Ketan Savaliya, modified 6 Years ago. Regular Member Posts: 117 Join Date: 3/3/11 Recent Posts
吴 旻Thank you for your response. We change use roles in panel UI and tried clear server cache in control panel-server admin but it didn't work.

We tracked into permissionChecker's source code and found out that the reason is
UserGroupRoleLocalService.hasUserGroupRole(userId, groupId, SITE_ADMIN, true)
does not work. It can not return true even if the userId-groupId-roleId record exists in UserGroupRole table, due to cache issue. But unfortunatelly we haven't found the method to flush that cache yet...


Hi,
​​​​​​​

I think you can use below code line to clear cache for any entiry by giving entity impl full package path. in your case UserGroupRoleImpl. 

EntityCacheUtil.clearCache("com.liferay.portal.db.model.impl.Payment_TransactionImpl");


Where Payment_Transaction is your service builder entity. Payment_TransactionImpl is generated by service builder. 


HTH!!
吴 旻, modified 5 Months ago. Junior Member Posts: 57 Join Date: 5/17/17 Recent Posts
It works! Thank you so much!