[Checkins] SVN: grok/trunk/doc/ Added Luis' permissions tutorial.

Uli Fouquet uli at gnufix.de
Wed Aug 22 23:55:53 EDT 2007


Log message for revision 79154:
  Added Luis' permissions tutorial.

Changed:
  U   grok/trunk/doc/grok2html.py
  A   grok/trunk/doc/minitutorials/permissions.txt

-=-
Modified: grok/trunk/doc/grok2html.py
===================================================================
--- grok/trunk/doc/grok2html.py	2007-08-23 02:35:29 UTC (rev 79153)
+++ grok/trunk/doc/grok2html.py	2007-08-23 03:55:52 UTC (rev 79154)
@@ -178,6 +178,9 @@
     rest_files.append(RestFile('xmlrpc', 
                               os.path.join(source_dir, 'minitutorials', 'xmlrpc.txt'),
                               os.path.join(www_dir, 'minitutorials', 'xmlrpc.html')))
+    rest_files.append(RestFile('permissions', 
+                              os.path.join(source_dir, 'minitutorials', 'permissions.txt'),
+                              os.path.join(www_dir, 'minitutorials', 'permissions.html')))
     rest_files.append(RestFile('zc.buildout', 
                   'http://svn.zope.org/*checkout*/zc.buildout/trunk/doc/tutorial.txt',
                   os.path.join(www_dir, 'minitutorials', 'buildout.html')))

Added: grok/trunk/doc/minitutorials/permissions.txt
===================================================================
--- grok/trunk/doc/minitutorials/permissions.txt	                        (rev 0)
+++ grok/trunk/doc/minitutorials/permissions.txt	2007-08-23 03:55:52 UTC (rev 79154)
@@ -0,0 +1,269 @@
+===========================
+Newbie Permissions Tutorial
+===========================
+
+:Author: Luis De la Parra
+
+Intended Audience:
+
+  * Python Developers
+
+  * Zope 2 Developers
+
+  * Zope 3 Developers
+
+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, Grok
+allows access to everything unless you explicitly restrict it. The
+authorization checks here are done based on the ``Views`` used to
+access (display/manipulate) the content.
+
+
+Setup
+-----
+
+.. code-block:: python
+
+     #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:
+
+
+.. code-block:: python
+
+     # 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, including 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: %s%s%s' % (contact.first_name,
+                                         contact.last_name,
+                                         contact.email)
+
+*Note* The ``grok.define_permission()`` vanished from Grok *after*
+release 0.10. The current subversion copy of Grok does not provide
+it anymore. Instead you can now use the component base class
+``grok.Permission``. Roughly, it works like this:
+
+.. code-block:: python
+
+     class ViewContactsPermission(grok.Permission):
+         grok.name('mysite.ViewContacs')
+         grok.title('View Contacts') # optional
+
+
+If you are using ``grokproject`` this change currently does not affect
+your installation. In this case use ``grok.define_permission`` as
+described above.
+
+
+
+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 to create new contacts,
+you could grant them the permissions when the user account is 
+created:
+
+.. code-block:: python
+
+     from zope.app.security.interfaces import IAuthentication
+     from zope.app.securitypolicy.interfaces import IPrincipalPermissionManager
+
+     def addUser(username, password, realname):
+         """Create a new user.
+
+         create a new user and give it the authorizations,
+         ``ViewContacts`` and ``EditContacts``. This example assumes
+         you are using a Pluggable Authentication Utility (PAU) /
+         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 its children. The
+above example grants ``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
+
+.. code-block:: python
+
+     class AddContact(grok.AddForm):
+         """Add a contact.
+         """
+
+         # 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')
+
+         #automagically generate form fields
+         form_fields = grok.AutoFields(IContactInfo) 
+
+         @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):
+         """Edit a contact.
+         """
+
+         #only users with permission 'mysite.EditContacts' can use this
+         grok.require('mysite.EditContacts') 
+
+         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.
+
+.. code-block:: python
+
+     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]
+
+.. code-block:: python
+
+     role_man = IRolePermissionManager(grok.getSite())
+
+As an example, let's group all permissions in two roles: one for
+normal site members, and one for administrators:
+
+.. code-block:: python
+
+     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 of who the
+creator is.
+
+.. code-block:: python
+
+     role_man = IPrincipalRoleManager(context)
+     role_man.assignRoleToPrincipal('mysite.Administrator', principalID)
+
+



More information about the Checkins mailing list