[Grok-dev] HEADS UP: grok.define_permission gone in favor of grok.Permission

Sebastian Ware sebastian at urbantalk.se
Wed Aug 22 09:42:47 EDT 2007


I just want to remind about the permissions tutorial... it needs to  
be updated :)

Mvh Sebastian


Luis De la Parra <lparrab at gmx.net>:

Hi all,

I'm re-opening the thread on security/permissions from beginning of  
july.
Sebastian did proof-read it and made some comments on it, but I was  
over 3
weeks with tons of work and pretty much off-line, so I'm just  
starting to
catch up with stuff..

here it goes again, with sebastian's comments addressed..
cheers. luis

===========================
Newbie Permissions Tutorial
===========================

Introduction
-------------
Zope3 and Grok come with authorization capabilities out of the box.  
While a
vanilla Zope3 application protects all content by default and performs
authorization checks on the content objects themselves. On the other  
hand,
Grok allows access to everything unless you explicitly restrict it,  
and the
authorization checks are done on the Views used to access
(display/manipulate) the content.


Setup
-----
::
     #contact.py
     from zope import component, interface, schema
     import grok

     class IContactInfo(interface.Interface):
         """ Interface/Schema for Contact Information """
         first_name = schema.Text(title=u'First Name')
         last_name  = schema.Text(title=u'Last Name')
         email      = schema.Text(title=u'E-mail')


     class ContactInfo(grok.Model):
         interface.implements(IContactInfo)

         first_name = ''
         last_name  = ''
         email = ''


     class ViewContact(grok.View)
         """ Display Contact Info, without E-mail. Anyone can use  
this view,
             even unauthenticated users over the internet
         """
         def render(self):
             contact = self.context
             return 'Contact: ' + contact.first_name + contact.last_name


Defining Permissions and restricting access
-------------------------------------------
As all Views in Grok default to public access, anyone can use the
ViewContact-view defined above. If you want to restrict access to a  
view,
you have to explicitly protect it with a permission.

::

#   Define Permissions. This can be any string, but it is
#   strongly recommended to make them unique by prefixing
#   them with the application name

     grok.define_permission('mysite.ViewContacts')
     grok.define_permission('mysite.AddContacts')
     grok.define_permission('mysite.EditContact')


     class ViewContactComplete(grok.View)
         """ Display Contact Info, inclusive email.
             Only users which have the permission 'mysite.ViewContacts'
             can use this view
         """"
         grok.require('mysite.ViewContacts')  #this is the security
declaration

         def render(self):
             contact = self.context
             return 'Contact: ' + contact.first_name +  
contact.last_name +
contact.email



Granting Permissions
--------------------

You can grant permissions to principals with a "PermissionManager". For
example, if all registered users
should have permission to view contact details and create new  
contacts, you
could grant them the permissions when the user account is created:

::
     from zope.app.security.interfaces import IAuthentication
     from zope.app.securitypolicy.interfaces import
IPrincipalPermissionManager

     def addUser(username, password, realname):
         # create a new user and give him the authorizations  
ViewContacts and
         # EditContacts. This example assumes you are using a
         # Pluggable Authentication Utility / PrincipalFolder, which  
you have
         # to create and register when creating your Application
         pau = component.getUtility(IAuthentication)
         principals = pau['principals']
         principals[username] = InternalPrincipal(username, password,
                                                               realname)

         # grant the user permission to view and create contacts
         # everywhere in the Site
         permission_man = IPrincipalPermissionManager( grok.getSite() )

         # NOTE that you need a principal ID. If you are  
authenticating users
         # with a PAU this is normally the user name prepended with the
         # principals-folder prefix (and  the PAU-prefix as well, if  
set)
         permission_man.grantPermissionToPrincipal 
('mysite.ViewContacts',
                                               principals.prefix +  
username)
         permission_man.grantPermissionToPrincipal('mysite.AddContacts',
                                              principals.prefix +  
username)




Permissions are set for the context for which the PermissionManager is
created, and --if not explicitly overridden-- all it's children. The  
above
example gives the 'View' and 'Add' permissions for the complete site,
unless a folder down in the hierarchy revokes the permission.

If you want users to be able to edit only their own ContactInfos, you  
have
to give them the 'Edit' permission only within the context of the
ContactInfo-object itself

::

     class AddContact(grok.AddForm):
         # only users with permission 'mysite.AddContacts' can use this.
         # NOTE that if you don't protect this Form, anyone --even  
anonymous/
         # unauthenticated users-- could add Contacts to the site
         grok.require('mysite.AddContacts')

         form_fields = grok.AutoFields(IContactInfo) #automagically  
generate
form fields

         @grok.action('Create')
         def create(self, **kw):
              # Create and Add the ContactInfo to our context  
(normally a
              # Folder/Container)
             contact = ContactInfo()
             self.applyData(contact, **kw)
             self.context[contact.first_name] = contact

             # Grant the current user the Edit permission, but only  
in the
             # context of the newly created object
             permission_man = IPrincipalPermissionManager(contact)
             permission_man.grantPermissionToPrincipal 
('mysite.EditContacts',
                                                  
self.request.principal.id)

             self.redirect(self.url(contact))



     class EditContact(grok.EditForm):
         grok.require('mysite.EditContacts') #only users with
permission 'mysite.EditContacts' can use this

         form_fields = grok.AutoFields(IContactInfo)

         @grok.action('Save Changes')
         def edit(self, **data):
             self.applyData(self.context, **data)
             self.redirect(self.url(self.context))


Checking Permissions
--------------------
[FIXME How to check permissions in a page template and from python code?
User Interfaces should not contain any links/actions which users cannot
access / for which users don't have authorizations]


Defining Roles
----------------
Permissions can be grouped together in Roles, which makes granting  
all the
permissions for a particular type of user much easier.

::
     from zope.app.securitypolicy.interfaces import  
IPrincipalRoleManager
     from zope.app.securitypolicy.interfaces import  
IRolePermissionManager

[FIXME: Roles have to be first defined / registered as a local  
Utility????]
[FIXME: As of July 2007, there has been some discussion on the  
mailing list
about simplifying role definitions. This section may be outdated]

     role_man = IRolePermissionManager( grok.getSite() )

As an example, let's group all permissions in two roles: one for  
normal site
members, and one for admins

::
     role_man.grantPermissionToRole('mysite.ViewContacts',  
'mysite.Member')
     role_man.grantPermissionToRole('mysite.AddContacts',   
'mysite.Member')

role_man.grantPermissionToRole('mysite.ViewContacts',  
'mysite.Administrator')
role_man.grantPermissionToRole('mysite.AddContacts',   
'mysite.Administrator')
role_man.grantPermissionToRole('mysite.EditContacts',  
'mysite.Administrator')

Now, if the context here is the Site/Application, users with the
Administrator role can edit all ContactInfos, regardless who the  
creator is

     role_man = IPrincipalRoleManager(context)
     role_man.assignRoleToPrincipal('mysite.Administrator', principalID)



22 aug 2007 kl. 15.19 skrev Jan-Wijbrand Kolman:

> Hi,
>
>
> This is an important heads up!
>
> As has been discussed before (http://thread.gmane.org/ 
> gmane.comp.web.zope.grok.devel/1637/) the define_permission is now  
> gone in favor of the grok.Permission component base class.
>
> So, from now on, instead of:
>
>   grok.define_permission('grok.NicePermission')
>
> you do:
>
>   class NicePermission(grok.Permission):
>       grok.name('grok.NicePermission')
>       grok.title('Title for Nice Permission') # optional
>
> As an added bonus (and the reason for this refactoring) there's now  
> an easy way to define roles:
>
>   class NiceRole(grok.Role):
>       grok.name('grok.NiceRole')
>       grok.title('Title for Role') # optional
>       # multiple permissions ids allowed here
>       grok.permissions('grok.NicePermission', ...)
>
> Writing this post reminds me of updating CHANGES.txt - I will do so  
> rightaway...
>
>
> kind regards,
> jw
>
> _______________________________________________
> Grok-dev mailing list
> Grok-dev at zope.org
> http://mail.zope.org/mailman/listinfo/grok-dev



More information about the Grok-dev mailing list