Forum OpenACS Development: listbuilder: permissions on columns

I have seen two implementations for providing permissions on columns of tables, none of which use acs-permissions but their own functional permission system. ACS Permissions is used to limit the data, but not the access to the functionality (hope this distinction makes sense, if you look at table columns).

Either way, I was wondering if anyone else has done permissions on columns in a list? We have in contacts a cludge which allows us to display columns based on a search (so we can dynamically extend columns in listbuilder) and then give permissions to the search.

If we were to implement this in a generic way for listbuilder, what would be the way (apart from a flag "-use_column_permissions")?

Apart from the business uses (like financial data tables) I could imagine that e.g. the members table in .LRN could have more columns shown if a professor views the table. But how would you give permissions on those columns to the professors and maybe only to some of them to the teaching assistent. And do this in a generic way...

Posted by Dave Bauer on
I think it would make more sense to create a "view" object which was a list of columns to display, and grant permissions on that. The view could be either hard coded in the tcl file by the developer, or you could allow user creation of views if you wanted.

I am going to start work on a saved view feature for listbuilder soon and I think you could build on that. It will save all features of the current state of a list, ie: fitlers, sorting, grouping, and which columns are displayed.

I don't think it makes sense to try to grant permissions on the actual columns, but just create a view object that contains a list of 1) diplayed columns and 2) hidden columns that may be choosen to be displayed.

Posted by Andrew Piskorski on
I've never actually done it, but I've long had a use case for something like that too.

At work, we have various pages that implement "features". Some "features" might be read access to particular columns, but others are more arbitrary - a "feature" might be the ability to execute certain Tcl procs or whatever. Right now we control access to the various features in an ugly, quick and dirty style which makes it very hard to change or verify just who has permission to do what.

A much nicer system would be to, as Dave essentially described above, model each "feature" as an acs_object row, and then add/remove the usual read/write permissions to that object. I think the only other major design question is how to map the conceptual "features" to the acs_objects. Probably I would stick a Tcl call onto each page declaring that "this page provides feature X", but it would also be possible to track the page to feature mapping in the RDBMS.

I don't think this is quite the same as your column display permissioning case, Malte, but it seems close enough that I'm definitely curious about whatever solution you come up with.

Posted by Malte Sussdorff on
I talked this through a little bit more with guys at Quest and one way to handle this was to use arbitrary objects just as you suggest Andrew. This way you can have a call in your page or TCL proc which checks for permission on the function object , though we would have to make sure that the function objects have a unique label.

Driving this further for listbuilder I was then thinking that each list has a name, so we could provide the permission on an arbitrary object with the name "list.$list_name.$element_name" and provide a permission interface for an admin to create the object and to provide permissions to it.

This could actually be done fairly quickly both from a UI as well from a code point of view.

In listbuilder UI you would provide for Admins a link "provide permissions on columns", which would go to a page which takes as parameters the name of the list and the elements available in this list. On this page you have the ability (for each of the possible elements / columns) to create the object or give permissions on it. It would inherit the permissions from the package.

In the listbuilder code we could then have the elements that are to be displayed and we would run a check against this permission (does the user have functional permission on this column), if listbuilder is called with "has_column_permission_p"). If the object does not exist he has permission (unless you want to run a really restricted site), which is probably the case most of the time, so you would run a query which gives you the list of possible object names with ids and returns the ones which exist. You can probably cache that and flush the cache once you create a new object.

This being said I am curious how the view will work out and how the UI for that will look like, because I dont understand it fully yet.

We have something called "Saved searches" in contacts, which we will bring into AMS, allowing you to create a search with certain attributes to prefiled to limit the number of results returned and the ability to add columns to the table view, either by having a direct attribute of the attribute type, or by defining extended columns which you join in SQL (e.g. the turnover of a project, where the turnover is calculated in a subselect from the ecommerce tables). We have permissions on that so if this is what you envision Dave, then it would be good to talk this through with Matthew who is going to work on getting this out of contacts and into AMS, working directly off the acs-attributes table.

Posted by Dave Bauer on

Yes me "view" idea is very similar to saved searches in contacts.

Its a little different in that its keyed on the list, not the object attributes.

I hesitate to expose the object types, attributes, and permissions interface for this kind of thing. My vision is more abstract, and hopefully easier to use.

The idea is to let admins see all the columns, and then choose which columns are contained in a view and set permissions on the views.

I think its overkill to individually permission every column. Maybe there is an applicaiton for that as well, but it seems like a usability problem.

Posted by Malte Sussdorff on
Dave, I think we should figure a way to come up with a solution that suits both (contacts/AMS and yours). Because if it is keyed to a list in listbuilder or keyed to an object_type or multiple object types should not matter (that much) and be it for the simple reason that we could have a simple list which displays all objects of an object type. And thats basically what contacts does.

At the moment here is my idea (very theoretical): We have a package / place where we can say: This are the columns available and please create a view out of these columns. Basicly that is what we do in AMS (after all it is not necessarily keyed to the attributes, that is just and example how we use it).

What I want to have in addition for this view: Filter by element, meaning, you can create a view which might contain prefilled in filter values but also define one element as searchable by the user using the view. This way the admin, when creating the view, can preset certain filters. And additionally he can say "These are filters the user is allowed to use". Do we have textbox filters in listbuilder?

Do you have a timeline when you want to work on that?

Posted by Dave Bauer on
Filter by form already exists in listbuilder. This is basically what I'll be extending. I added a new parameter to template::list::create and it builds a form based on all the filter definitions.

We can add a "displayed_columns" and "hidden_columns" built in filters to go along with the other built in filters.

To make it simple I am going to just present all filter options for my application. In your case you need to have two pages. One for admins to build a view from all options, then a user visible page that does not have the filters in ad_page_contract, and only allows selecting a pre-defined view from the list they are allowed to see (of if there's only one, just show that automatically.)

The thing I need to add is a saved_list_view object. Right now you can't save the filters from a form. This is going to be very simple. Right now it just stores all the filter criteria in a list in a session property. All we need to do to save it is create an object and store the list in the database.

Posted by Tom Jackson on
Hmmm, interesting ideas. I hate to always look at problems via my query-writer package, so please try to ignore that, I'm not wishing anyone to pick it up and use it.

Actually, query-writer has never been used to build views, do selects, etc. as I have always thought it nearly impossible to pass through the expressiveness of a nice SQL query to Tcl or any other language. One thing query-writer starts with which is helpful is a list of columns available for certain operations on objects: new, set, del, rst (reset). A view operation/permission is easy to add. This simply provides a method of tagging which columns of a defined object are available to a certain qw group (tied to a relational segment). qw groups span objects, and in general there is an admin group, usually getting all columns, and a site member group, getting a developer defined subset.

The concept is that the developer can establish in one place what a particular group of users can do with a set of objects without the need to write new pages for each group.

Ditching query-writer, you can get the same effect with tying a list of object/columns to a rel segment, and add users to the rel segment, or just re-use an existing rel segment that is already related to the package making use of list builder. Query-writer reuses main site members and site wide admins for the default access controls.

So the only thing I'm really suggesting here is to use a proxy object, same as for the features object, but assign permissions based upon the type of membership in a rel segment.