The role hierarchy lets you define which roles are included in other roles, so you don't have to assign all of them to each user. In applications with many roles, this configuration grows quickly and it's hard to tell which exact roles belong to a given user. Symfony 8.2 makes role hierarchies shorter to write and easier to debug.
Wildcards in the Role Hierarchy
Role hierarchies list their roles one by one. If your application defines e.g.
ROLE_BLOG_AUTHOR, ROLE_BLOG_EDITOR and ROLE_BLOG_MODERATOR, and all of
them should include ROLE_BLOG_READER, you need one entry for each of them, plus
another one whenever you add a new blog role.
In Symfony 8.2, the keys of the role hierarchy can include the * wildcard to
match an entire family of roles:
1 2 3 4 5 6 7 8 9
# config/packages/security.yaml
security:
# ...
role_hierarchy:
ROLE_*: ROLE_USER
ROLE_*_MODERATOR: ROLE_MODERATOR
ROLE_BLOG_*: ROLE_BLOG_READER
ROLE_BLOG_MODERATOR: [ROLE_BLOG_DELETE_POST, ROLE_BLOG_LOCK_POST]
Roles don't need to be listed in the hierarchy to match a wildcard. With this
configuration, a user with ROLE_BLOG_COMMENTER also gets ROLE_BLOG_READER
and ROLE_USER, even if that role doesn't appear anywhere in the configuration.
The * character is only considered a wildcard when it's wrapped by underscores
(ROLE_*_FOO) or placed after an underscore at the end of the role name (ROLE_BAR_*).
Keys such as ROLE_BLOG* or ROLE_*BLOG are still regular role names.
Wildcards are patterns, not roles, so you can only use them in the keys of the
hierarchy. For example, is_granted('ROLE_BLOG_*') still looks for a role with
that exact name and wildcards are never returned by the getReachableRoleNames()
and getParentRoleNames() methods.
The debug:roles Command
Wildcards simplifies role configuration but can make debugging a bit more difficult.
If you need to know the exact roles granted to a user, Symfony 8.2 adds a debug:roles
command that does that for you:
1 2 3 4 5 6 7 8 9 10 11 12
# displays the whole role hierarchy
$ php bin/console debug:roles
# displays all the roles granted by the given role(s)
$ php bin/console debug:roles ROLE_BLOG_MODERATOR
* ROLE_BLOG_MODERATOR
* ROLE_BLOG_DELETE_POST
* ROLE_BLOG_LOCK_POST
* ROLE_USER
* ROLE_MODERATOR
* ROLE_BLOG_READER
Add the --tree option to see why each role is granted, including the wildcards
that were matched:
1 2 3 4 5 6 7 8 9 10 11
$ php bin/console debug:roles ROLE_BLOG_MODERATOR --tree
ROLE_BLOG_MODERATOR
├── ROLE_*
│ └── ROLE_USER
├── ROLE_*_MODERATOR
│ └── ROLE_MODERATOR
├── ROLE_BLOG_*
│ └── ROLE_BLOG_READER
├── ROLE_BLOG_DELETE_POST
└── ROLE_BLOG_LOCK_POST
Role Hierarchy Graph in the Profiler
Symfony 7.4 introduced the debug:security:role-hierarchy command to dump the
role hierarchy as a Mermaid chart. In Symfony 8.2, that chart is displayed
directly in the Security panel of the profiler, so you can check the roles
available in your application without running any command:
The next logical step for me personally would be to allow
*on the value side of the role, so aROLE_DEVELOPERorROLE_SUPER_ADMINcan just become aROLE_*to include every role of your app.am I not yet awake, or is something wrong with this:
The * character is considered a wildcard when it's placed at the end of the role name.
So,
ROLE_BLOG*is a wildcard right? Not a regular role name?@KaiEichinger that's not possible. Matching a glob against a known value (the role passed as input to the hierarchy) does not require knowing all the possible roles. Listing all the matching roles requires that knowledge, which does not exist in SecurityBundle (the role hierarchy is not required to contain all the roles you use)
@Joris you are right. The original text wans't fully precise about this. We updated it. Thanks!