Recently on various lists and in the trackers the question of handling more complex ACL structures and expected behaviors has come up. This is something that obviously partly the responsibility of the platform and partly the responsibility of the application, but I think to make the application work we need to clarify about what the platform classes are expecting.
There are two related scenarios in which this has become an issue.
1. When an application wants to have multiple types of assets but not use categories.
2. When an application wants to have multiple types of categories using the dot separated names offered by JCategory.
The short version of what happens in these cases is that the assets always are set to be children of the root asset. This means that they cannot inherit permissions from their extension in the way that developers are expecting.
This is going to look long but I have narrowed it down to 4 specific questions and the rest is just explaining the background to each question.
So, as we know, JAccess is the key class but there are a lot of relationships including to JTable, JTableAssets, JCategories, JTableCategory, JTableExtensions, JFormFieldRules, Even though some of them are in now in legacy they actually in the real world of applications have a lot of dependencies and are typical of the kinds of things developers on the platform want to do.
Let's look at JTableContent which is probably the example most developers use if they want an example table that tracks assets and see why this is happening.
The important code is here:
To get the parent we check the catid. If there is no catid we use the default. The default is to use the root asset (parent_id=1).
Question 1: Why is it that the default is not to parent to the extension given that the extension is already specified in _getAssetName()?
I believe this is why the CMS ended up mandating that all items in its content type extensions require categories. However I don't really understand the logic that says that because you are not in a category we don't have any information on permissions based on the component.
If there is no extension of course it makes sense to fall back to the root. That means that in a simple platform application there won't be a problem, you just fall back to the base permissions where ever you have figured out to save those--I guess you can just use a string that could be stored in the configuration.
Question 2: Would it be reasonable for us to add a fall back layer in JTableContent that goes to component as a parent if no catid is present? Or does that violate something in the JAccess model?
This would be fine in JTableContent as far as I know and would make a better example asset tracking table class in my opinion.
Now thinking about the second group, those that want to use categories but want to have multiple types of categories. As mentioned above in principle this is done by created a dot separated name to be used as the extension in the categories table. So for example if in the CMS I wanted to create categories for banners clients in addition to categories for banners I would use com_banners.clients as the extension. In doing this I would add a category.clients section to the xml. If I did this, I would notice a few things.
When I go to create a category.clients category it at first appears to work perfectly until I notice that the category permissions are inheriting only from global configuration not from com_banners. This is because the asset for the new category has an asset name like: com_banners.clients.category.78 and is parented to the global configuration. This is a variation of the issue above except that categories usually is well behaved and has the code to find the extension name and use that as the parent. But in this case it is looking for an extension named com_banners.clients.
It is easy enough to make the asset name for a specific category.clients asset not include the .clients string but that creates other issues, for example the rules field then does not know to use category.clients for the rules since it uses the asset name for that. So, it's easy enough to change the asset name but that has other ramifications for the classes I listed above. Again these are fixable but not without knowing the answer to Question 3.
Question 3: What is the expected asset name when an application wants to allow multiple subtypes of an asset type within an "extension" (the three or more levels are important)? In my example is it com_banners.category.xx or is it com_banners.category.clients.xx but it does not have to be categories.
I know all the categories classes are legacy but the same issue will apply if a developer tries to do something similar (have an asset type with multiple variations or have nested assets or have multiple "extensions" whatever they end up being called). For example any application using user permissions will have users and is still going to need a user manager and a way to set the global permissions (a concept that is built in all over the place) and we are still going to need a way to set permissions for who can do those things) in any platform application. Even if it is a separate application that does user management there still need to be rules about who makes rules.
I also wanted to mention that although it will never happen if people use the API correctly in practice we have found that in many cases for various reasons having to do with the messiness of data and the ability of users to directly modify the database this query:
$query = $db->getQuery(true);
$query->select('rules');
$query->from('#__assets');
$query->where('parent_id = 0');
$db->setQuery($query);
$result = $db->loadColumn();
will at times return multiple items (or no items).
Question 4: Would it be reasonable to add a test for returning multiple records here?
And if so would we attempt to select the one where the first 4 letters of the name are
'root' ? Or use the minimum lft and/or maximum rgt value? Or should it just throw an
exception and be done?
Normally I would probably just send in pull request for question 4 to add an exception but in the context of the other questions I feel like I need a better understanding of what's supposed to be happening.
Thanks for your patience,
Elin