Diagnosing Permission Problems

A simple utility Snippet to help diagnose permission issues and a bit of detail about how MODX permissions work.

By Bob Ray  |  November 15, 2023  |  7 min read
Diagnosing Permission Problems

When I first thought of the Snippet below, I thought it was a brilliant idea. On further reflection, I have to confess that it’s a lot less useful than I thought. I hope, though, that it’s still useful for helping people understand Revolution permissions. You may find it helpful in specific situations. For Object Policies (more on this in a bit), it is specific to Resources, but those are the most common things you want to diagnose the permissions for.

What the Snippet Tells Us

One extremely common issue with MODX Revolution permissions is knowing whether a user has a particular permission or not. Users can get permissions in various places and if they’re granted a particular permission somewhere, they may have it in places you wouldn’t expect them to.

This can be especially confusing in your permission system is complex. It can be very difficult to be sure whether a user has, or doesn’t have, a permission in a given situation. I’ve spent some time wondering why taking away a certain permission didn’t prevent the user from performing a certain action, only to find out after a lot of frustrating debugging, that I hadn’t actually taken away the permission in the first place.

In this article, we’ll look at a simple utility Snippet that will tell you whether a user has a permission or not. If the user has the permission, the Snippet will also report the type of policy that contains the permission.

Policy Types

Before we look at the Snippet, we need to take a short detour to consider the two types of permissions on policies used in MODX Revolution: context and object permissions. Remember that a policy is just a list of specific permissions. Each permission is either checked (granted) or unchecked (not granted) on the policy.

Permissions in context policies determine what the user can do and see in a particular context. If the user has save_document in the Manager ('mgr' context), they have it throughout the Manager. The master list of context policies is the default Administrator Policy installed during the initial setup of MODX Revolution.

Permissions in object policies determine what the user can do and see with a particular object such as a Resource or Element. It would be more correct to say that object policies determine what the user can do with a particular group of objects such as a Resource group or category. This is because the only way to grant either kind of permission is to create a User Group and attach a policy to it. The master list of object permissions for Resources is the default Resource Policy installed during the initial setup of MODX Revolution. The Element and Media Source policies are also object policies.

It can be confusing to distinguish the permissions because some of them have the same names. For example, there is a create permission in the Administrator Policy and the same permission in the Resource Policy. The Administrator Policy ones take precedence. If the user does not have create permission in the context policy, they can’t create any new objects at all. If they do have that permission, they still can’t create new Resources unless they also have the create permission on the Resource Policy.

To see the list of permissions, go to System (gear icon), Access Control Lists. On the Policies tab, right-click on a Policy and select “Update Policy”.

Why Would I Need to Know This?

The reason it’s important to understand this distinction is that MODX tests the permissions in two different ways by MODX and by any code you write that needs to check for a specific permission.

Context policy permissions are tested with $modx->hasPermission('permission_name').

Object policy permissions, such as add_children, are tested with $object->checkPolicy('permission_name'), where $object is an instance of the type of object the user might want to do something with (like a resource or element). The object is most often a Resource, but could be an Element, or Media Source. For the current Resource, you’ll often see code like this: $modx->resource->checkPolicy('some_permission'). In both cases, the method will return true if the user has the permission, and false if not.

Selecting a Method

As you’ve probably guessed, if we want to select a method to see whether a user has a specific permission, we need to know if we’re testing for a context permission or an object permission. If the permission is a context permission (like the ones listed on the Administrator Policy), you check with $modx->hasPermission('permission_name'). If, on the other hand, it’s an object policy (like the ones listed on the Resource Policy), you use something like $resource->checkPolicy('permission_name').

Which Method Does the Snippet Use?

As a matter of fact, it uses both. Because we’re doing that, we need to list whether the permission is a context or object permission. We do that based on which method is used to check for the permission.

The Code

Put this tag on a page where you’d like to see the report:

[[!CheckPermission? &permission=`permission_name`]]

For the object permissions, the list will only report permissions that are available for the page you put the tag on.

Paste this code into a Snippet called CheckPermission:

/* CheckPermission Snippet */

$perm = $modx->getOption('permission', $scriptProperties, '');

$output = ' Checking Current user for permission: ' . $perm . ' <br>';

$hasPermission = $modx->hasPermission(trim($perm));

$output .= $perm . ' -- ' . $hasPermission ? 'YES' : 'No' . '(Context)';

$hasPermission = $modx->resource->checkPolicy(trim($perm));
$output .= '<br>'. $perm . '-- ' .  $hasPermission? 'YES' : 'No' . '(object)';

return $output;

Usage

You can put the Snippet tag in the content of any page, then log in as the user you want to check the permission for and view the page. Remember to use a different browser where you’re not logged into the Manager when you view the page.

You can also put the Snippet in a Template and view multiple pages that use that Template.

How It Works

First, we get the name of the permission to check for from the $scriptProperties array. We perform the two checks, and add the results to the $output variable. At the end of each result we append the type (Context or Object) to the message.

Notice that the Snippet is called uncached (with the !). This is important because we don’t want the cached value of the Snippet, which could be incorrect in the current situation.

Limitations

Of course our Snippet is no use at all if the Resource is hidden from the user or the user doesn’t have permission to view it, and it won’t do us any good in the Manager.

Our Snippet also won’t work well as a Plugin (where returned output usually doesn’t appear on the screen), though you can print the output to the error log. The Snippet, as written won’t work with Elements either. Fortunately, most permission checking involves Resources and the Snippet works fine with them as long as the user can see them. If you need to check permissions in a Plugin or during the execution of another Snippet, you can try using echo to display the results. It may or may not work, and on a busy Manager page, it may take you a while to spot the output. We mentioned using the error log for the output earlier. That would look like this:

$modx->log(modX::LOG_LEVEL_ERROR, $output);

Another way to go is to create a Chunk called “Debug” and write the output to the Chunk with this code, then use QuickUpdate to look at the Chunk’s content:

/* CheckPermission code above goes here */
$chunk = $modx->getObject('modChunk', array('name' => 'Debug'));
$chunk->setContent($output);

For both of the methods above, put the code at the end of the Snippet.

Another limitation, though not a serious one, is that you can’t use the Snippet to check permissions when running PHP code from the command line or in your code editor. In those cases, MODX bypasses the permission system entirely, so every user has every permission.

Wrapping Up

Once you know for sure whether a user has, or doesn’t have, a specific permission, you can spend your time trying to figure out why the user has the permission or not and what to do about it. After each change you make, you can recheck the user’s permission status to see if you’re making progress.


Bob Ray is the author of the MODX: The Official Guide and dozens of MODX Extras including QuickEmail, NewsPublisher, SiteCheck, GoRevo, Personalize, EZfaq, MyComponent and many more. His website is Bob’s Guides. It not only includes a plethora of MODX tutorials but there are some really great bread recipes there, as well.