Masquerading As Another User In a Zope 3 Browser View

I had a requirement for Anonymous Users to add content to a designated folder in my Plone site. They submit a form, then the form handling code validates and creates an object. Simple. Or maybe not.

Proxy Roles exist for PythonScripts in Zope 2, but my form was a zope3-style browser view, so that wasn’t an option.

I struggled a lot with this, and after much googling and help from folks on #plone, I came up with this approach, using the AccessControl module that comes with Zope 2.

Here’s what it looks like:

...
from AccessControl.SecurityManagement import newSecurityManager, getSecurityManager, setSecurityManager
from Products.CMFCore.utils import getToolByName
...
class MyViewClass(SomeBaseViewClass):
    # without going into detail here, assume that __init__ is passed a context and request object
    # that are set as instance properties.

    
    def someProcessorMethod(self):
        # I've created a folder called "Special Folder" at the root of my Plone site. 
        
        portal = getToolByName(self.context, 'portal_url').getPortalObject() 
         
        owner = portal['special-folder'].getWrappedOwner()
        
        # stash the existing security manager so we can restore it
        old_security_manager = getSecurityManager()
        
        # create a new context, as the owner of the folder
        newSecurityManager(self.request, user)
        
        try:
            # make the content
            portal['special-folder'].invokeFactory('Document', 
                                                   'anonymous-content-ftw',
                                                   title='Anonymous Content FTW!')
        except:
            # we want to ensure that setSecurityManager gets called
            # in reality you should do more here!
            pass
            
        # restore the original context
        setSecurityManager(old_security_manager)       

That’s all there is to it. The nice thing about this approach is that the user who owns the special folder
could change, and the code will still work.

Be careful not to do this without very seriously considering the security rammifications, and be extra careful about
where you allow the view to be used.

For example, if you had used self.context.getWrappedOwner, and the view was mapped to ‘*’, imagine
the mess that could be made if the wrong anonymous user hit the view on every level of your site. :)

Special thanks to Mario Orlandi for this post, which is where I snagged the idea to use getWrappedOwner(). :)

EDIT: After posting this in #plone, petschki pointed out that I should wrap the content creation in a try block to catch exceptions, so I added that to the example code. This way the security manager will be restored even if there’s an exception during content creation.

Advertisements
This entry was posted in plone. Bookmark the permalink.

One Response to Masquerading As Another User In a Zope 3 Browser View

  1. Gaudenz Steinlin says:

    If you just want to make sure that setSecurityManager is called no matter what happens you should use a finally block and remove the except block. That way the security manager is restored and afterwards the exception is reraised.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s