User-Specific Pages

Suppose that you want to have a number of users on your site that can each see only their own pages (pages they create, or pages you create for them). It's not uncommon in MODX to want to show users their own subset of pages in the Manager, and/or the front end. Many MODX developers have trouble creating the permissions for member-specific pages. The concepts are simple, once you understand them, but getting there can be a challenge. This tutorial is designed to help you understand the process for creating user-specific Resources.

If you need more help on Permissions, please don't email me with questions. Instead, ask your questions on the MODX Forums so that others can learn from the answers, people who know more than I do can answer them, and I don't end up answering the same questions over and over.

Here are some things to remember:

  • In order for MODX to do anything user-specific, the user has to be logged in, so MODX knows who the user is.
  • Protecting (hiding) resources in the Manager and in the front end are two separate operations. Hiding a resource in the Manager will have no effect in the front end, and hiding resources in the front end will have no effect on the Manager.
  • MODX knows the Manager as the 'mgr' context and the front end as the 'web' context (or other front-end context you've created).
  • If you don't want to hide pages in the front end, never create a Resource Group Access ACL entry with a context other than 'mgr' (in other words, don't use a context of 'web' or other front-end context you create).
  • Users don't have to be members of the Administrator group to use the Manager — in fact, if you *don't* put them in that group, it will generally make your life easier and give you more flexibility in controlling what they can see and do.
  • If you want users to see only their own pages, you need a separate User Group *and* a separate Resource Group for each user (name both after the user to make things easier).
  • Context Access ACL entries and Resource Group Access ACL entries are two very different things. There's more information on that here. Pay attention to which phrase is used in all security tutorials.
  • Resources in a Resource Group that is connected to a User Group are protected (hidden) from users outside the group.
  • Resources that don't meet the condition above are not protected (hidden) from anyone. Putting Resources in a Resource Group does *not* protect them. They are only protected when that Resource Group is connected with a User Group.

Burn the last two things on the list above into your brain. Over 90% of the problems people have with member-specific page permissions (and permissions in general) relate to these principles.

Note that if you want to hide or control access to all resources for certain users, that is done with a Context Access ACL entry as explained in this tutorial.

If you want to control access to some resources for certain users (e.g., to let them edit but not publish certain resources), that's explained in this tutorial.

This tutorial is about creating user-specific pages that can be seen and/or edited by their "owners" but are hidden from other users and (optionally) from the general public. Notice that there are actually two separate situations here:

  • You want users who can only *edit* their own pages, but you want all pages visible to the public. In that case, you want to hide the pages in the Manager, but not in the front end. An example of this would be a public User Bio page where users can edit their own Bio and see, but not edit, the Bio pages of others.
  • You want all pages completely hidden from everyone except the page owner (i.e., hidden on the Manager and the front end). An Example would be a business information page that should only be seen and edited by certain members.

The permission settings for both cases are similar. In both cases, you want to hide the Resources from other users in the Manager. In the second case, you also want to hide them from other users in the front end. I'll note the differences in the tutorial with an optional section on hiding the page in the front end.

Preview

Here is a preview of the basic steps necessary to only show specific resources to specific users:

  1. Protect *all* resources on the site so resources only you should see (as the admin Super User) are hidden from all other users.
  2. Create the users.
  3. Create a Role for the users.
  4. Create a User Group for each user.
  5. Put the user in the group.
  6. Create one or more Resources for each user.
  7. Create a Resource Group for each user.
  8. Put each user's Resource(s) in the user's Resource Group.
  9. Create a Resource Group Access ACL entry with a context of 'mgr' for each user linking the user's User Group with the user's Resource Group.
  10. (Optionally, to hide the Resources in the front end) Create a Resource Group Access ACL entry with a context of 'web' for each user linking the user's User Group with the user's Resource Group.

Step-by-step Tutorial

Here are the steps for creating Manager users who can and cannot see specific resources. In this tutorial, each user is the "page owner" of specific pages that only he or she can see or edit. The links in the list below are to other mini-tutorials explaining how to perform each step. If you have performed the first steps in another tutorial, be sure to create new User Groups, new resources and new Resource Groups for this one.

  1. Using Package Manager, download and install the DefaultResourceGroup plugin. Set the drg_groups property to AllDocs
  2. (Optional) Add all existing documents in the root of the tree to the AllDocs Resource Group (you can do this later). Child resources will be hidden automatically if the parent is hidden.
  3. Create a Role for the users. Call the Role "PageEditor" and give it an Authority level of 15
  4. Create the Users
  5. Create a User Group for each user (named after the user) and add the user to it
  6. Create one or more resources for each user (named after the user).
  7. Create a Resource Group for each user (named after the user) and add the user's resources to it
  8. Create a Resource Group Access ACL Entry for each User Group:
    1. Go to Security | Access Controls
    2. Click on the "User Groups" tab if it is not the current tab
    3. Right-click on the user's User Group
    4. Select "Update User Group"
    5. Click on the "Resource Group Access" tab
    6. Click on the "Add Resource Group" button
    7. Use the following values in the ACL entry:
      • Resource Group: the user's Resource Group
      • Context: mgr
      • Minimum Role: PageEditor
      • Policy: Resource
    8. Click on the "Save" button in the dialog
    9. Click on the "Save" button at the upper right
  9. (optional) If you want the user's resource(s) hidden from everyone but the user in the front end as well, repeat the steps just above (from clicking on the "Add Resource Group" button) above and use 'web' for the context.
  10. Repeat the steps above for each user.
  11. Under Security in the Top Menu, select "Flush Permissions". You may also need to "Flush All Sessions" and clear the site cache before your permissions take effect.

Because we have linked each user's User Group to the user's Resource Group with a Resource Group Access ACL entry, those resources are now protected. That means that the users in other groups will not see them in the Resource tree and will have no access to those resources.

Dude, Where are My Resources?

Don't be alarmed if all the users' Resources disappear from the tree. Since you are not a member of any of the groups, they are hidden from you as well. There are several different solutions to this if you would like to see (and edit) the resources. The easiest is to edit your own User Profile and make yourself a sudo (i.e., "all-powerful") user. Go to Security | Manage Users. Right-click on the 'admin' user and select "Update User" in the drop-down list. On the "General" tab, check the "Sudo User" checkbox at the upper right and then click on the "Save" button. Flush permissions (and maybe Flush Sessions) on the "Security" menu, and the Resources should reappear.

Making yourself a sudo user is a good solution if you are the only administrator on the site, but if there are other Manager users on the site who should be able to see and edit the resources, you almost certainly don't want to make them sudo users. I'll discuss some other solutions in a bit after we handle another problem.

My Users Can't Log In to the Manager

In order for any user to log into the Manager, the user needs access to the 'mgr' Context. That means creating a Context Access ACL entry for the user group. We could do this individually for each user's User Group, but since users can belong to more than one user group, we'll create a new user group and grant the access there:

  1. Go to Security | Access Controls
  2. Click on the "User Groups" tab if it is not the current tab
  3. Click on the "New User Group" button
  4. Call the user group "ManagerUsers
  5. Click on the "Save" button in the dialog

First, we need to add the users to the group:

  1. Right-click on "ManagerUsers" User Group
  2. Click on the "Add User to Group" button
  3. Add a user with a Role of PageEditor
  4. Click on the "Save" button in the dialog
  5. Repeat for all the Users who will have their own pages

Next, we'll give the users access to the Manager

  1. Right-click on "ManagerUsers" User Group
  2. Select "Update User Group"
  3. Click on the "Context Access" tab
  4. Click on the "Add Context" button
  5. Use the following values in the ACL entry:
    • Context: mgr
    • Minimum Role: PageEditor
    • Policy: Content Editor
  6. Click on the "Save" button in the dialog
  7. Click on the "Save" button at the upper right

The users can log in to the Manager now, but they won't see resources in the Web context until we create another Context Access ACL entry for that context:

  1. Right-click on "ManagerUsers" User Group
  2. Select "Update User Group"
  3. Click on the "Context Access" tab
  4. Click on the "Add Context" button
  5. Use the following values in the ACL entry:
    • Context: web
    • Minimum Role: PageEditor
    • Policy: Resource
  6. Click on the "Save" button in the dialog
  7. Click on the "Save" button at the upper right

The users should now be able to log in and see their resources (but not those of other users), but there's one more thing to do.

Hiding the Other Resources

If you have logged in as one of your users, you may have noticed that the resources in other user's Resource Groups are hidden, but all the other resources on the site are still visible (the Home page, for example). You don't want these users editing the Home page and probably a number of other pages. Remember that resources that are not in a Resource Group connected to a User Group are not protected from anyone. Protecting them is why we created the AllDocs Resource Group above and installed the DefaultResourceGroup plugin.

The DefaultResourceGroup plugin will put all new Resources in the AllDocs group, but you need to put all the existing Resources that the users shouldn't see into the AllDocs Resource Group. If you put a container resource into the AllDocs group, you don't have to put the children there (they will be hidden automatically). Do that now (including the users' resources if you created them before installing the plugin).

After putting all the resources in the AllDocs group, if you check, you'll see that they are still not hidden from the users. That's because that Resource Group isn't connected to any User Group.

To hide them from the users, create a Resource Group Access ACL entry using the same steps we outlined above but right-click on the "Administrator" User Group. Use the following values in the ACL entry:

  • Resource Group: AllDocs
  • Context: mgr
  • Minimum Role: Super User
  • Policy: Resource

Save the ACL entry and flush things again. The resources should be hidden from the users. We've protected the resources by connecting their Resource Group to the Administrator User Group. Because the PageEditor users are not members of that group, the resources are hidden from them.

Unhiding the Resources for Other Manager Users

I mentioned above the case where you have other Manager users who should be able to see and edit all the Resources but shouldn't be sudo users. If you don't have any users like that, you can skip this section.

One, not every efficient, alternative is to add each of those other users to each User Group. If you do this, I'd recommend creating a new Role for them first (call it something like MasterPageEditor), with an authority level more powerful than the PageEditor users (say, with an authority level of 10 for the Role), and adding them to the group with that Role. That will allow you to give them more rights with the resources than the PageEditor users have (e.g. deleting, duplicating, etc).

A better alternative, now that you have the AllDocs group protected, is to give the other users access to the resources simply by putting those other Manager users in their own User Group and connecting the User Group to the AllDocs Resource Group with a Resource Group Access ACL entry like the ones we created above. Use a context of 'mgr' and a Policy of 'Resource' (unless you want to restrict their rights too — in that case use the Policy we created above or a new Policy). That will let them see and edit all the resources on the site. If you don't want that, you can create a new Resource Group just for them and put all the resources they should see (including the users' resources) into it. Then connect that Resource Group to their User Group instead of the AllDocs Resource Group.

It's OK to put the same user in more than one User Group and the same Resource in more than one Resource Group (though things are simpler if you can avoid it). Just remember that if you give a user access to a Resource Group in any Resource Group Access ACL entry, nothing you do elsewhere will take away their right to the Resources in that Resource Group.

Controlling What Users Can Do With Their Resources

Once you have the users restricted to their own pages, you may discover that you want to limit what they can do with them. You may want to let them edit pages, for example, but not delete or duplicate them. A complete explanation is beyond the scope of this tutorial, but the general principles are fairly simple. What users can do with a Resource is controlled by two things:

  • The permissions in Policy attached to the Context Access ACL entry giving them rights to the Manager
  • The permissions in the Policy attached to their Resource Group Access ACL entry that gives them rights to the Resources

The permissions in the Context Access ACL entry are broad permissions that cover the whole Manager, and if the user doesn't have them, granting them elsewhere won't have any effect. If the user doesn't have the save_document permission, for example, they won't be able to save a document, ever, no matter what else you give them. Note that giving the user a permission here doesn't necessarily guarantee that they can perform the action. If a Resource is protected (as we've done here), the user will also have to have the necessary permission in the Policy attached to the Resource Group Access ACL entry giving them rights to the Resource Group.

For the purposes of this tutorial, make sure that the Policy attached to the Context Access ACL entry for the users has the permissions they will need, such as save_document, edit_document, load, list, and view. If you don't want them to be able to duplicate Resources, take that permission away from them there, but don't worry about removing other resource-related permissions, we'll do that in the Resource Group Access Policy.

Most of what you want to do will be controlled by the permissions in the Policy attached to the Resource Group Access ACL entry that gives them rights to the Resources. In the example above, we used the Resource Policy, which grants them full rights, but you can use a different Policy (Important: don't modify the Resource Policy). On the "Access Policies" tab (under Security | Access Controls), duplicate the "Resource" Policy. Give the Policy a name (e.g., PageEditorPolicy). Uncheck any permissions you don't want the user to have and save the Policy.

Next, edit the Resource Group Access ACL entries for the users. Go to Security | Access Controls | User Groups tab. Right-click on the User Group and select "Update User Group" on the drop-down list. On the Resource Group tab, right-click on the ACL entry giving them rights to their Resources and select "Update Resource Group Access" on the drop-down list. Click on the arrows at the right side of the "Policy" field and select the Policy you just created, then click on the "Save" button of the dialog. Flush things on the Security menu and your users should have only the permissions you granted them.

Wrap Up

In this tutorial, we discussed how to create user-specific pages that only certain users can see and edit in the Manager and we saw how to hide those pages in the front end as well. Hopefully, you also got a little closer to understanding MODX Revolution security permissions.

Security Resources at Bob's Guides

 

My book, MODX: The Official Guide - Digital Edition is now available here. The paper version of the book may still be available from Amazon.

If you have the book and would like to download the code, you can find it here.

If you have the book and would like to see the updates and corrections page, you can find it here.

MODX: The Official Guide is 772 pages long and goes far beyond this web site in explaining beginning and advanced MODX techniques. It includes detailed information on:

  • Installing MODX
  • How MODX Works
  • Working with MODX resources and Elements
  • Using Git with MODX
  • Using common MODX add-on components like SPForm, Login, getResources, and FormIt
  • MODX security Permissions
  • Customizing the MODX Manager
  • Using Form Customization
  • Creating Transport Packages
  • MODX and xPDO object methods
  • MODX System Events
  • Using PHP with MODX

Go here for more information about the book.

Thank you for visiting BobsGuides.com

  —  Bob Ray