[Zope3-checkins] CVS: Zope3/src/zope/app/publisher/browser - globalbrowsermenuservice.py:1.4

Jim Fulton jim@zope.com
Mon, 30 Dec 2002 18:31:51 -0500


Update of /cvs-repository/Zope3/src/zope/app/publisher/browser
In directory cvs.zope.org:/tmp/cvs-serv15930/zope/app/publisher/browser

Modified Files:
	globalbrowsermenuservice.py 
Log Message:
Added the ability to specify a permission for a menu item. This
allows menus to be displayed more quickly, since we can do the
security check directly, rather than having to traverse to each item,
which can get expensive.


=== Zope3/src/zope/app/publisher/browser/globalbrowsermenuservice.py 1.3 => 1.4 ===
--- Zope3/src/zope/app/publisher/browser/globalbrowsermenuservice.py:1.3	Fri Dec 27 18:32:16 2002
+++ Zope3/src/zope/app/publisher/browser/globalbrowsermenuservice.py	Mon Dec 30 18:31:20 2002
@@ -12,16 +12,24 @@
 #
 ##############################################################################
 
-from zope.app.interfaces.publisher.browser import IBrowserMenuService
-from zope.interfaces.configuration import INonEmptyDirective
-from zope.interfaces.configuration import ISubdirectiveHandler
+from zope.exceptions import DuplicationError, Unauthorized, Forbidden
+
 from zope.configuration.action import Action
+
 from zope.interface.type import TypeRegistry
-from zope.exceptions import DuplicationError, Unauthorized, Forbidden
-from zope.app.pagetemplate.engine import Engine
-from zope.app.publication.browser \
-     import PublicationTraverser
+
+from zope.interfaces.configuration import INonEmptyDirective
+from zope.interfaces.configuration import ISubdirectiveHandler
+
+from zope.security.checker import CheckerPublic
+from zope.security.securitymanagement import getSecurityManager
+
+from zope.app.security.permission import checkPermission
+
 from zope.app.component.metaconfigure import handler
+from zope.app.interfaces.publisher.browser import IBrowserMenuService
+from zope.app.pagetemplate.engine import Engine
+from zope.app.publication.browser import PublicationTraverser
 
 class GlobalBrowserMenuService:
     """Global Browser Menu Service
@@ -42,8 +50,9 @@
 
         self._registry[menu_id] = TypeRegistry()
 
-    def menuItem(self, menu_id, interface,
-                 action, title, description='', filter_string=None):
+    def menuItem(self, menu_id, interface, action, title,
+                 description='', filter_string=None, permission=None,
+                 ):
 
         registry = self._registry[menu_id]
 
@@ -52,8 +61,14 @@
         else:
             filter = None
 
+        if permission:
+            if permission == 'zope.Public':
+                permission = CheckerPublic
+            else:
+                checkPermission(None, permission)
+
         data = registry.get(interface) or []
-        data.append((action, title, description, filter))
+        data.append((action, title, description, filter, permission))
         registry.register(interface, data)
 
     def getMenu(self, menu_id, object, request, max=999999):
@@ -62,9 +77,10 @@
 
         result = []
         seen = {}
+        sm = getSecurityManager()
 
         for items in registry.getAllForObject(object):
-            for action, title, description, filter in items:
+            for action, title, description, filter, permission in items:
 
                 # Make sure we don't repeat a specification for a given title
                 if title in seen:
@@ -85,7 +101,14 @@
                     if not include:
                         continue
 
-                if action:
+                if permission:
+                    # If we have an explicit permission, check that we
+                    # can access it.
+                    if not sm.checkPermission(permission, object):
+                        continue
+
+                elif action:
+                    # Otherwise, test access by attempting access
                     try:
                         v = traverser.traverseRelativeURL(
                             request, object, action)
@@ -128,9 +151,10 @@
         )]
 
 def menuItemDirective(_context, menu, for_,
-                      action, title, description='', filter=None):
+                      action, title, description='', filter=None,
+                      permission=None):
     return menuItemsDirective(_context, menu, for_).menuItem(
-        _context, action, title, description, filter)
+        _context, action, title, description, filter, permission)
 
 
 class menuItemsDirective:
@@ -142,14 +166,16 @@
         self.menu = menu
         self.interface = _context.resolve(for_)
 
-    def menuItem(self, _context, action, title, description='', filter=None):
+    def menuItem(self, _context, action, title, description='',
+                 filter=None, permission=None):
+        
         return [
             Action(
               discriminator = ('browser:menuItem',
                                self.menu, self.interface, title),
               callable = globalBrowserMenuService.menuItem,
               args = (self.menu, self.interface,
-                      action, title, description, filter),
+                      action, title, description, filter, permission),
               ),
                 ]