Sunday, September 18, 2011

Plone, security and workflows: when rely on Owner role is bad

Once upon a time Plone was a CMS that:
  • was using less roles than today (no Contributor, Reader or Editor and obviously no Site Administrator, the new entry)
  • None of few roles available (Manager, Owner, Reviewer and Member) were hidden from the sharing form
Starting from Plone 3 the sharing view were simplified in two ways:
  • hiding confusing roles (Member and Owner)
  • translating the general meaning of every roles left
In this post I want to talk about the Owner role.

First of all: why it has been hidden from the sharing form? Because this was confusing users a lot.
Who is the Owner of a document? Commonly is a single user, the one you read from the Creator metadata field.

You can manipulate the Owner of a document (you know? If you change the Creator from the edit tab you simply change an information, nothing different as changing the description): you need simply to access http://url/to/document/ownership_form (the link to this page has been removed from the sharing form... I never get why, however it's always there if you need its service).
Also: you can use the very good that also help you to manage the deprecation/removal of a user, transferring ownership of all documents from one to another.

The Dark Side Of The Owner
In a basic Plone installation there's nothing wrong with Owner. It's natural to base part of the document security on the ownership nature and it's right that the document creator still keep special power onto it.
If you use Plone for a open collaboration project this is ok. For example if I publish something on is good that I can always change it later, or retract it.

You must be warned about using workflows that give special powers to Owner only if the organization using Plone is a bit structured. Follow some examples:
  • your Organization is splitted in at least two or more departments and on that division you also create a set of Plone groups. "Department A" can have a personal area where "Department B" can't enter, or simply can't write into.
    What's happen when a user from Department A is moved (let say because get a promotion) to Department B?
  • you give temporary special power to a user that isn't really part of your team and for some times he will be able to contribute, creating some documents. Then you revoke this power but you can't simply also remove the users itself
Using Plone default workflows both cases above can leave you security problems.
Take for example the Simple Publication Workflow, current Plone default workflow: when a content is in the published state the Owner can still modify it. Commonly this is not a problem (if it is, you need a different workflow, but Plone is really good for build them quickly) but if you are in a situation like the two described above the real creator will not be the proper user for having this power on the content.

There isn't only a solution to this problem. From now for simplicity we will consider the first example, where the user that is creator of a document has been moved away.

Perfect solution
The perfect solution is to use because in this way you can:
  • keep the high level ownership (metadata) of the original user. Commonly this is good, you don't want to change the history and destroy proof that the user one time worked in Department A (but know that with this product you can also do this, like cancel documents creation performed by super user used during site creation).
  • give low level ownership (Owner role) to another user that still work in Department A
However the user of this product is not automatically integrated in Plone. Your organization must take care of perform the migration manually every time someone leave one of the departments.
So, even if I name this "the perfect solution", you probably prefer a well Plone workflow integrated ones.

Don't rely on Owner
The other kind of solution is to design and use workflows that don't rely on the Owner role.
Going back to Simple Publication Workflow, you can remove to Owner the power to edit published contents.
Simple Publication Workflow: published state
If this seems enough for you, remember that this will not cover all cases. For example: the user moved to other department must not be able to edit also document he created that are still in private state (because he didn't published them, or a reviewer retracted).

You can't simply remove all permissions to Owner role. Why not? Because you need to keep special power for the Owner in the workflow initial state.
Look again at Simple Publication Workflow, this time to the private state permissions. Who can edit the content? If you remove administrative roles (Manager and Site Administrator), only Editor and Owner are left. You can't be sure that the user is also in a group that will give him Editor role (the "can edit" from the sharing form)... maybe he is simply a Contributor ("can add").
Simple Publication Workflow: private state
So, if you remove the Owner power there your user will not be able anymore to create new contents. He will get Unauthorized error when saving for the first time.

Rely on Editor Role
In facts you can still rely only to Editor role, but for what described above this can be only applied to organizations where you don't have the Owner/Contributor/Editor concepts, but simply the "Author" ones, where is not important who create a document, but all the team matters.

In my customer-types experience, we have many organizations like this. It mean that you can create a content, but it isn't yours; it's always of your group (Office, Department, ...). You create it, but your colleague can edit it later, even if it is still in the private state. The Plone history form take track of all changes done.

When your organization works in this way, for you the Editor and Contributor roles collapse because your users can add new content and edit all contents. You commonly have a group that can manage contents on a folder and all users in this group have both roles.
You don't get Unauthorized errors removing to Owner all permissions because the Contributor will be also an Editor so he will be able to save the content.

What's happen when you are moved away? You loose all Editor powers and the Owner roles is giving you nothing special.

Fake initial state
The solution above is OK, but it can't be used if you want to keep the differences between Editor role and Contributor: you could like the fact that a member of the department can add new contents but also that he isn't able to edit other contents, while an editor user can modify all contents.

In this situation you need to go back to the Owner role. But how use it without falling in the security risk and also give to the user the permission to save the content the first time?

The solution can be add a new initial state: let name it "Being created" (stolen from one of the Poi's workflows).

Added Being Created state
(images above realized using the always great DCWorkflowGraph)

You can leave "Modify portal content" permission to Owner only in this state. The "Post" transition can be "Automatic", instead of "Initiated by user action" so, as soon as the user save the content, it will move in the real initial state: private.

This solution has some limitation: Owner can't be able to edit again the content after saved it (or better: he need also additional roles like Editor).

Fake initial state (lite)
Another solution is very similar to the one above: use again a pre-initial state (let say again "Being created") but leave to the user the choice of move forward. Also, only a Reviewer/Manager power role can move the content back to the pre-initial state, where the Owner can edit it.
The Owner will be able to save it multiple times, the send it, but later can ask permission for edit again. Also: this "Being created" state will be "super private". No other Editor/Reviewer/Reader role will show those contents.

In this way, even if later the user moved to Department B mess up or destroy his old documents, no one will cry. If those document stay there, they will be only a little garbage in your database.

Owner role is a good mate, just know how and when use it!

Saturday, September 10, 2011

Plone and Related Items use for Collections and Folders

This post is about an old but hidden feature of Plone Collections, and how related items are used in some non-standard ways in Plone.

Have you ever used related items for a Plone Collection? Maybe you never used them neither for Folders, so you simply learn that Plone choose to hide related items for some types.

But while for Folders this is simply a choice to make related items as hidden, for Collections is different.

Using related items for Folders
Every AT content schema, after being defined, call a function that is finalizeATCTSchema.

    def finalizeATCTSchema(schema, folderish=False, moveDiscussion=True):
        """Finalizes an ATCT type schema to alter some fields
        schema.moveField('relatedItems', pos='bottom')
        if folderish:
            schema['relatedItems'].widget.visible['edit'] = 'invisible'

The function receive the argument folderish=True for folder content types. As you can see this hide the related items widget when editing (and in this way no simple user can fill the field, so you'll never see it also in view).

But if you fill the field through an external code, the field appear also in Folder's view.

To restore the field normally, simply make the widget visible again.

Using related items for Collections
For Collections the related items field is not hidden but has a special purpose.

You must use it to add additional items to the collection search result, ignoring whatever type of criteria you have set in the Collection.

For example: you can have a Collection that show all contents inside a folder (using a simple well-know path criterion) then you can add to related items of the collection one or more contents outside that folder. The resultset of the collection will include also this content.

Another example: you have a collection that display news items on the portal, then you need to include also an important event. The normal way for Plone is to create a new news item that talk about this event, but you can also use this trick: add the event to related items.

I consider this a good feature. Not common, but two examples above are not so uncommon... but probably you never know of this feature.
However this behavior has some problems.

Plone 4.1 double related items. Seems that there is a bug in recent Plone. On Plone 3 if you were using related items in collections, the related items section was not shown in the Collection view template. Now is... probably a little bug that need to be fixed.

Documentation. No one know of this behavior because this isn't readable anywhere in the Plone UI. The related items field is the same of always. Some suggestion that can help:
  • related items for Collections must be moved on the main fieldset, to highlight that there has some special meaning.
  • related items widget help text for Collections could give some additional information on this behavior.
Related items aren't as normal criterion results. Related items are added to the resultset of the Collection, but:
  • They are not sorted using the choosen sorting criteria
  • They are not mixed with normal results
  • They are always returned first
So related items are always used first, then other results are displayed. This can be good (because you can use this feature to put an high important news as first item of your Collection) but not simple to understand. However this is not a bug... mix related items and other results sorting them all can be complex and expensive for Plone.

How to sort those additional resultset? Recent Plone releases have finally add a way to sort related items (without using external add-ons like before) but using Plone 4.1 trunk the manual sorting is ignored for this feature. Maybe another little but to be fixed?

Can I use related items normally? Giving us this feature will steal us the possibility to use related items for Collections for the common purpose. I don't find this a big problem, however I get this request one time: the customer asked us to be able to use related items for collections in the classic way. Use the same field for a different task is someway strange.

Is this a good feature? I think it can be... however sometime I think that is too complex and simply needs to be removed. Some other times I find it smart.

What you think?