4

Preface

Let me preface this post by saying that though I have considerable experience with PHP, I am not familiar with Joomla in any meaningful sense. What follows is based on assumptions about how Joomla works and information I have gleaned from folks more familiar with this CMS than I am. I would be grateful if you would correct any misconceptions I have.

The Problem

Fundamentally, this question boils down to: Is it possible for extensions to a Joomla component to define their own permissions?

Defining Permissions for a Component (this part works)

I develop on CiviCRM, a constituent relationship manager for nonprofits which integrates with Joomla, Drupal, WordPress, and Backdrop. CiviCRM is for the most part a standalone application; it integrates with the various CMSes by packaging itself as a module, component, etc., but its core logic is CMS-agnostic.

In the case of Joomla, CiviCRM defines its core permissions in the component's access.xml file. These core permissions work as expected; Joomla's permissions UI renders them, and they can be ticked on and off like any other Joomla permission.

Programmatically Adding New Permission Definitions to a Component (this is where I need help)

Here's where things get tricky. Like Joomla, CiviCRM has an extension system, and extensions to CiviCRM may themselves define new permissions.

CiviCRM extension developers register new permissions by use of a hook function hook_civicrm_permission. CiviCRM core abstracts away the differences between the CMSes and registers extension-defined permissions with the host CMS (e.g., via its implementation of Drupal's hook function hook_permission). In every CMS besides Joomla, this has been worked out so that merely registering a new permission is sufficient to have it displayed alongside other permissions in the relevant UIs, have the CMS store which groups/roles have been granted the permission, and have the CMS enforce it.

As I understand it, Joomla's permissions management UI is built by consuming all the access.xml files for all the Joomla components at run-time. As CiviCRM's extension-defined permissions do not exist in any access.xml file, these permissions are not rendered in the form.

Are there other extensible extensions in the Joomla space? How do they deal with this scenario? The ideal solution would not require CiviCRM extension developers to package their CiviCRM extensions differently -- there's enough to learn about CiviCRM without getting into the particulars of each CMS! If there's a way to modify CiviCRM core (or perhaps make a change to Joomla) so that arbitrary CiviCRM extensions can pass arbitrary permission definitions to Joomla through CiviCRM core, such a solution would be preferable.

Things That Have Been Tried

  • Hacking CiviCRM's access.xml to include permissions defined by extensions appears to work, but clearly this is a maintenance nightmare and a terrible user experience.
  • Our tests show that the permissions are actually enforced if you manage to set them. In a test instance, we did so by hacking the database to set the desired permissions. Again, not a great user experience.
  • I have also considered pretending the Joomla permissions UI doesn't exist and building a separate permissions UI just for CiviCRM on Joomla, but I'd still need to learn about Joomla's permission APIs, and I'd rather not fragment the user experience that way.
2

I realise that this is a bit late but …

Yes, it is possible for extensions to define their own permissions, as really the "permissions" are fundamentally just strings. However, the standard method would be to use the extension's access.xml file you describe above. The steps would be:

  1. Define your permission in the access.xml file (you would generally have associated translatable text strings for the permission's description, etc).

  2. Use Joomla's standard "rules" field type within a form to allow administrators to enter the permissions against users. A little extra work is needed to store these permissions in the database – they're stored in the Joomla Assets table. Eg your extension would have an asset record and the permissions would be stored in a JSON format within the rules field of that record.

  3. Where you want to restrict access you'd need to then check if an individual user had your permission, eg via:

JFactory::getUser()->authorise("your.permission", "com_yourcomponent"); will return true or false, depending on whether the user has or has not the permission.

JHelperContent::getActions("com_yourcomponent"); will return an associative array containing all the permissions associated with your extension, and whether or not the logged on user has each one.

Your description of Joomla's capabilities are correct, as far as I know. One possibility you might consider is storing the definition of your permissions locally in your own component, and then programmatically generating the access.xml file every time you define a new permission. However, I can't say what impact that would have on the user experience.

As you say, you could bypass the Joomla UI and store the permissions directly in the assets record. You'd have to be aware though about the user and user group permissions inheritance that Joomla implements, so I think that this approach might be more problematic.

I suggest you have a look at some of the tutorial information on the web regarding Joomla permissions as the area is fairly complex: this video (which does mention an extension which helps with configuring access control, but I've no experience of it) and this step in the Joomla MVC development tutorial.

Best of luck!

  • Thanks, Robbie. I solved this a little while back and forgot to provide an update, which I've now added in a separate answer. – universalhandle Oct 13 '17 at 14:05
2

I have been meaning to provide an update for some time. I solved this problem with two pull requests to CiviCRM a few months ago. My memory is fading, and I might have some of the Joomla terminology wrong -- edits welcome.

The first pull request makes changes to the component (i.e., the Joomla parts). Basically, instead of using the rules form field type, I created a new type civiperms, which is an extension of the former. I overrode that class's getInput() method so I could put a wrapper around JAccess::getActions(), which is responsible for getting the permissions from access.xml. The rest of the method is unchanged. My wrapper queries CiviCRM for any dynamically added permissions and appends those to the ones Joomla found on its own.

The second pull request is more concerned with CiviCRM-isms and is not likely of interest to anyone trying to solve this problem for a different platform.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.