betabug... Sascha Welter

home english | home deutsch | Site Map | Sascha | Kontakt | Pro | Weblog | Wiki

27 September 2005

Introduction to some Zope security settings

How to declare Roles and Permissions to your Zope Product

Say you have made your own disk based python product in Zope. Now we want to secure some of your methods. We have two classes of users, let's call them "Client" and "Supervisor". We have two sample methods, which we want to secure for who is allowed to view them. Let's call these methods "display_sprockets" and "display_sprocket_orders". Obviously mere Clients can't be allowed to see orders, only Supervisors should. We could click our way through ZMI, but we want this to be as smooth as possible when installing our product. So let's look at a sample setup...

Prepare security declarations

For the setup we decide to build our product with a container object that contains our sprocket information, sales, adminstration, and ordering logic. It contains sprocket subobjects, order database connections and a host of other boring stuff. We are not interested in them right now. Actually we are not interested in them at all, we just want to lock down our sample methods. In our container object (class, product, whatever you care to call it), we prepare to set up the security declarations as we have learned in the Zope Developer Guide:

class sprocketcenter( ObjectManager, PropertyManager, SimpleItem ):
    ... lots of stuff omitted ...

Automatically setup roles

Our two classes of users correspond in Zope parlance to "roles". We will in the working application define our users with their user names and assign them one of those "roles". Now, usually we can go into the Zope Management Interface (ZMI) and assign new "local roles" to any object that behaves like a folder. That is nice and dandy as long as it should be done just once. If there is any chance that we will re-use our product, we should automate that setup. Next time you will have to migrate to a new machine, or need a test setup, you will be thankfull. We will add this snippet of code to add new roles:

localroles = ['Client','Supervisor']
for role in localroles:
    if role not in container.valid_roles():
Where do we have this code? It can either go into a method called "manage_afterAdd(self, item, container)", in which case you can leave those variables in the code snipped as is. (manage_afterAdd is a special name for a method that will be called right after a new instance of your product is added to the Zope database. It's a hook.) Or else you could work it into your constructor method (maybe called something like "manage_add_sprocketcenter"), in which case you will have to juggle "self" and "container" around to fit. What have we done there? We assigned new roles to the "container", which is the folder surrounding our products new instance. We checked that these roles are not already there.

Decide on Permissions

Next thing is, we have to decide on some "Permissions". What we call "Permissions" in Zope, is a name to bundle the rights for something. We then use this Permission to make a link from a group of users (that's users who have the same "role") to a group of methods (who are declared to be accessible with this Permission).

One permission already there is the "View" permission, or the "Change Images and Files" permission. Obviously you can set up some "role" of users to only view stuff, while others can change stuff. But it get's more fine grained. For example the blog product "COREBlog" has permissions for "Add COREBlog Entries", "Moderate COREBlog Entries" and "Manage COREBlog". Obviously this allows for more control of who is allowed to do what. The programmer assigns these permissions to a bunch of methods and in this way she controls who is allowed to do what.

It is good practice to re-use existing permissions wherever they fit, but to invent your own if it makes sense. In our example we will use "View" as a readymade and "Approve Sprocket Orders" as our own custom permission.

Assign permissions to methods

Permissions are assigned to methods. This is usually done right above the "def methodname" line in our class code:

security.declareProtected( 'View', 'display_sprockets' )
def display_sprockets( self, REQUEST ):
    ... more stuff omitted ...

security.declareProtected( 'Approve Sprocket Orders', \
                                'display_sprocket_orders' )
def display_sprocket_orders( self, REQUEST ):
    ... lots of stuff omitted ...
The arguments to declareProtected are the permission name and the name of the method (both as strings). Another option for a permission setting is security.declarePrivate( '_internal_sprocket_calculator' ). This declares that this method is not allowed to be called through the web, for anyone. On the other hand, our declareProtected declaration allows anyone to call this method in their web browser, as long as they belong to a role who has the proper Permission.

Automatically assign Permissions to our Roles

What we are still missing is the link from Permission to Roles. If we do our product with the code as we have it now, nobody will be allowed to do anything but "View". Why? Because "View" is predefined, while our "Approve Sprocket Orders" is a new permission and no role has this Permission yet. We cold go into the ZMI, click on the "Security" tab and assign our "Supervisor" role this new Permission. But again, we want to have this ready for new installations. So we add some more code, in this case in our manage_add_sprocketcenter method, where we set up various stuff of our sprocket center product. (It could of course go into other places too, your choice.)

# ... we assign the newly created object into my_instance ... then:
    ("View",('Client','Supervisor','Manager'), acquire=0)
    ("Approve Sprocket Orders",('Supervisor','Manager'), acquire=0)
In both cases, with "acquire=0", we make sure that no permissions are acquired from folders "above" our own. This is just to make sure that settings outside our application do not affect our security settings. It may not be desirable in all cases. In any case we also helped "Manager" to these permissions, that's the guy who works in the ZMI, usually the Developer... you! So good idea to give you that Permission too or you would not be able to work with the stuff.

So I hope this little overview has been usefull. I had the idea to put this down after answering some questions on IRC. The idea is that this might work as an introduction for you and as a reminder for you and me :-). Be sure to read the Zope Developer Guide and the Zope book to get the complete image.

Posted by betabug at 11:15 | Comments (0) | Trackbacks (0)
ch athens
Life in Athens (Greece) for a foreigner from the other side of the mountains. And with an interest in digital life and the feeling of change in a big city. Multilingual English - German - Greek.
Main blog page
Recent Entries
Best of
Some of the most sought after posts, judging from access logs and search engine queries.

Apple & Macintosh:
Security & Privacy:
Misc technical:
Athens for tourists and visitors:
Life in general:
<< Another Euro Championship won for Greece | Main | Move, move,... moved! (partied too) >>
There are no comments.
You can trackback to:
There are no trackbacks.