Allowing Anonymous Users to Add Content

by Tom "Spanky" Kapanka last modified Dec 30, 2008 03:02 PM
I had the need for Anonymous Plone users to add, edit, and save a specific content type in a specific location (folder) and couldn't find any resources, thus this quick HowTo.

Problem at Hand:

By default Anonymous users cannot create content in Plone. For one step in my Product, I needed to allow this, but only in the context of a particular folder. I needed to run a method to do so, as well.

DANGER! DANGER!

This HowTo is published WITHOUT ANY WARRANTY without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. It has not been security audited and might be grossly inaccurate, but I put it out there so that other who know more than me can comment, correct, and keep this information public and current. This is one of my first solo ventures into managing security and I hope that I am approaching it correctly!

All of the ZMI stuff I mention below should be done programmatically instead. I only outline it this way because it gives instant results. As I actualize these changes into code, I can add them as examples.

This HowTo uses a fictitious product called MyProduct and an equally bogus Content Type called MyType.

The first thing I did was add a "permissions.py" file to the root folder of my product. In it, I defined some new permissions for it:

ADD_MYTYPE_PERMISSION = "MyProduct: Add MyType"

EDIT_MYTYPE_PERMISSION = "MyProduct: Edit MyType"

This type has its own workflow associated with it. It is called "MyWorkflow". I went to MyWorkflow in the portal_workflow tool in the ZMI. Click the "States" tab from within the workflow, look for the default state, and click on it. You should see the "Permissions" tab. Click on that and you will see a "permissions managed by this workflow" link at the top. Click there. You should be presented with a dropdown list of permissions in the portal. My Product was developed from UML using ArchGenXML so a permission of "Add MyProduct Content" was created by default. In __init__.py I find the following code:

ADD_CONTENT_PERMISSION = '''Add MyProduct content'''

...

utils.ContentInit( PROJECTNAME + Content, content_types = content_types, permission = ADD_CONTENT_PERMISSION, extra_constructors = constructors, fti = ftis, ).initialize(context)

This permission may be too broad, but I am experimenting with it. Regardless, I chose this permission from the drop down and clicked Add.

Workflow:

Going back to the Permissions tab (by clicking all around again), you should now see this permission listed with checkboxes under all of the roles in the site. I checked the boxes for Anonymous, Manager, and Owner and then Save.

Container:

Now I created a folder called "my_folder" at the root of my Plone. This is the folder I want Anonymous users to be able to create and save MyType types in. Once again, back in the ZMI (I know, I know) navigate to this folder and click the "Security" tab.

Under roles in the giant grid of checkboxes, click "Anonymous" since this is the only role we are dealing with. Now, Command-click (or alt-click for PC users) to add the following permissions to the Anonymous role:

  • Access contents information
  • Modify portal content
  • MyProduct: Add MyType
  • MyProduct: Edit MyType
  • View (should already be selected)

Again, I'm not sure if this is too broad or accomplished easier/better, but when I find out, I will update this.

Method/Tool:

Now, to make things more difficult, my type was created programmatically from a method in a type in MyProduct. I did this because there were some special things that need to happen on creation and this method is reused elsewhere for the same activity. Anonymous users can't access this method so you need to enable that. Be sure this method doesn't do anything you wouldn't want anyone on your site to do, since you are enabling anonymous access to it. My method is called by an Action, but at one point I had tried to do this from a skin script which I gave a Proxy Role of Manager to (I ran into problems this way, and try to avoid skin scripts as solutions anyways). I'm not sure which is the more accepted or the proper way, so please help steer me in the right direction!

Anyhow in my type, we will find the following code:

from AccessControl import ClassSecurityInfo
from Products.MyProduct.permissions import *

...

class MyType(BaseContent): security = ClassSecurityInfo()

...

security.declareProtected(ADD_MYTYPE_PERMISSION, "make_myType") def make_myType(self): """ docstring of course """

...

security.setPermissionDefault(ADD_MYTYPE_PERMISSION, ("Manager","Anonymous"))

...

Schema:

When I was attempting to instantiate an instance of this class, I got errors about not being able to render the fields. So I went to the schema of this type and added some attributes to allow the fields to be edited.

from Products.MyProduct.permissions import EDIT_MYTYPE_PERMISSION

...

# within the schema definition, I did this for each field to be # edited by Anonymous, all others were hidden, like in the second # string field below

StringField("StringInput", write_permission = EDIT_MYTYPE_PERMISSION, widget = StringWidget( description = "desc" label = "String Input" ) ),

StringField("StringHidden", widget = StringWidget( visible = {"edit":"invisible", "view":"visible",}, description = "desc2" label = "String Hidden" ) ),

Wrap Up:

When I did all of this, Anonymous users were able to add, and subsequently save, the MyType content type in this folder. So far, I have not gone beyond this in terms of testing, but I will be doing so. As I said before, I welcome feedback, corrections, and criticisms on this! (please be nice, this is my first time)

Problems:

Since Anonymous users can now work with this content type, they can potentially get to all of the instances of that type in that folder, even if they were not created by them, since, I believe, Anonymous users are indistinguishable from each other. That means people can potentially edit any instance.

Also, I have not verified that Anonymous users can now create this type in other locations, or other types in this location, or other such mayhem. I will be testing as much as I can but this was the result of my ZMI-based experimentation.

Permissions might need to be more workflow-centric rather than on the folder?

PLEASE give me corrections and guidance, I will update this document to be as accurate as I learn. Thanks and I hope this helps someone along the way!

~Spanky

Filed under: