Get all "permissions" for user


#1

Hii there,

a while ago, I have made this question on how I could get a specific permission/right for a user.
Now I want to do pretty much the same but except of a specific permission, I want to have all the permissions for a user.

The structure I’m dealing with looks like this (exact result may vary depending on the roles a user has):

Array
(
    [0] => Cake\ORM\Entity Object
        (
            [role_id] => 1
            [access_cms] => 
            [edit_settings] => 
            [view_media] => 
            [add_media] => 
            [edit_media] => 
            [delete_media] => 
            [add_posts] => 
            [edit_posts] => 
            [view_private_posts] => 
            [view_unlisted_posts] => 1
            [[new]] => 
            [[accessible]] => Array
                (
                    [*] => 1
                )

            [[dirty]] => Array
                (
                )

            [[original]] => Array
                (
                )

            [[virtual]] => Array
                (
                )

            [[hasErrors]] => 
            [[errors]] => Array
                (
                )

            [[invalid]] => Array
                (
                )

            [[repository]] => Permissions
        )

    [1] => Cake\ORM\Entity Object
        (
            [role_id] => 2
            [access_cms] => 
            [edit_settings] => 
            [view_media] => 
            [add_media] => 
            [edit_media] => 
            [delete_media] => 
            [add_posts] => 
            [edit_posts] => 
            [view_private_posts] => 
            [view_unlisted_posts] => 
            [[new]] => 
            [[accessible]] => Array
                (
                    [*] => 1
                )

            [[dirty]] => Array
                (
                )

            [[original]] => Array
                (
                )

            [[virtual]] => Array
                (
                )

            [[hasErrors]] => 
            [[errors]] => Array
                (
                )

            [[invalid]] => Array
                (
                )

            [[repository]] => Permissions
        )

)

So I want a list containing all the permissions a user has (if none of the roles have a specific permission, do not add it to the list).
So in this example one role has view_unlisted_posts so It should be in the list, but no others will be in there (role_id can be ignored).
Now let’s say one of the roles has the access_cms permission, then add that to the list as well.
If the permission is found at least once in any role, it can be added, else, it shouldn’t be added.

I hope I’m not too confusing with this :stuck_out_tongue:


#2

You’re looking for something other than a simple

TableRegistry::get('Permissions')->find()->where(['role_id IN' => $roles])

? Where $roles might be pre-loaded from elsewhere, or might be a query of its own.


#3

I have not even considered doing it like that yet.
Unfortunately, I just returned home so I can’t test it yet.
Will report back when I get to work again Thursday.


#4

So, I’ve tried doing this but it leaves me with a huge object that I cannot understand what to do with it.

Cake\ORM\Query Object
(
    [(help)] => This is a Query object, to get the results execute or iterate it.
    [sql] => SELECT Permissions.role_id AS `Permissions__role_id`, Permissions.access_cms AS `Permissions__access_cms`, Permissions.edit_settings AS `Permissions__edit_settings`, Permissions.view_media AS `Permissions__view_media`, Permissions.add_media AS `Permissions__add_media`, Permissions.edit_media AS `Permissions__edit_media`, Permissions.delete_media AS `Permissions__delete_media`, Permissions.add_posts AS `Permissions__add_posts`, Permissions.edit_posts AS `Permissions__edit_posts`, Permissions.view_private_posts AS `Permissions__view_private_posts`, Permissions.view_unlisted_posts AS `Permissions__view_unlisted_posts` FROM permissions Permissions WHERE role_id in (:c0,:c1)
    [params] => Array
        (
            [:c0] => Array
                (
                    [value] => Kikioboeru\Kikioboeru\Model\Entity\Role Object
                        (
                            [id] => 1
                            [name] => Administrator
                            [_joinData] => Cake\ORM\Entity Object
                                (
                                    [user_id] => 1
                                    [role_id] => 1
                                    [[new]] => 
                                    [[accessible]] => Array
                                        (
                                            [*] => 1
                                        )

                                    [[dirty]] => Array
                                        (
                                        )

                                    [[original]] => Array
                                        (
                                        )

                                    [[virtual]] => Array
                                        (
                                        )

                                    [[hasErrors]] => 
                                    [[errors]] => Array
                                        (
                                        )

                                    [[invalid]] => Array
                                        (
                                        )

                                    [[repository]] => UsersRoles
                                )

                            [[new]] => 
                            [[accessible]] => Array
                                (
                                    [name] => 1
                                    [permissions] => 1
                                    [users] => 1
                                )

                            [[dirty]] => Array
                                (
                                )

                            [[original]] => Array
                                (
                                )

                            [[virtual]] => Array
                                (
                                )

                            [[hasErrors]] => 
                            [[errors]] => Array
                                (
                                )

                            [[invalid]] => Array
                                (
                                )

                            [[repository]] => Kikioboeru/Kikioboeru.Roles
                        )

                    [type] => integer
                    [placeholder] => c0
                )

            [:c1] => Array
                (
                    [value] => Kikioboeru\Kikioboeru\Model\Entity\Role Object
                        (
                            [id] => 2
                            [name] => Member
                            [_joinData] => Cake\ORM\Entity Object
                                (
                                    [user_id] => 1
                                    [role_id] => 2
                                    [[new]] => 
                                    [[accessible]] => Array
                                        (
                                            [*] => 1
                                        )

                                    [[dirty]] => Array
                                        (
                                        )

                                    [[original]] => Array
                                        (
                                        )

                                    [[virtual]] => Array
                                        (
                                        )

                                    [[hasErrors]] => 
                                    [[errors]] => Array
                                        (
                                        )

                                    [[invalid]] => Array
                                        (
                                        )

                                    [[repository]] => UsersRoles
                                )

                            [[new]] => 
                            [[accessible]] => Array
                                (
                                    [name] => 1
                                    [permissions] => 1
                                    [users] => 1
                                )

                            [[dirty]] => Array
                                (
                                )

                            [[original]] => Array
                                (
                                )

                            [[virtual]] => Array
                                (
                                )

                            [[hasErrors]] => 
                            [[errors]] => Array
                                (
                                )

                            [[invalid]] => Array
                                (
                                )

                            [[repository]] => Kikioboeru/Kikioboeru.Roles
                        )

                    [type] => integer
                    [placeholder] => c1
                )

        )

    [defaultTypes] => Array
        (
            [Permissions__role_id] => integer
            [Permissions.role_id] => integer
            [role_id] => integer
            [Permissions__access_cms] => boolean
            [Permissions.access_cms] => boolean
            [access_cms] => boolean
            [Permissions__edit_settings] => boolean
            [Permissions.edit_settings] => boolean
            [edit_settings] => boolean
            [Permissions__view_media] => boolean
            [Permissions.view_media] => boolean
            [view_media] => boolean
            [Permissions__add_media] => boolean
            [Permissions.add_media] => boolean
            [add_media] => boolean
            [Permissions__edit_media] => boolean
            [Permissions.edit_media] => boolean
            [edit_media] => boolean
            [Permissions__delete_media] => boolean
            [Permissions.delete_media] => boolean
            [delete_media] => boolean
            [Permissions__add_posts] => boolean
            [Permissions.add_posts] => boolean
            [add_posts] => boolean
            [Permissions__edit_posts] => boolean
            [Permissions.edit_posts] => boolean
            [edit_posts] => boolean
            [Permissions__view_private_posts] => boolean
            [Permissions.view_private_posts] => boolean
            [view_private_posts] => boolean
            [Permissions__view_unlisted_posts] => boolean
            [Permissions.view_unlisted_posts] => boolean
            [view_unlisted_posts] => boolean
        )

    [decorators] => 0
    [executed] => 
    [hydrate] => 1
    [buffered] => 1
    [formatters] => 0
    [mapReducers] => 0
    [contain] => Array
        (
        )

    [matching] => Array
        (
        )

    [extraOptions] => Array
        (
        )

    [repository] => Cake\ORM\Table Object
        (
            [registryAlias] => Permissions
            [table] => permissions
            [alias] => Permissions
            [entityClass] => Cake\ORM\Entity
            [associations] => Array
                (
                )

            [behaviors] => Array
                (
                )

            [defaultConnection] => default
            [connectionName] => default
        )

)

Again, all I want is a simple array/object that contains a list of all the rights a user has :\

EDIT: using all() or execute() on it just throws a big error in my face:

Cannot convert value of type Kikioboeru\Kikioboeru\Model\Entity\Role to integer

EDIT2: I got around the error by the following code:

return TableRegistry::get('Permissions')
        ->find()
        ->where([
          'role_id IN' => collection($this->roles)
            ->extract('id')
            ->toArray()
        ]);

But this still leaves two separate entities instead of one…


#6

Ive written some code to illustrate what results I want to receive back, but it’s horribly inefficient and throws errors:

$res = TableRegistry::get('Permissions')
  ->find()
  ->where([
    'role_id IN' => collection($this->roles)->extract('id')->toArray()
  ]);
$permissions = [];

foreach($res as $entity) {
  foreach($entity as $obj) {
    foreach($obj as $permission => $value) {
      if($permission == "role_id" || $permission == "*")
        continue;

      if(in_array($permission, $permissions))
        continue;
            
      if($value)
        $permissions[] = $permission;
    }
  }
}

This gives me the following back:

array:10 [▼
  0 => "access_cms"
  1 => "edit_settings"
  2 => "add_media"
  3 => "edit_media"
  4 => "delete_media"
  5 => "add_posts"
  6 => "edit_posts"
  7 => "view_private_posts"
  8 => "view_unlisted_posts"
  9 => "view_media"
]

I hope someone can help me finding a cleaner solution to this.
the $permissions may also be an object instead of an array ofcourse.


#7

I’ve managed to make the code a bit smaller, but I still feel it can be done better:

foreach($res as $entity) {
    foreach($entity->toArray() as $permission => $value) {
      if($permission == "role_id" || $permission == "*") {
        continue;
      }

     if(in_array($permission, $permissions)) {
       continue;
     }
          
     if($value) {
       $permissions[] = $permission;
     }
  }

#8

There’s probably some collection method that would simplify your code, but it seems to me that the main problem here is that your database structure is restrictive. More common might be a many-to-many join table between the roles table and a very simple permissions table (just id and name). Then when you contain permissions with the roles, you get back the concise list you’re looking for quite directly. Also, it is then easy to add new permissions by adding a row in the database, instead of needing to write a migration every time.


#9

We… ehm… have not thought of doing that…
We have a similar thing for assigning users to roles but not for the permissions themselves.

I’ll throw it into the project discussion.
Sounds like it’s a way more viable option in the long run (I was already looking at my table and thinking “this might become an issue”).
Thanks!