[CMF-checkins] CVS: CMF/CMFCore - ActionsTool.py:1.27.10.2 TypesTool.py:1.37.4.2

Chris McDonough chrism@zope.com
Fri, 26 Jul 2002 13:02:10 -0400


Update of /cvs-repository/CMF/CMFCore
In directory cvs.zope.org:/tmp/cvs-serv10443

Modified Files:
      Tag: CMF-1_3-branch
	ActionsTool.py TypesTool.py 
Log Message:
Merge two patches in from trunk:

1.  Cause ActionsTool and TypesTool to return "unmolested" actions
    dictionary from listFilteredActionsFor.  Editing actions via the
    types tool does not destroy un-web-editable entries in a site's
    actions dictionary.

2.  Cause TypesTool's isConstructionAllowed method to not mask construction
    exceptions with Unauthorized.  Also removed the 'raise_exc' argument
    to isConstructionAllowed (it was never part of the interface).
    isConstructionAllowed now never raises an exception.  If an error
    is encountered, a log message is written to the stupid log.


=== CMF/CMFCore/ActionsTool.py 1.27.10.1 => 1.27.10.2 ===
 from Expression import Expression, createExprContext
 from ActionInformation import ActionInformation, oai
 from ActionProviderBase import ActionProviderBase
-
+from TypesTool import TypeInformation
 
 class ActionsTool(UniqueObject, OFS.Folder.Folder, ActionProviderBase):
     """
@@ -200,29 +200,28 @@
         if object is not None:
             base = aq_base(object)
             types_tool = getToolByName( self, 'portal_types' )
-            ti = types_tool.getTypeInfo( object )
-            if ti is not None:
-                defs = ti.getActions()
-                if defs:
-                    c_url = object.absolute_url()
-                    for d in defs:
-                        a = d['action']
-                        if a:
-                            url = c_url + '/' + a
-                        else:
-                            url = c_url
-                        actions.append({
-                            'id': d.get('id', None),
-                            'name': d['name'],
-                            'action': d['action'],
-                            'url': url,
-                            'permissions': d['permissions'],
-                            'category': d.get('category', 'object'),
-                            'visible': d.get('visible', 1),
-                            })                
+            # we might get None back from getTypeInfo.  We construct
+            # a dummy TypeInformation object here in that case (the 'or'
+            # case).  This prevents us from needing to check the condition.
+            ti = types_tool.getTypeInfo( object ) or TypeInformation('Dummy')
+            defs = ti.getActions()
+            url = object_url = object.absolute_url()
+            for d in defs:
+                # we can't modify or expose the original actionsd... this
+                # stems from the fact that getActions returns a ref to the
+                # actual dictionary used to store actions instead of a
+                # copy.  We copy it here to prevent it from being modified.
+                d = d.copy()
+                d['id'] = d.get('id', None)
+                if d['action']:
+                    url = '%s/%s' % (object_url, d['action'])
+                d['url'] = url
+                d['category'] = d.get('category', 'object')
+                d['visible'] = d.get('visible', 1)
+                actions.append(d)
+
             if hasattr(base, 'listActions'):
                 self._listActions(append,object,info,ec)
-                
 
         # Reorganize the actions by category,
         # filtering out disallowed actions.


=== CMF/CMFCore/TypesTool.py 1.37.4.1 => 1.37.4.2 ===
 from ActionProviderBase import ActionProviderBase
 from ActionInformation import ActionInformation
 from Expression import Expression
-from zLOG import LOG, WARNING
+from zLOG import LOG, WARNING, ERROR
+import sys
 
 from CMFCorePermissions import View, ManagePortal, AccessContentsInformation
 
@@ -306,19 +307,20 @@
         actions = []
         for idx in range(len(self._actions)):
             s_idx = str(idx)
-            action = {
-                'id': str(properties.get('id_' + s_idx, '')),
-                'name': str(properties.get('name_' + s_idx, '')),
-                'action': str(properties.get('action_' + s_idx, '')),
-                'permissions':
-                (properties.get('permission_' + s_idx, ()),),
-                'category': str(properties.get('category_' + s_idx, '')),
-                'visible': not not properties.get('visible_' + s_idx, 0),
-                }
+            action = self._actions[idx].copy()
+            action.update( {
+                    'id': str(properties.get('id_' + s_idx, '')),
+                    'name': str(properties.get('name_' + s_idx, '')),
+                    'action': str(properties.get('action_' + s_idx, '')),
+                    'permissions':
+                    (properties.get('permission_' + s_idx, ()),),
+                    'category': str(properties.get('category_' + s_idx, '')),
+                    'visible': not not properties.get('visible_' + s_idx, 0),
+                    } )
             if not action['name']:
                 raise ValueError('A name is required.')
-            actions.append(action)
-        self._actions = tuple(actions)
+            actions.append( action )
+        self._actions = tuple( actions )
         if REQUEST is not None:
             return self.manage_editActionsForm(REQUEST, manage_tabs_message=
                                                'Actions changed.')
@@ -444,28 +446,43 @@
     #
     #   Agent methods
     #
-    def _getFactoryMethod(self, container, raise_exc=0):
+    def _getFactoryMethod(self, container):
         if not self.product or not self.factory:
-            return None
+            raise ValueError, ('Product factory for %s was undefined' %
+                               self.getId())
+        p = container.manage_addProduct[self.product]
+        
+        m = getattr(p, self.factory, None)
+        if m is None:
+            raise ValueError, ('Product factory for %s was invalid' %
+                               self.getId())
+        if getSecurityManager().validate(p, p, self.factory, m):
+            return m
+        raise Unauthorized, ('Cannot create %s' % self.getId())
+
+    def _queryFactoryMethod(self, container, m=None):
         try:
-            p = container.manage_addProduct[self.product]
-            m = getattr(p, self.factory, None)
-            if m is not None:
-                if getSecurityManager().validate(p, p, self.factory, m):
-                    return m
-            return None
-        except: # only raise if allowed
-            if raise_exc:
-                raise
-            return None
+            if self.product and self.factory:
+                p = container.manage_addProduct[self.product]
+                t = getattr(p, self.factory, None)
+                if getSecurityManager().validate(p, p, self.factory, t):
+                    m = t
+        except:
+            LOG('Types Tool', ERROR, '_queryFactoryMethod raised an exception',
+                error=sys.exc_info())
+        return m
 
     security.declarePublic('isConstructionAllowed')
-    def isConstructionAllowed ( self, container, raise_exc=0):
+    def isConstructionAllowed ( self, container ):
         """
-        Does the current user have the permission required in
-        order to construct an instance?
+        a. Does the factory method exist?
+
+        b. Is the factory method usable?
+
+        c. Does the current user have the permission required in
+        order to invoke the factory method?
         """
-        m = self._getFactoryMethod(container, raise_exc)
+        m = self._queryFactoryMethod(container)
         return (m is not None)
 
     security.declarePublic('constructInstance')
@@ -476,10 +493,8 @@
         """
         # Get the factory method, performing a security check
         # in the process.
-        m = self._getFactoryMethod(container, raise_exc=1)
 
-        if m is None:
-            raise Unauthorized, ('Cannot create %s' % self.getId())
+        m = self._getFactoryMethod(container)
 
         id = str(id)