JAccess, Rules, Categories and more complex ACL -- Expected behavior?

184 views
Skip to first unread message

Elin Waring

unread,
Jul 8, 2012, 8:05:05 AM7/8/12
to joomla-de...@googlegroups.com
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

Elin Waring

unread,
Jul 24, 2012, 7:56:46 PM7/24/12
to joomla-de...@googlegroups.com
I guess no one is going to answer the four  questions so I'll have to try my best to make up my own anwers.  This is what I am thinking based on spending some more time on it and also on a possible generic (non CMS specific) replacement abstract class for JTableContent. 

The version of JAccess in the 11.4 platform is both highly CMS specific (e.g. it specifies a  component folder as the place to look for the rules)and yet does not work in the CMS when a component wants to just inherit from global settings.  The newer APIs are more generic but still have the some of the same basic issues.

Now I initially thought that the problems people not using the categories system were having were because they were probably failing to set $recursive to true here:

That may be true, but actually I think it is more complex than that or there is a second issue.

First the root asset has two different ways of being found or set. Sometimes it is the asset with parent_id of 0 and sometimes it is the asset with the key of   1, which are obviously not necessarily the same thing.
(that's the query that brings sites down)
Also relevant:


If we are going to use the query then I think the answer to question # 4 must be yes and we should also take a look at that hard coding of 1 as well.  Would it make sense to use  JTableNested's getRootID() method which already deals with the possibility of this with an unexpected value exception? Or something like it that can handle 0? Or else address this in some other way?  

Also it seems to me that this sanity check is totally ignoring the insanity of having multiple asset records with parent_ids of 0. 


For #3

I think I have this right.

An asset has  dot separated name. Reading from right to left, the rightmost level is a unique identifier for the record within the table in which it is stored, either a numeric key or a string name. 
The rest of the name by default is just the table name. However, an application can make up its own human readable name instead, like "article" or "category" and these can be more complex and can make searching easier by using structured naming like users.category.note.117 instead of #__categories.117, but they are essentially arbitrary from the point of view of JAccess, all it cares about are lft rgt parent_id and level. 
 


At the point that the table name is used, we just tack on the id and make the root asset the parent. 

It seems to be that the answer to #4 is that if an application wants to implement separate acl within a subsection (e.g. different types of categories within one component or different content types but all stored in the same #__tablename) this should be managed by the application probably with extra fields. In the CMS we give you a built in way of doing that easily with the categories system, but if a developer doesn't want to use the category system she has to implement some other method of managing hierarchy because by themselves JTable and JTableContent are not going to do anything about handling this.  Indeed if you do not extend
_getAssetParentId()  you will always get a parent of 1 no matter what else you do. So I think neglecting to specifically do that is a second mistake people are making in attempting to use ACL while extending JTable. 

For question #2 my feeling is that a generic content table should help make this happen correctly by including a property optionally identifying a parent table (e.g. #__categories or #__extensions but it could be anything) and a property identifying the field name of the field with key to that table if needed. (We already use these in the CMS in the form of catid most places and extension in categories).  That lets us escape categories if we want to (and developers both inside and outside the CMS very much  want to do so, which is why we are getting questions on all the  lists about it). 

If we did that it would also help to handle question 1.  

So to summarize:
Question 1: Why is it that the default is not to parent to the extension given that the extension is already specified in _getAssetName()? 
Because it is hard coded to 1 unless the extended class does something else.

Question 2: Would it be reasonable for us to add a fall back layer in a replacement for JTableContent  that goes to something as a parent (and specifically in the CMS if no catid is present)? Or does that violate something in the JAccess model?

Yes it would be reasonable (especially since JTableContent it is in legacy)

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)? 

It's up to the application except that the last part has to be unique within the table holding the assets.

Question 4: Would it be reasonable to add a test for returning multiple records here?  (this is the query for parent_id)

yes and it would be good to handle the results properly.


Sorry,

Elin
Reply all
Reply to author
Forward
0 new messages